Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

AI agents find $4.6M in blockchain smart contract exploits- 1815

Anthropic    Reference →Posted 3 Months Ago
  • The impact of security vulnerabilities is hard to price, unless you're dealing with smart contract funds. So, Anthropic decided to see how well AI could find vulnerabilities in smart contracts. Smart contracts are also minimal with a well-defined set of security definitions, making them ideal for AI capabilities.
  • First, they created a benchmark of 405 smart contract vulnerabilities across 3 EVM-compatible chains from 2020 to 2025. The agent was given a large set of tools via MCP and a 60-minute time limit. They evaluated the success of this across 10 different models, resulting in exploits for 51% of the vulnerabilities. They also evaluated a set of 34 problems after the cut-off date. This resulted in about 50% of the exploits being successful. Finally they tried to uncover some zero days and found two bugs where the exploit was slightly more profitable than the API cost at 3.4K.
  • The first novel vulnerability it found was an access control issue. The contract had an access-control bug: it forgot the view modifier on a function that changed the caller's funds. By repeatedly calling this, they were able to claim all funds under the contract. The bot was able to completely steal funds and sell them for a profit on its own. Crazy!
  • The second vulnerability was an input validation issue. The contract was a one-click token launch. When the token was created, the contract collected trading fees associated with the token. These fees are split between the contract and the beneficiary address specified by the token creator. If the creator wasn't specified, the contract fails to force a default or validate the field. So, anybody could make the call on behalf of the token creator. This was used to steal 1K worth of funds in the real world.
  • The cost to run these models was about the same as the profit gained. In practice, they claim that attackers could have better heuristics for finding vulnerable code and the code of tokens is going down. According to the post, the median number of tokens has declined by 70% or a 3.4x increase.
  • The AI agent has gone from exploiting 2% of vulnerabilities to 55% of vulnerabilities within the benchmarking area. They claim that more than half of the blockchain exploits in 2025 could have been carried out by autonomous attackers. I feel this is somewhat exaggerated, given the total stolen amount was only 4.6 million when the actual amounts since March are MUCH higher than this. I'd like to see it reason about more complicated bugs rather than simple input validation or access control issues.

Solana: Jumping Around in the VM- 1814

OtterSec    Reference →Posted 3 Months Ago
  • The authors of this post competed in the Paradigm CTF in 2023. One of the challenges was a Solana Jump Oriented Programming (JOP) challenge. The idea was to adapt a traditional binary exploitation technique for Solana. Solana programs can have memory corruption issues. So, having a mechanism to achieve an arbitrary CPI is a great challenge idea.
  • The vulnerable program has three instructions: a write-what-where primitive, a CPI to a non-existent program and a jump to an arbitrary address. The test environment is a standard Solana node. The competition criteria is that the program contains a PDA with the seed "flag" with a length of 0x1337 and the first bytes being equal to 0x4337. Although you're limited to only a single instruction in the state of the VM (because most things are temporary), we can actually use the primitives above to execute arbitrary instructions.
  • The goal is to find a way to CPI into the system program with controlled parameters. When looking at the assembly in Binary Ninja, they found a gadget that allows for calling sol_invoke_signed_rust as long as the proper data is in place on the Stack. To store the fake parameters, they can be stored directly in the instruction's input data. Using the write primitive, pointers to this information can be added to the stack.
  • A pretty neat post on binary exploitation within Solana!

Pinocchio for Dummies- 1813

Blueshift    Reference →Posted 3 Months Ago
  • Most Solana programs are written using Anchor. If you're really chasing performance, you may write raw Rust code too. Recently, the Pinocchio framework was developed as a middle ground between the two more common approaches. It acts as a minimalist Rust library for crafting Solana programs. This has the benefit of using fewer compute units, small binaries, and very few dependencies. This document is meant to be an overview of Pinocchio.
  • With Pinocchio, it's closer to native than to Anchor. You must write your own entrypoint function that performs function discriminator checks and operation routing. Compared to solana-program, it performs zero-copy operations by reading data directly from the byte array without copying anything. This eliminates serialization/deserialization overhead.
  • For Accounts, there aren't any macros for data types. Instead, the trait TryFrom() is used for deserializing account data into a structure to use. On an instruction context, there is another TryFrom trait that will perform necessary validations. Proper amount of accounts, signer checks, account ownership checks... all of the good Solana account checks. A similar validation process is done on the instruction data with TryFrom again.
  • Account creation must be manually checked for validity and done. This is a major downgrade from Anchor and adds a lot of complexity. Overall, a good article on the new Solana framework!

Not so Secure Enclaves- 1812

Joran Honig    Reference →Posted 3 Months Ago
  • Some applications have very strong security requirements. For instance, you should be able to execute code but not know what's executing. In cases like Secret Network, these secure enclaves are really important for security. A server compromise does nothing in this case.
  • Secure enclaves run in a very locked down environment. On AWS Nitro, users can only interact with the enclave via a virtual socket. Each enclave contains an attestation document, such as the hash of the image running, the hash of the kernel and whether it's signed or not.
  • Evervault is a platform built on top of AWS Nitro enclaves. It's providing scaffolding and infrastructure that allows connecting over HTTPs to the connection. They do this by including the attestation document in the TLS handshake. The key used to establish the connection must match the one in the attestation document. Besides this, the application needs to check all PCR values.
  • The Golang library for doing PCR validation has a neat feature: it only compares the PCRs that you want. If you leave the PCR as an empty string, then it will be considered valid. This comes at a funny cost of complexity though: what if a malicious host returned an empty string? If the user expected a value to be here and the empty string was passed in, the remote PCR validation would pass! The public bug report is here.
  • The vulnerability really only affects applications that check PCR8. This is because anything with a valid AWS signature requires that PCR0-2 be present and the requirement that at least one PCR must be sent in the document. Overall, an interesting bug that was found from really understanding the threat model.

Introducing constant-time support for LLVM to protect cryptographic code- 1811

Julius Alexandre - Trail of Bits    Reference →Posted 3 Months Ago
  • Cryptography is a fragile beast. It's powerful but can break with any small mistakes. One of these "small mistakes" is around comparisons. If one operation takes a different amount of time than another, this leaks some information. In the case of cryptography, this can lead to complete breakage. Because of this, a lot of cryptography is constant-time - meaning that all code-paths should take the same amount of time.
  • This constant-time thing is great! However, the code you write is different than the code that is executed. Sometimes, the compiler will optimize these constant-time operations away. Compilers will remove redundant operations, vectorized loops and restructure algorithms to be faster. Naturally, this is the enemy of constant-time cryptography code. In a recent research paper, 19 libraries across five compilers added vulnerabilities.
  • So, what's the solution to the optimization issue? This is what the article discusses. in LLVM, they added __builtin_ct_select to a family of intrinsic. This function contains a special intermediate representation that says "this must be constant-time" and "do not do optimizations on this". According to the authors, this fixed almost all of the constant-time issues discussed in the paper.
  • Many cryptography libraries hand-write assembly code to prevent optimizations. Of the features that don't, some were still vulnerable. Several projects have expressed strong interest in using this feature instead of inline assembly or hoping/praying the optimizer doesn't add a bug.
  • How does the constant-time work on different platforms? On x86-64, cmov is used for conditional moves. On i386, which doesn't have this instruction, masked arithmetic is performed with bitwise operations. On ARM, CSEL is used. On AAarch64, masked arithmetic is performed with bitwise operations. On all other architectures, bitwise arithmetic is ton.
  • Overall, a great blog post and addition to the LLVM compiler. Great work on this!

ERC-4337 Paymasters: Better UX, Hidden Risks- 1810

Nicholas Putra - OtterSec    Reference →Posted 3 Months Ago
  • ERC-4337 for Account Abstraction is great for UX improvements, but it has added significant complexity to smart contract interactions. Ethereum natively only allows transactions that originate by EOAs. By using smart wallets and gas sponsors, this becomes cheaper via batching and "free" for users to execute a transaction. User recovery can also be done.
  • There are several roles in this:
    • UserOperation: A transaction-like object for representing the users intent.
    • Smart Contract Account: The sender is a contract that implements logic via validateUserOp() and executeUserOp().
    • Bundler: Off-chain service that acts as an alternative mempool. Collects user ops, packages them and pays the gas.
    • Entrypoint: Central on-chain gateway for ERC4337. This validates and routes each user operation.
    • Paymaster: Felixible gas payment options. Use the native token or ERC20 tokens. Calls validatePaymasterUserOp and postOp().
  • The Entrypoint contract first validates that all operations are valid before executing them. This includes checking gas payments, nonce checks and more. In the execution phase, the entrypoint calls innerHandleOp() to forward the operation to the intended destination. Next, it calls postOp() on the Paymaster (if provided). Finally, the bundler is compensated for gas costs.
  • The author of this post has audited several implementations of ERC-4337 and has noticed two common issues. The first one is undercalculated gas costs. If the execution gas limit exceeds what's actually used during execution, a 10% penalty is charged, paid to the bundler/deducted from the user's deposit. In the example code, the returned funds includes the penalty - this allows for more funds than put it to be taken from the paymaster.
  • For ERC20 token transfers, there are two types: pre-payment + refund and post-payment. The pre-payment path is more secure; the issues stem from the post-payment method. If postOp() fails, then the error is just handled. If it's not one of two specific errors, then the state isn't rolled back. In practice, this means that the bundler will still get paid for the failed transaction.
  • Why does this matter? Even if the postOp() call fails because it can't collect funds from the user, the paymaster still needs to pay the bundler's gas costs. This is how the attack would work:
    1. Create a UserOperation with a high gas price.
    2. Revoke the paymaster's allowance before postOp() executes.
    3. postOp() fails. The paymaster pays Bundler for their high gas costs without receiving any funds.
    4. The paymaster loses money since they paid the bundler but couldn't collect from the user. The bundler profits as long as the actual gas costs less than what they charged.
  • This bug allows for bundlers to drain paymaster deposits. Some paymasters try to protect against this by simulating the UserOperation execution before signing. However, this can be bypassed by approving the transfer during simulation, but rejecting it on the actual call. So, what's the solution? Just don't use the post-payment strategy. If you absolutely have to, restrict usage to a whitelist of trusted bundlers. Just use pre-funding instead.
  • Overall, a great article explaining how ERC-4337 works and bugs around it.

A Series of Vignettes From My Childhood and Early Career - 1809

Jason Scheirer    Reference →Posted 3 Months Ago
  • The author of this post has been a software developer for over 30 years. Over the course of the years, they have heard "the end of software engineering as a profession" over and over again.
  • In 1983, it was time for the Multimedia age. Adding sounds and videos was made websites way better. You put a video tag in HTML and your job was ton; everyone was going to be a a sound engineer for UX products. Obviously, UX is still around.
  • In 2000, the IntelliJ IDE came out. Autocomplete was there. JavaDocs in the IDE. Feedback on compiling before even compiling the code. His friend claimed that was the end of our job. It substantially helped with the quantity of the code with some of their code in between.
  • They discuss two times they automated a job away: once for themselves and another time for somebody else. The "somebody else" case was around migration of help care systems from MUMPS to a more modern relational system. The author automated 85% of it, gave this person and the code but they still had a job. For themselves, it was updates an HTML page with mental health care providers via a long process from reading emails, opening excel sheets and more. When the work was done, they just moved to something else.
  • The dot com bubble was the next one. Software went from discs to websites written in JavaScript. The widespread Internet came true. Many people lost their jobs but many more were gained.
  • "This is indeed a set of passive-aggressive jabs on the continuing assault on our senses by the LLM hype lobby." is the quote at the end. LLM's aren't going to completely take our jobs but it was just change.

Hacking the Meatmeet BBQ Probe — Part 3- 1808

Julian B - Software Secured    Reference →Posted 3 Months Ago
  • The post looks at a Meatmeet BBQ Probe device and how it works. The device had two modes: one that runs directly through a mobile application and another that uses a cloud connection via passed WiFi credentials.
  • From using a BLE-Connect script they wrote in Python, they are able to see the UUIDs for each of the GATT characteristics. They grepped through the APK to get a list of files and luckily for them, the symbols were there for each one of the characteristics. So, they created a simple Python script to interact with the device for each one of the characteristics. Neat!
  • The article effectively claims that anybody can connect to the BLE device. In the various modes of BLE, there is no required pairing process; it's just simple to connect. The GATT services were likely usable without authentication at all. With other devices, even without keyboards, you typically have to "opt-in" to the process via a special set of button presses. It's weird that this wasn't the case.
  • Once you can connect to the device, it's effectively game over. The command remove_config could be used against the device to drop the configuration and add your own. The device even has over-the-air updates accessible as well. Naturally, there was no verification on the firmware either. So, it was a complete compromise of the device. They created a Botnet using this for fun. Good read!

Twitter/X Premium Account Verification Bypass Vector (of sorts): Gift Subscriptions- 1807

Its Not Nicole    Reference →Posted 3 Months Ago
  • The author of this post received an unprovoked gifted premium subscription to X/Twitter. Since moving to a paid subscription model, we all know that the requirements for "verified" have dropped drastically.
  • In many places, Twitter says an account must have a confirmed phone number and agree to the Terms of Service to become a Twitter Premium member. The gifted subscription route should theoretically go through the same requirements as the regular route.
  • The author of this post's account does NOT have a phone number linked or confirmed on their account. In fact, they haven't even confirmed their email address was 2012! They tested this with several friends and were able to replicate the issue.
  • Why does any of this matter? Privacy and transparency! This feature was rolled out in 2024, a few months before that year's election. Many of the political accounts that were "based in the US" were recently outed as being elsewhere as "fake news" because of the country indicator that was rolled out. If we take people's identities on Twitter seriously (I am the president of the United States), then this is a lapse in Twitter's security. Good post!

A heatmap diff viewer for code reviews- 1806

cmux    Reference →Posted 3 Months Ago
  • Given an open-source PR, this will do some magic to highlight potential bug-prone spots using AI. Pretty neat!