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!
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!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. solana-program, it performs zero-copy operations by reading data directly from the byte array without copying anything. This eliminates serialization/deserialization overhead. 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. __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. 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.validateUserOp() and executeUserOp(). validatePaymasterUserOp and postOp().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.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.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:
postOp() executes.postOp() fails. The paymaster pays Bundler for their high gas costs without receiving any funds.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!