[8525, TyTN, MDA Vario II, JasJam Software Upgradin] pof:
stepw discovered a stack overflow vulnerability that affects ALL Trinity SPL versions up to now, I implemented an exploit for it, see details here.

The same bug is present in Hermes SPL versions >= 1.11, and all SPLs using HTC common base 1.51, so probably newer Breeze SPLs are vulnerable too.

Sadly for hermes users this bug can't be exploited the same way it's done on Trinity, this is the memory layout on Trinity:

0x80b00000 | xxxxxxxxxxx | \
.... | xxxxxxxxxxx | > wdata buffer
0x80b10000 | xxxxxxxxxxx | /
+-------------+
| . |
| . |
+-------------+
0x8c000000 | SPL-begins | \
.... | SPL SPL SPL | ME
.... | SPL SPL SPL | MO <--- how_far
.... | SPL SPL SPL | RY
.... | SPL SPL SPL | /
0x8c040000 | SPL-ends |
+-------------+
| . |
| . |
+-------------+
| . | \
0x8c08cb90 | . | s
.... | | t /\
.... | | a ||
.... | | c ||
.... | | k ||
0x8c08db90 | | /
| |

By doing recusrive 'ruustart' calls we can overflow the stack and set arbitrary bytes in 0x64 bytes buffer (size of command buffer in ruu mode).

We first try to detect how far the overflow should go, this varies on each SPL version. Then we put a known pattern on the stack and use the 'checksum' command to determine offsets of current stack top and size of stack frame of ruustart and normal command mode.

Then we load our unsigned code using wdata, of course we get an "invalid cert error" from bootloader, but the data we send is stored at 0x80b00000 (wdata buffer). We place here a modified IPL to skip loading SPL from NAND, and the custom SPL we want to load.

Then we calulate how many recursions we need to reach the spl end at 0x8c040000, the first recursions are padded with 0's as they are useless, only need them to overflow the stack, we put our shellcode here, the shellcode is a handler which executes the loader that resides in ram (0x80b00000) which copies patched IPL, SPL to RAM, disables ARM instruction caching and virtual addressing and branches to 0 offset to start IPL.

After placing the shellcode, we send the next ruustart calls with padding that contains branch instructions (relative jumps to the handler), we calculate how many calls we need based on target offset, initial stack offset and stack frame size.

Finally we need to jump to our patched code, to do this we call a function which has its entry point properly aligned with the overflown stack frame (we only control 0x64 bytes out of the frame size for ruustart which is tipically 0xe0), this also varies in each SPL version.

Now let's see the problem we're facing in hermes, this is the Hermes memory layout:

| . | \
| . | s /\
| | t ||
.... | | a ||
| | c ||
.... | | k
0x8c033b90 | | /
+-------------+
| . |
| . |
+-------------+
0x8c080000 | SPL-begins | \
.... | SPL SPL SPL | ME
.... | SPL SPL SPL | MO <--- how_far; we never reach here :(
.... | SPL SPL SPL | RY
.... | SPL SPL SPL | /
0x8c0c0000 | SPL-ends |
+-------------+
| . |

As you can see here, the stack grows up in the same direction as trinity, but the SPL code is placed below the stack so we can't overwrite it, thus we can't call a function that branches to our code.

So this is a call for developers & researchers, we need to find what else is between the stack and the ram top in hermes and see if there's something there that could be exploited, or if there's a pointer in ram that code branches to, we can exploit it by replacing the pointer.

You can use the Trinity exploit code with '-m hermes' hidden flag to test things on Hermes, feel free to modify / adapt the source for your tests on hermes.

Any ideas are welcome, have fun! :D