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!

Shining New Light on an Old ROM Vulnerability: Secure Boot Bypass via DCD and CSF Tampering on NXP i.MX Devices- 972

Jon Szymaniak - NCC Group    Reference →Posted 3 Years Ago
  • Secure boot is an important part of ensuring that a running device is not modified. While reading a reference manual for the NNXP i.MX 6/7/8M Application Processors (AP) , they noticed a weird quote that "The DCD based SoC initialization mechanism should not be used once the boot process exits the ROM". In the UBoot Github report, this change had been added but reverted later - this is the beginning of the research.
  • This chip is provides High Assurance Boot (HAB) functionality to protect the integrity and authenticity of the first boot loader stage retrieved from non-volatile storage. The HAB exports several API functions that allow further boot stages for ROM-based authentication.
  • For information on how several commands are executed, Device Configuration Data (DCD) and Command Sequence File File (CSF). These sections perform device configuration and image authentication.
  • However, there is a vulnerability: the DCD and CSF sections validation occurs after some use. As a result, this allows for the reading, polling and writing to configuration register spaces prior to authenticating them.
  • What result does this have on the system? An attacker can use the unverified DCD section to modify further stages in the boot process. For instance, U-Boot's authenticate_image function can be patched to always succeed. It appears they can even modify the currently loaded boot step to hijack control flow entirely.
  • The major issue is that the DCD Execution allows for execution outside of the ROM Context. The DCD code is attempts to sandbox specific regions but it just wasn't enough. This same vulnerability existed in the CSF functionality as well but the usage of deprecated functions being called.
  • The author concludes with why the study of old vulnerabilities is important. This design issue, of allowing ROM-resident code to be shared between boot stages, gave us an potential access problem. Overall, this was a solid post on the secure boot process and design level vulnerability discovery.

BitBTC's Optimism bridge- 971

PlasmaPower0    Reference →Posted 3 Years Ago
  • Optimism is a L2 sidechain of Ethereum. There are several bridges that allow for the taking of assets from L1 to L2 by creating a wrapped variant of the asset. One of these bridges is BitBTC.
  • When going from L2 to L1, a user can specify the token in which they would like unwrap. Part of the unwrapping is finding the proper L1 token to use when going back to the other chain, Ethereum.
  • The L1 bridge completely ignores the L2 token and simply mints the L1 token! This means that an attacker can create an arbitrary token on Optimism (which anybody can do) with all of the supply and set the L1Tokens address to be the L1 address. Using this, they could steal all of the tokens from BitBTC.
  • Luckily, this bug would take 7 days to exploit... where somebody would likely notice. The author posted this on Twitter, hoping that the BitBTC team would respond. Eventually, they did and fixed the bug.
  • It's amazing how bad the security of many of these platforms is. You think that handling this much money would require a deep look into the implications of the code written.

BNB Chain’s Cross-Chain Bridge Exploit Explained- 970

samczsun    Reference →Posted 3 Years Ago
  • The cross-chain bridge for the Binance Coin (BNB) on the Binance Smart Chain (BSC) was hacked. An attacker drained 2 million in BNB (566 million in USD). How did this happen? Let's follow the twitter thread!
  • While reviewing the transactions of the attacker account, they noticed a large amount of funds that went into Venus. While reviewing the transaction from the Binance Bridge, it was clear: the bridge had been convinced to send the attacker 1 million BNB. So, it appears that the bridge has a bug in it.
  • What reconnaissance can we do before checking the code of the project? The samczsun noticed that the height of the transaction was always the same and much smaller than expected. Additionally, the withdrawal proof was sustainability shorter. It appears there is something wrong with how the proof is determining if a transaction is valid or not.
  • The Binance bridge was keeping track of the state using a self balancing tree algorithm called an AVL tree, with a twist of being immutable - IAVL While doing the verification of the operations, there are two expected operations: iavl:v and multistore. To succeed, both operations need to succeed.
  • The verification process was busted. But how? The input of the multistore operation is the output for the iavl:v operation. The function COMPUTEHASH is used to go down every path and lead node to do the verification. Since a single bit change will change the way this works, it is not realistic to trick the hash function. In particular, if we want to forge a proof, the path and leaf pair will need to stay the same.
  • For the root node in the Merkle proof, the code needs to verify each node in the chain. However, there is a slight optimization bug. If there is a left node, the right node is NOT validated. As a result, we can place an arbitrary node into the tree WITHOUT it getting validated. This functionality is described in the The PR to fix the vulnerability on Github.
  • Since we can add an arbitrary right node, all we have to do is add a leaf node to the right side with a blank inner node. By tweaking the leaf to exit early, we can still get a correct root hash despite altering the chain maliciously.
  • Wow, this was literally an issue with the core blockchain framework itself. When doing the cross-chain communication, the BSC keeps track of the state of the root hash of the other chain (Binance Chain). The bypass of the verification allowed for the creation of money that never existed.
  • Overall, a super interesting vulnerability that shouldn't have been possible. Things this big and impactful really should be tested thoroughly via dynamic testing and code review.

Cross-chain DEX Aggregator Transit Swap Hacked Analysis- 969

SlowMist    Reference →Posted 3 Years Ago
  • Transit Swap is a cross-chain exchange. It allows for aggregating all of the tokens you owe between the different platforms.
  • When performing a swap, there is a routing contract. Depending on the chain being used, a different contract is called. The routing bridge contract will is where the bug is at.
  • The function claimTokens is used to transfer tokens redeemed by the user to the routing bridge and eventually to the user. This is done by invoking the transferFrom ERC20 call on the specified token contract.
  • The vulnerability is that the user controls all of the parameters provided into the transferFrom() call from the router contract. In particular, they control the users from, to and amount. Additionally, users have to permit the contract to use the funds. Hence, with this control, they can make arbitrary calls to steal funds from all of the users.
  • The vulnerability occurs because there is no input validation on data passed during the token exchange. This is a classic confused deputy problem! A trusted entity is making the call but the input coming in abuses this trust.
  • The exploit led to $23 million in funds being stolen. The pattern for the router making calls to other contracts is a common pattern. Reviewing smart contracts individually doesn't work; the interoperability is extremely important as well. Overall, good report on the bug!

Pixel6: Booting up- 968

Gagnerot Georges - eShard    Reference →Posted 3 Years Ago
  • While reading various security advisories the author missed while on vacation, there noticed a Pixel anti-rollback notice. This indicated that a vulnerability occurred in the bootloader of the device, making it a major risk and adding an anti-rollback feature to it. Since there was no public information besides there being a bug and it says RCE, the author of the post decided to find and exploit the bug.
  • The ARM specification for the boot process is going from the Primary Boot Loader (PBL) ->BL1->->BL2->BL31->Trustzone(TZSW) and ABL. BL1 performs late architectural and platform specific initialization and runs the second BL image, which simply loads BL3. BL3 sets up he runtime services for the CPU and helps pass control to the operating system. The bootloader is in likely in BL1 because its the furthest down in the chain that isn't in ROM.
  • To find the vulnerability, they downloaded versions before and after the patch. By comparing with bindiff, it probably wouldn't be the hardest thing in the world to find the patch for the security issue. They used bindiff on the most of the fastboot commands for each of the binaries. From this, they identified a small bit of code that was removed from the command handlers.
  • There were low level commands that the fastboot console has access to - flash:raw. However, part 2 appears to refer to a vulnerability in the bootloader but doesn't actually mention what it is. Instead, they claim there's a vulnerability that allows for some sort of write primitive. So, I'm a little confused here.
  • To build a working exploit, they setup an emulator with Unicorn. The typical workflow for emulation is creating the emulator, setting up the memory in the same way as the image, initializes the device and execution. To top it off, hooks must added to native functionality that cannot be emulated.
  • With the debugging environment setup, the hacking can be done. To get a nice read/write primitive, we can probably reuse existing code. The internal commands (without handlers) download for reading content and upload for writing content.
  • Overall, the posts are mildly confusing, as not everything is laid out perfectly. In particular, the vulnerability is not defined well and the wording in the second post can be confusing. However, the process for reverse engineering, emulation and exploit methodology was very interesting!

Hacking TMNF: Part 2 - Exploiting a blind format string bug- 967

bricked.tech    Reference →Posted 3 Years Ago
  • In the previous post, a format string vulnerability was found that led to a crash. This post is all about exploiting the vulnerability to get code execution. The vulnerability occurs in the stdout logging because of a call to fprintf taking in a user controlled string with no other parameters.
  • Simply sending a %99999s will crash the program. What else can we do besides crash? With format string bugs, the identifier %n can be used to perform writes. However, the format string is stored on the heap. This means that the simple <target addr>%x$n doesn't work. This is because the format string parser will attempt to find data on the stack for pointers and it will not be our controlled data.
  • Although we cannot control the location being written to via %n, we can still write to ANY pointer on the stack with a user controlled value. What if there are user controlled pointers on the stack though? By design, the Base Pointer (BP) is exactly this.
  • So, here's the trick. Since we can perform this format string vulnerability multiple times, we can abuse that. On the first write, we'll use a pointer on the stack to write a user controlled value on the stack. This will be the address we want to write in the future. On the second write, we will use the <target addr>%x$n trick with this address and other user controlled value by incrementing the amount of spaces in use. With this technique, we have an arbitrary write primitive!
  • Let's make this primitive better! Currently, it is writing 134.5 MB of padding to stdout because of the amount of filler bytes required for %n to write the address. To get around this, the %hhn specifier can be used to write a single byte at a time. This led to a 1/16 chance that the attack would work because of base pointer alignment.
  • The author decided that the speed gain was worth it but wanted to figure out the 1/16 problem beforehand. They noticed that the RPC GetVersion returned a global variable. By performing a write to corrupt the string in the version with the format string bug, we can leak a stack address. In particular, using a relative write on the global address to the name to point to the .bss section argv pointer, we can leak a stack address. This requires a slow 2 byte write but makes this much faster later on.
  • Once we have the arbitrary write primitive, we need something to write! The binary is compiled without PIE, meaning that we can corrupt the global variables for the binary without needing a memory leak. From the arbitrary write and the stack leak, we can trivially ROP the binary. The chain, which is made easier by the binary being statically compiled, calls mprotect to make the stack executable then jumping to shellcode written beforehand. They created a reverse shell with this.
  • The code for the ROP is interesting since it makes heavy use of the pwntools functionality instead of hardcoding addresses and sycalls. Pretty neat to see and something I'd use in the future. Overall, great post on format string exploitation.

Hacking TMNF: Part 1 - Fuzzing the game server - 966

bricked.tech    Reference →Posted 3 Years Ago
  • The author of the post was interested in binary only fuzzing via snapshots and fuzzing highly structured inputs. Given their requirements, they saw Trackmaina Nations Forever from 2008 to be a good target.
  • To fuzz something, you need to write a harness to take in the fuzzing input and process it. Since the application uses XML-RPC over TCP, this is not trivial. Sockets are slow and messy.
  • To get around this, the author takes a snapshot right before the processing of the XML-RPC message occurs. Then, they modify the memory location of the message by updating the size, the buffer and edit the session_object information to bypass auth.
  • LibAFL is an amazing for building these types of fuzzers. There is a magic qemu launcher that is used for fuzzing this, which can be used for the snapshot functionality. To generate XML messages, they use Nautilus. The author links to some good resources for getting this working.
  • To fuzz the XML input, we need to ensure it has a valid XML message. The XML-RPC protocol is well defined by Trackmania, luckily. Additionally, we can reverse engineer the application to find out more messages that can be sent.
  • The fuzzer more so fuzzes the inputs within the XML tags than the XML itself. For instance, the first rule for Nautilus includes the content <?xml version=\"1.0\"?<methodCall>{METHOD_CALL}</methodCall> with a small substitution in it for the method call ({METHOD_CALL}). All other inputs are done in a similar fashion, with only small substitutions done for the values within the XML.
  • After setting up the grammar by adding rules with Nautilus and setting up some test inputs, they fuzzed the application. Additionally, they setup a repro mode that does the same thing as the fuzzer but only for a single input. From fuzzing, they instantly found a bunch of format string bugs! More on this in part 2.
  • They patched the format string bug, which was simply in a logging function, in order to find other bugs. This was done by a simple memory write to the QEMU process. Besides the format string bug, they found a few other crashes.
  • Their favorite bug was an issue where the spectators could be forced to look at a specific player. By forcing the game into a freecam on all of the spectators, it hits an edge case that causes a crash. Pretty interesting edge case that was found! Overall, awesome post on snapshot binary fuzzing, which I didn't have much experience in.

PS5 4.xx Kernel Exploit- 965

Cryptogenic    Reference →Posted 3 Years Ago
  • The PS5 has a vulnerable version of WebKit to a use after free (UAF) bug in the IPv6 stack. The Github repo is an implementation of the exploit to gain a read/write primitive.
  • The PS5 has an interesting binary protection called eXecute Only Memory (XOM). This allows for the code to execute, but never be read out while in the kernel. This stifles ROP because we don't know the gadgets to execute. We simply don't know where we are jumping at!
  • Besides XOM, the PS5 kernel has fine grained CFI, SMAP/SMEP and the hypervisor prevents patching the kernel as well. The PS5 is a masterpiece of defense in depth protections to make the life of exploiters much harder.
  • The actual details of the exploit in the Github are not very thorough. At a high level... a UAF is triggered to overlap a ip6_rthdr object. This object can then be used get an info leak. From there, a fake pktopts option is used in order to gain an arbitrary read/write primitive. Of course, some clean up is required for this. Overall, interesting to read out the complexity of the PS5 kernel!

uClibC and uClibC-ng libpthread linuxthreads memory corruption vulnerabilities- 964

Talos    Reference →Posted 3 Years Ago
  • uClibC and uClibC-ng are both standalone replacements for glibc that are extremely lightweight. These are commonly used on embedded platforms.
  • When creating threads on the platform, the thread must create a stack. This is done with a fixed size memory address and decreases from a fixed address. Because they are using mmap with the MMAP_FIXED flag, it will overwrite all existing mappings if they are asked for.
  • By creating a large amount of threads, other mappings may be overwritten. For instance, the code for libc could be corrupted. If the mapping is RWX, this could be used to get code execution. This attack is only possible on 32-bit because of the limit of threads that can be created.
  • Overall, good bug report for items that are not normally talked about. Normally, if you're using mmap directly, you're probably doing something wrong.

How I Hacked my Car Part 3: Making Software- 963

GreenLuigi1    Reference →Posted 3 Years Ago
  • In the previous two posts, they got root access to the system by breaking the update functionality. So, now what? Let's build some software!
  • ccOS(Connected Car Operating System) is an OS developed by Nvidia and Hyundai for all recent vehicles. While reading the OS, they found several header files for doing development on the OS! The author downloaded VS code, the G++ ARM cross compiler stack and a few other things in order to start compiling. They started off with a simple C++ program to view the status of the door using the library. That's pretty neat!
  • From there, they made a slightly more complicated CLI interface to unlock and lock the doors using the known interface. To finish off the research, they built a simple GUI application with QT in order to pop a screen on the entertainment console. The only complication with this was registering the GUI app with the Helix package manager. With this, they could start up their application from the CLI to display on the screen!
  • Overall, a good blog series on reverse engineering and getting a good setup for hacking. They may wrote more posts in the future, which I'd love to see.