 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Wed Nov 23, 2005 2:09 am Post subject: PatchNID function |
|
|
This is a small function which allow to change the function called by the NID (changes the syscall opcode) by a function of your choice (it must have the same parameters and return) :
| Code: |
#define PATCH_JAL(x) 0xC000000 | ((((u32) x) >> 0x2) & 0x3FFFFFF) // JAL x
int patchNID (u32 oid, u32 nid, u32 *patch)
{
SceModule *modEntry;
SceModuleInfo *modInfo;
SceLibraryStubTable *stubTable;
int x;
// Trouver le pointeur memoire du module
modEntry = sceKernelFindModuleByUID(oid);
#if defined(PATCH_INFO_SHOW) || defined(PATCH_INFO_FILE)
printf_patch("modEntry : 0x%X\n",((u32) modEntry));
#endif
// Si mauvais module
if ((((long) modEntry) & 0xFF000000) != 0x88000000) return -1;
if ((modEntry->stub_top - modEntry->ent_top) < 40) return -1;
// Trouver le SceModuleInfo
modInfo = (SceModuleInfo *) ((*((u32 *) modEntry->stub_top)) - 0x38); // 0x38 = sizeof(SceModuleInfo) + 0x4
#if defined(PATCH_INFO_SHOW) || defined(PATCH_INFO_FILE)
printf_patch("modInfo : 0x%X\n",((u32) modInfo));
printf_patch("modInfo->modname : %s\n",modInfo->modname);
printf_patch("modInfo->stub_top : 0x%X\n",((u32) modInfo->stub_top));
printf_patch("modInfo->stub_end : 0x%X\n",((u32) modInfo->stub_end));
#endif
// Parcourir la liste des stubs
stubTable = (SceLibraryStubTable *) modInfo->stub_top;
while (stubTable < ((SceLibraryStubTable *) modInfo->stub_end))
{
#if defined(PATCH_INFO_SHOW) || defined(PATCH_INFO_FILE)
printf_patch("stubTable : 0x%X\n",((u32) stubTable));
printf_patch("stubTable->libname : %s\n",stubTable->libname);
printf_patch("stubTable->stubcount : %d\n",stubTable->stubcount);
#endif
// Parcourir la table des NID
for (x=0;x<stubTable->stubcount;x++)
{
// Patcher l'adresse de la fonction si NID trouvé ou si nid = 0xFFFFFFFF (code pour patcher tout les NID)
if ((stubTable->nidtable[x] == nid) || (nid == 0xFFFFFFFF))
{
#if defined(PATCH_INFO_SHOW) || defined(PATCH_INFO_FILE)
printf_patch("patched (0x%X, NID %d) : 0x%X -> 0x%X\n",((u32) &((u32 *) stubTable->stubtable)[(x << 0x1) + 0x1]),x,((u32 *) stubTable->stubtable)[(x << 0x1) + 0x1],((u32) patch));
#endif
// (x << 0x1) + 0x1 -> 2 instructions par NID (jr et nop) et c'est la 2eme instruction qu'on patche
((u32 *) stubTable->stubtable)[(x << 0x1) + 0x1] = PATCH_JAL(patch); // JAL patch
break; // un seul NID pareil par librairie ?
}
}
// Mettre a jour le pointeur
stubTable = (SceLibraryStubTable *) (((u32 *) stubTable) + stubTable->len);
}
return 0;
}
// Exemple d'appel
SceUID sceIoOpenPatched (const char *path, int flags, SceMode mode)
{
char pathPatch[512];
// Patcher le nom
strPatchPath(path,pathPatch);
#if defined(PATCH_INFO_SHOW) || defined(PATCH_INFO_FILE)
printf_patch("SceIoOpenPatched : %s -> %s\n",path,pathPatch);
#endif
// Appeler la fonction normale
return sceIoOpen(pathPatch,flags,mode);
}
... fonction appelante :
SceUID oid = sceKernelLoadModule(pathPatch,flags,option);
// Si erreur
if (oid & 0x80000000) return oid;
// Patcher les NID du module chargé
patchNID(oid,0x109F50BC,(u32 *) sceIoOpenPatched);
// Purger cache des instructions
sceKernelIcacheClearAll();
|
|
|
| Back to top |
|
 |
Fanjita
Joined: 28 Sep 2005 Posts: 217
|
Posted: Wed Nov 23, 2005 3:08 am Post subject: |
|
|
Doh! You posted this just a couple of days after I spent most of the weekend figuring out how to do the same thing :) _________________ Got a v2.0-v2.80 firmware PSP? Download the eLoader here to run homebrew on it!
The PSP Homebrew Database needs you! |
|
| Back to top |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Wed Nov 23, 2005 3:11 pm Post subject: |
|
|
| Fanjita wrote: | | Doh! You posted this just a couple of days after I spent most of the weekend figuring out how to do the same thing :) |
oups, sorry ;-) |
|
| Back to top |
|
 |
blasty
Joined: 22 Aug 2005 Posts: 9
|
Posted: Thu Dec 01, 2005 3:23 am Post subject: |
|
|
I have compiled the example but I am having trouble getting it to work, could you post a slightly more detailed example? I'm not sure if I'm getting the loading of the module bit correct. When I run the program it never finds the NID. I got the NIDs from here
Any help would be appreciated. Thanks in advance! |
|
| Back to top |
|
 |
johnmph
Joined: 23 Jul 2005 Posts: 119
|
Posted: Thu Dec 01, 2005 8:21 am Post subject: |
|
|
| blasty wrote: | I have compiled the example but I am having trouble getting it to work, could you post a slightly more detailed example? I'm not sure if I'm getting the loading of the module bit correct. When I run the program it never finds the NID. I got the NIDs from here
Any help would be appreciated. Thanks in advance! |
I have modified a little the function, this is the new function with sample :
| Code: |
// INCLUDES
#include <pspdisplay.h>
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include <pspctrl.h>
#include <string.h>
// MODULE INITIALISATION
PSP_MODULE_INFO("FirmLaunch", 0x1000, 2, 0);
PSP_MAIN_THREAD_ATTR(0x0);
// DEFINES
#define printf pspDebugScreenPrintf
#define PATCH_INFO_SHOW
// MIPS OPCODE
#define PATCH_J(x) 0x8000000 | ((((u32) x) >> 0x2) & 0x3FFFFFF) // J x
#define PATCH_LUI(x,y) 0x3C000000 | ((x & 0x1F) << 0x10) | (y & 0xFFFF) // LUI x, y
// FUNCTIONS CALLBACKS
int exit_callback (int arg1, int arg2, void *common)
{
sceKernelExitGame();
return 0;
}
int CallbackThread (SceSize args, void *argp)
{
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
int SetupCallbacks (void)
{
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, PSP_THREAD_ATTR_USER, 0);
if(thid >= 0) sceKernelStartThread(thid, 0, 0);
return thid;
}
// FUNCTIONS
int patchStub (u32 oid, u32 nid, u32 *patch)
{
SceModule *modMem;
SceLibraryStubTable *stubTable, *stubEnd;
int x;
// Trouver le pointeur memoire du module
modMem = sceKernelFindModuleByUID(oid);
#if defined(PATCH_INFO_SHOW)
printf("modMem : 0x%X\n",((u32) modMem));
#endif
// Si mauvais module
if ((((long) modMem) & 0xFF000000) != 0x88000000) return -1;
if ((modMem->stub_top - modMem->ent_top) < 40) return -1;
// Parcourir la liste des stubs
stubTable = (SceLibraryStubTable *) ((u32 *) modMem->stub_top);
stubEnd = (SceLibraryStubTable *) (((u8 *) modMem->stub_top) + modMem->stub_size);
while (stubTable < stubEnd)
{
#if defined(PATCH_INFO_SHOW)
printf("stubTable : 0x%X\n",((u32) stubTable));
printf("stubTable->libname : %s\n",stubTable->libname);
printf("stubTable->stubcount : %d\n",stubTable->stubcount);
#endif
// Parcourir la table des NID
for (x=0;x<stubTable->stubcount;x++)
{
// Patcher l'adresse de la fonction si NID trouvé ou si nid = 0xFFFFFFFF (code pour patcher tout les NID)
if ((stubTable->nidtable[x] == nid) || (nid == 0xFFFFFFFF))
{
#if defined(PATCH_INFO_SHOW)
printf("patched (0x%X, NID %d) : 0x%X -> 0x%X\n",((u32) &((u32 *) stubTable->stubtable)[x << 0x1]),x,((u32 *) stubTable->stubtable)[x << 0x1],((u32) patch));
#endif
((u32 *) stubTable->stubtable)[x << 0x1] = PATCH_J(patch); // J patch
((u32 *) stubTable->stubtable)[(x << 0x1) + 0x1] = PATCH_LUI(0x0,0x0); // LUI $zero, 0 (delay slot instruction)
if (nid != 0xFFFFFFFF) break; // un seul NID pareil par librairie ?
}
}
// Mettre a jour le pointeur
stubTable = (SceLibraryStubTable *) (((u32 *) stubTable) + stubTable->len);
}
return 0;
}
u32 LoadStartModule (char *path, int start)
{
u32 loadResult, startResult;
int status;
loadResult = sceKernelLoadModule(path, 0, NULL);
if (loadResult & 0x80000000) return -1;
if (start)
{
startResult = sceKernelStartModule(loadResult, 0, NULL, &status, NULL);
if (loadResult != startResult) return -2;
}
return loadResult;
}
SceUID sceIoOpenPatched (const char *path, int flags, SceMode mode)
{
char pathPatch[512];
// Patch name
strcpy(pathPatch,path);
strcat(pathPatch,".bak"); // example : ms0:/temp.bin -> ms0:/temp.bin.bak
// Call normal function
return sceIoOpen(pathPatch,flags,mode);
}
int main (void)
{
u32 oid;
// Init SDK
pspDebugInstallKprintfHandler(NULL);
pspDebugScreenSetTextColor(0xFF);
pspSdkInstallNoDeviceCheckPatch();
pspSdkInstallNoPlainModuleCheckPatch();
// Init display and HOME button
pspDebugScreenInit();
pspDebugScreenClear();
SetupCallbacks();
// Setup Pad
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(0);
// Load a module
oid = LoadStartModule("ms0:/module.prx",1);
// Patch NID module
patchStub(oid,0x109F50BC,(u32 *) sceIoOpenPatched); // Replace sceIoOpen imported function of module.prx module by sceIoOpenPatched
// Apply modifications to cache
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
// Main loop
for (;;) sceDisplayWaitVblankStart();
// Exit program
sceKernelExitGame();
return 0;
}
|
|
|
| Back to top |
|
 |
dankydoo
Joined: 29 Mar 2005 Posts: 11
|
Posted: Sat Dec 03, 2005 9:14 am Post subject: |
|
|
John,
Interesting function!
I have a few questions on how it works, I am attempting to understand how all this works:
I Understand that you patch the first instruction of the given NID function to jump to the patched function. What I do not understand is how the unpatched function is called within the patched function? Wouldn't this result in a loop, or there are 2 different methods for calling a given functoin? I guess I do not really understand the difference on how an NID is resolved compared to a normal function call? ( I understand the code on how you are looping through the modules NIDs to find the correct one to patch)
Even further, why are syscalls needed? Why do we need to know the NID of the function when we can call it by name?
Also, how would you patch the function that is called by name in a similar manner to the patchNID function?
thanks for any help with this, I'd really like to understand these concepts...
dankydoo |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|