Code: Select all
#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();