Random Homebrew: Tuyo Kiss
Tuyo Kiss is an interactive graphic novel for the PSP
Friends: Coding 'n Cracking - Nymphaea - PS3 Forum - darkforestgroup - daxhordes.org - Tgames - coldbird - gopsp.it - pspstation.org - prometheus - hgoel.info - MakeSmartTV - ps vita

Reverse of TN HEN main function

Forum rules
Any post not directly related to programming will be moderated.
Do not request people to code something for you.
Avoid posting messages that do not bring anything to the conversation. We want the threads in this subforum to stay focused.

Reverse of TN HEN main function

Postby jigsaw » Sat Dec 25, 2010 10:13 pm

Hi,

I reversed main function of TN HEN. It's basically what Davee described in his blog ( http://lolhax.org/2010/12/23/arcanum/#more-18 ) , with some extra effort for locating routine address via htmlviewer.
Is it allowed post reversed HEN here? :?

thx &
rgds,
-ql
Last edited by jigsaw on Sun Dec 26, 2010 11:33 am, edited 1 time in total.
jigsaw
 
Posts: 255
Joined: Sat Dec 18, 2010 12:49 pm

Re: Is it OK to post reverse of TN HEN here?

Postby m0skit0 » Sun Dec 26, 2010 10:24 am

I don't see why it would be forbidden.
I wanna lots of mov al,0xb
Image
"just not into this RA stuffz"
User avatar
m0skit0
Guru
 
Posts: 4783
Joined: Mon Sep 27, 2010 6:01 pm

Re: Is it OK to post reverse of TN HEN here?

Postby jigsaw » Sun Dec 26, 2010 11:32 am

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

jigsaw
 
Posts: 255
Joined: Sat Dec 18, 2010 12:49 pm

Re: Reverse of TN HEN main function

Postby jigsaw » Sun Dec 26, 2010 6:02 pm

The C code goes. Note: It compiles but always halt PSP under HBL (6.20 OFW). No idea of how to fix it. :(
According to the debug message, it stops after calling sceUtility_private_2DC8380C, the first jalr, and halt after few seconds.
I checked the asm and cannot find major difference between TN HEN.
I'd appreciate If somebody could give it a try.

rgds,
-ql
Code: Select all

#include <stdio.h>
#include <string.h>

#include "pspsdk.h"
#include "pspkernel.h"
#include "pspdebug.h"
#include "psputility.h"
#include "psputilsforkernel.h"

PSP_MODULE_INFO("TEST", 0, 1, 0); /* not sure how to set it, but tried to keep align with TN HEN .rodata.sceModuleInfo */

#if 0
PSP_MAIN_THREAD_ATTR(0); /* no idea of what it is */
#endif

#define printf pspDebugScreenPrintf

/* prototype of sceUtility_private_2DC8380C, scePower_driver_CE5D389B */
typedef int (*func1_t)(unsigned int);

/* prototype of sceUtility_private_764F5A3C, scePower_driver_1A41E0ED */
typedef int (*func2_t)(unsigned int, SceUID);

static void
clear_cache(void)
{
   sceKernelIcacheInvalidateAll();
   sceKernelDcacheWritebackInvalidateAll();
}

static void
callback(void)
{
   printf("Hello World!\n");
}

int
main(void)
{
   const static char *cbname = "test";

   char buf[168];
   pspUtilityHtmlViewerParam *param = (pspUtilityHtmlViewerParam *) buf;
   unsigned int *p = (unsigned int *) buf;
   func1_t fp;
   func2_t fp2;
   SceUID sceuid;
   char *s;
   unsigned int intr;

   pspDebugScreenInit();

   memset(buf, 0, 168);
   *p = 168;
   p += 4;
   *p = 19;

   sceUtilityHtmlViewerInitStart(param);
   sceKernelDelayThread(1000000);

   printf("start...\n");
   s = (char *) 0x08800000U;

   do {
      if (!strncmp("sceVshHV", s, 8))
         break;
      s += 4;
   } while (s < (char *) 0x0A000000U);

   printf("find sceVshHV at %p\n", s);
   memset((void *) 0x08800000, 0, 0x00100000);
   pspSdkSetK1(0);
   fp = (func1_t) ((unsigned) s - 648U); /* sceUtility_private_2DC8380C. CRASH here */
   printf("power unregister at %p\n", fp); /* this line is never printed */
   fp(0x08080000);
   printf("power unregister done\n");
   clear_cache();

   p = (unsigned int *) 0x08800000;

   do {
      if (*p == 0xFFFFFFFF)
         goto found;
      p++;
   } while (p < (unsigned int *) 0x08900000);

   printf("0xFFFFFFFF not found. quit!\n");
   return 0;

found:
   printf("create callback\n");
   sceuid = sceKernelCreateCallback(cbname, 0, 0);
   fp2 = (func2_t) (s - 624U);
   printf("power register\n");
   fp2((0x0880CCB0 -(unsigned int) p) >> 4, sceuid); /* sceUtility_private_764F5A3C */
   clear_cache();

   p = (unsigned int *) 0x08800010;
   *p = (unsigned int) callback;
   p = (unsigned int *) 0x08804234;
   *p = 0x08800000;
   clear_cache();

   printf("suspend intr\n");
   intr = sceKernelCpuSuspendIntr();
   sceKernelPowerLock(0, 0x08800000);
   sceKernelCpuResumeIntr(intr);
   printf("resumed intr\n");
   sceKernelExitGame();
   sceKernelExitDeleteThread(0);

   return 0;
}


jigsaw
 
Posts: 255
Joined: Sat Dec 18, 2010 12:49 pm

Re: Reverse of TN HEN main function

Postby wololo » Mon Dec 27, 2010 5:16 am

I'm always lost with function pointers, but could it be the way you wrote it?

I would try
Code: Select all
   pspSdkSetK1(0);
  void (* func1)(u32 arg1) = (void *)((u32)s - 648);
  func1(0x08080000);


instead of
Code: Select all
   pspSdkSetK1(0);
   fp = (func1_t) ((unsigned) s - 648U); /* sceUtility_private_2DC8380C. CRASH here */
   printf("power unregister at %p\n", fp); /* this line is never printed */
   fp(0x08080000);
I have a few US PSN codes to sell for a reasonable price (cheaper than pcgamesupply). PM me if interested, 1st come 1st serve basis..

Looking for guest bloggers and news hunters here at wololo.net, PM me!
wololo
Site Admin
 
Posts: 4639
Joined: Wed Oct 15, 2008 12:42 am
Location: Japan

Re: Reverse of TN HEN main function

Postby JJS » Mon Dec 27, 2010 7:33 am

I have also reversed the whole HEN launcher. The output of pspdecompiler was used as a basis for the C code, so you can attribute any weirdness to that ;). It should just build and run, I tested on a GO and on a 1000. It is based on the original version by TN.

The rebootex.bin is not compiled in unlike on the original, but has to be extracted from the data section (at 0x0000BB10) and placed as "ms0:/rebootex" on the memory stick.

Code: Select all
#include <pspsdk.h>
#include <pspdebug.h>
#include <psputility.h>
#include <pspkernel.h>
#include <psputilsforkernel.h>
#include <psppower.h>
#include <stdio.h>
#include <string.h>


#define REBOOTEX_SIZE (32000)


int global_model = 0; // 0x00018EF4
int (*func_decompressReboot)(u32 addr, u32 size, void *unk, void *unk2, void *unk3) = NULL; // 0x00018EF8

char global_rebootEx[REBOOTEX_SIZE] __attribute__((aligned(64))); // 0x0000BB10

unsigned int loadExecPatchAddresses_Go[] = { 0x00002F28, 0x00002F74 }; // 0x0000BB00
unsigned int loadExecPatchAddresses[] = { 0x00002CD8, 0x00002D24 }; // 0x0000BB08

#define MAKE_CALL(f) (0x0C000000 | (((unsigned int)(f) >> 2) & 0x03FFFFFF))



PSP_MODULE_INFO("hen", 0, 1, 1);



// TN HEN got the rebootex.bin file compiled in, but here
// it is loaded separately from the memory stick
void helperLoadRebootEx()
{
   SceUID file = sceIoOpen("ms0:/rebootex", PSP_O_RDONLY, 0777);
   sceIoRead(file, global_rebootEx, REBOOTEX_SIZE);
   sceIoClose(file);
}



/** henPatchedRebootEx
* Subroutine at address 0x000002B4
*/
int henPatchedRebootEx(u32 addr, u32 size, void *unk, void *unk2, void *unk3)
{
   // Decompress rebootex
   int (*func_sceKernelGzipDecompress)(char*, unsigned int, char*, int*) = (void*)0x8800FA10;
   int uncompressedSize = func_sceKernelGzipDecompress((char*)0x88FC0000, 0x10000, global_rebootEx, NULL);

   // Zero some memory
   char* address = (char*)0x88FB0000;
   while (address < (char*)0x88FB0020)
   {
      *address = 0;
      address++;
   }

   *((unsigned int*)0x88FB0000) = global_model;
   *((unsigned int*)0x88FB0004) = uncompressedSize;

   return func_decompressReboot(addr, size, unk, unk2, unk3);
}




/** henKernelCallback
* Subroutine at address 0x00000360
*/
int henKernelCallback()
{
   // Find text entry of module "sceLoadExec"
   SceModule* (*func_sceKernelFindModuleByName)(char*) = (void*)0x8801EB78;
   SceModule* module = func_sceKernelFindModuleByName("sceLoadExec");
   // Get text_address member, it is at a different position than in the PSPSDK struct
   unsigned int* textAddress = *(unsigned int*)((unsigned int)module + 108);

   // Determine PSP model and chooce patch addresses accordingly
   int (*func_sceKernelGetModel)() = (void*)0x8800A1C4;
   global_model = func_sceKernelGetModel();

   unsigned int* patchSet;

   if (global_model == 4) // PSP Go
   {
      patchSet = &loadExecPatchAddresses_Go[0]; // 0x0000BB00
   }
   else
   {
      patchSet = &loadExecPatchAddresses[0]; // 0x0000BB08
   }

   unsigned int* patchAddress;

   // Patch call to rebootex decryption
   patchAddress = (unsigned int*)((unsigned int)textAddress + patchSet[0]);
   *patchAddress = MAKE_CALL(&henPatchedRebootEx); // sub_0002B4

   // Overwrite some instruction
   patchAddress = (unsigned int*)((unsigned int)textAddress + patchSet[1]);
   *patchAddress = 0x3C0188FC;

   // Patch hardcoded memory locations
   *((unsigned int *) 0x8800CCB0) = 0xACC24230;
   *((unsigned int *) 0x8800CCB4) = 0x0A003322;
   *((unsigned int *) 0x8800CCB8) = 0x00001021;
   *((unsigned int *) 0x8800CCBC) = 0x3C058801;
   func_decompressReboot = (void*)textAddress;

   // Unknown function call
   int (*func_unknown1)() = (void*)0x88000E98;
   func_unknown1();

   // Unknown function call
   int (*func_unknown2)() = (void*)0x88000744;
   func_unknown2();

   return 0;
}



/**   henClearCache
* Subroutine at address 0x00000494
*/
void henClearCache() // sub_00494
{
   sceKernelIcacheInvalidateAll();
   sceKernelDcacheWritebackInvalidateAll();
}



/** main()
* Subroutine at address 0x000004B0
*/
int main() // sub_004B0
{
   pspDebugScreenInit(); // sub_00F4C

   // Original TN HEN has the rebootex data compiled in
   helperLoadRebootEx();

   unsigned int firmwareVersion = sceKernelDevkitVersion ();

   if (firmwareVersion != 0x06020010)
   {
      pspDebugScreenPrintf("Error: %s.", "Incompatible firmware"); // sub_00F6C
      __asm__ ("break;");
   }

   pspUtilityHtmlViewerParam htmlParam;
   memset(&htmlParam, 0, sizeof(pspUtilityHtmlViewerParam)); // sub_01020
   htmlParam.base.size = sizeof(pspUtilityHtmlViewerParam); // = 0x000000A8
   htmlParam.base.accessThread = 0x13;

   SceUID loadResult = sceUtilityHtmlViewerInitStart(&htmlParam); //sceUtility_CDC3AA41
   if (loadResult < 0)
   {
      pspDebugScreenPrintf("Error: %s.", "Could not load module");
      __asm__ ("break;");
   }

   sceKernelDelayThread(1000000);

   // Search through all of user memory to find the values 0x56656373 0x56486873 = "sceVshHV" (from "sceVshHVUtility_Module")
   // Note: this performs the same function, it is not transcribed verbatim
   unsigned int* address_low = (unsigned int*)0x08800000;
   unsigned int* address_high = (unsigned int*)0x08800004;

   while (address_high < (unsigned int*)0x0A000000)
   {
      if ((*address_low == 0x56656373) && (*address_high == 0x56486873))
      {
         break;
      }

      address_low++;
      address_high++;
   }

   // String not found
   if (address_high == (unsigned int*)0x0A000000)
   {
      pspDebugScreenPrintf("Error: %s.", "Could not find module address"); // sub_00F6C(0x0000B428, 0x0000B464)
      __asm__ ("break;");
   }

   // Zero out a good chunk of the lower end of user memory
   memset((void*)0x08800000, 0, 0x100000); // sub_01020

   // Make function pointer from address_low and invalidate the cache
   int (*func_unknown1)(int) = (void*)((unsigned int)address_low - 0x288);

   // Call the function
   func_unknown1(0x08080000);

   henClearCache(); // sub_00494

   // Search for the 0xFFFFFFFF value in RAM between 0x08800000 and 0x08900000
   // Note: this performs the same function, it is not transcribed verbatim
   unsigned int* functionAddress;
   unsigned int* currentAddress = (unsigned int*)0x08800004;

   if (*(unsigned int*)0x08800000 == 0xFFFFFFFF)
   {
      functionAddress = (unsigned int*)0x00000CCB;
   }
   else
   {
      while (currentAddress < (int*)0x08900000)
      {
         if (*currentAddress == 0xFFFFFFFF)
         {
            break;
         }

         currentAddress++;
      }

      if (currentAddress == (unsigned int*)0x08900000)
      {
         pspDebugScreenPrintf("Error: %s.", "Could not initialize exploit"); // sub_00F6C(0x0000B428, 0x0000B484);
         __asm__ ("break;");
      }

      functionAddress = (unsigned int*)(((unsigned int)0x0880CCB0 - (unsigned int)currentAddress) >> 4);
   }

   SceUID callbackId = sceKernelCreateCallback("", 0, 0); // (0x0000B4C0, 0x00000000, 0x00000000);

   // Make function pointer
   int (*functionRegisterCallback)(void*, int) = (void*)(((int)address_low - 0xBC00 + 0xB990));

   // Register the callback
   functionRegisterCallback(functionAddress, callbackId);

   henClearCache(); // sub_00494

   *(unsigned int*)0x08800010 = (int)&henKernelCallback; // sub_00360;
   *(unsigned int*)0x08804234 = 0x08800000;

   henClearCache(); // sub_00494

   // Go into kernel mode
   sceKernelPowerLock(NULL, 0x08800000);

   sceKernelExitGame();
   return 1;
}
JJS
Big Beholder
 
Posts: 1516
Joined: Mon Sep 27, 2010 2:18 pm

Re: Reverse of TN HEN main function

Postby jigsaw » Mon Dec 27, 2010 8:24 am

Wololo wrote:I'm always lost with function pointers, but could it be the way you wrote it?

I would try
Code: Select all
   pspSdkSetK1(0);
  void (* func1)(u32 arg1) = (void *)((u32)s - 648);
  func1(0x08080000);


instead of
Code: Select all
   pspSdkSetK1(0);
   fp = (func1_t) ((unsigned) s - 648U); /* sceUtility_private_2DC8380C. CRASH here */
   printf("power unregister at %p\n", fp); /* this line is never printed */
   fp(0x08080000);


Sorry my mistake. It should crash at fp(0x08080000) instead of assigning fp value. I won't bet your fix will work but anyway I'll give it a try later today.
jigsaw
 
Posts: 255
Joined: Sat Dec 18, 2010 12:49 pm

Re: Reverse of TN HEN main function

Postby jigsaw » Mon Dec 27, 2010 8:47 am

Impressive. Yesterday I also worked out routines at 0x00000360 and 0x000002B4. Apparently the fix in Chinese version is in routine 0x00000360 (OK it may be in other places as well but I don't know).

But I would never figure out how it works coz I just don't know existence of rebootex which hides itself in data segment.

May I ask how you noticed rebootex.bin and found where to locate it?

I was really depressed when yesterday I found that 0x00000360 just call some random functions and place value in arbitrary addresses, which just doesn't make sense to me. But now I feel much better coz your code explains some of the mysterious functions.

And besides, could you please try to compile it till the first jalr in main, and see how it works?
That is, with this code, how far does it go (see below). Coz I'm confused why my code always stops at func_unknown1(0x08080000);
Is it because I use PSP_MODULE_INFO("hen", 0, 1, 0); while you use PSP_MODULE_INFO("hen", 0, 1, 1);
Or it could be some other issue, like wrong Makefile?

Code: Select all
int main() // sub_004B0
{
   pspDebugScreenInit(); // sub_00F4C
   pspUtilityHtmlViewerParam htmlParam;

   memset(&htmlParam, 0, sizeof(pspUtilityHtmlViewerParam)); // sub_01020
   htmlParam.base.size = sizeof(pspUtilityHtmlViewerParam); // = 0x000000A8
   htmlParam.base.accessThread = 0x13;

   SceUID loadResult = sceUtilityHtmlViewerInitStart(&htmlParam); //sceUtility_CDC3AA41
   if (loadResult < 0)
   {
      pspDebugScreenPrintf("Error: %s.", "Could not load module");
      __asm__ ("break;");
   }

   sceKernelDelayThread(1000000);

   // Search through all of user memory to find the values 0x56656373 0x56486873 = "sceVshHV" (from "sceVshHVUtility_Module")
   // Note: this performs the same function, it is not transcribed verbatim
   unsigned int* address_low = (unsigned int*)0x08800000;
   unsigned int* address_high = (unsigned int*)0x08800004;

   while (address_high < (unsigned int*)0x0A000000)
   {
      if ((*address_low == 0x56656373) && (*address_high == 0x56486873))
      {
         break;
      }

      address_low++;
      address_high++;
   }

   // String not found
   if (address_high == (unsigned int*)0x0A000000)
   {
      pspDebugScreenPrintf("Error: %s.", "Could not find module address"); // sub_00F6C(0x0000B428, 0x0000B464)
      __asm__ ("break;");
   }

   // Zero out a good chunk of the lower end of user memory
   memset((void*)0x08800000, 0, 0x100000); // sub_01020

   // Make function pointer from address_low and invalidate the cache
   int (*func_unknown1)(int) = (void*)((unsigned int)address_low - 0x288);

   // Call the function
   func_unknown1(0x08080000);

   henClearCache(); // sub_00494

   sceKernelExitGame();
   return 1;
}
jigsaw
 
Posts: 255
Joined: Sat Dec 18, 2010 12:49 pm

Re: Reverse of TN HEN main function

Postby jigsaw » Mon Dec 27, 2010 8:55 am

Hi JJS,

I noticed that you skipped set_k1(0) in your code. Is it purposely? Maybe that makes my code broken? But it does exist in TN HEN...getting confused.
I have to wait for another day to get back home and try it.
jigsaw
 
Posts: 255
Joined: Sat Dec 18, 2010 12:49 pm

Re: Reverse of TN HEN main function

Postby JJS » Mon Dec 27, 2010 9:20 am

jigsaw wrote:I noticed that you skipped set_k1(0) in your code. Is it purposely?
This must be something that the patch added because I have not seen that $k1 is being modified in the original. I am actually not sure if you can touch k1 from user mode at all or if just doing this will crash the PSP.

jigsaw wrote:May I ask how you noticed rebootex.bin and found where to locate it?
The program follows the same pattern as ChickHEN, which is explained here. Without that it would have been much harder.
I am not so hot with the RE stuff, so there might also be mistakes in my code.

jigsaw wrote:Apparently the fix in Chinese version is in routine 0x00000360 (OK it may be in other places as well but I don't know).
I haven't looked at that version. But I guess it makes sense that the patch addresses are the same as on the GO for 04g models since they were introduced at the same time.

jigsaw wrote:Is it because I use PSP_MODULE_INFO("hen", 0, 1, 0); while you use PSP_MODULE_INFO("hen", 0, 1, 1);
The last two parameters are just the version number. It doesn't matter what it is set to.

The Makefile I use is the most basic thing imaginable:
Code: Select all
TARGET = hen

OBJS = hen.o

INCDIR =
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBS = -lpsppower -lpsputility

LDFLAGS =

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = TN HEN loader for 6.20 RE

PSP_FW_VERSION = 371
BUILD_PRX = 1

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak



EDIT: I looked at the fixed version for the 04g and what I see is that it "fakes" the model number for it to "2" (03g), but uses the patch addresses for the GO. Edit again: I might be confused and that it only fakes the model number.
JJS
Big Beholder
 
Posts: 1516
Joined: Mon Sep 27, 2010 2:18 pm

Next

Return to Programming

Who is online

Users browsing this forum: Google Adsense [Bot], TS0SmikY and 1 guest