/* This function is simply a container for the assembly loop * below, which is the actual code to be injected upon safe process * forking/cloning */ void __trampy_container_func() { /* Setup a label, which we can hook */ __asm__(""\ "__trampy_safe_entry:\n" ); /* This syscall is to be replaced with the * appropriate fork/clone/vfork. */ MAKE_SYSCALL(SYS_sched_yield); /* This syscall will only occur in the child as the * parent is restored to its original position after * executing the previous fork/clone/vfork syscall. * * We send the tracing process SIGUSR1 to inform it * of the child's existence. The tracer then attaches * and repositions the child to its original syscall * position. * * The child can obtain the PID of the tracing process * by reading a specific register. The tracer will have * written its PID there. To find out which register, see * the macro's at the start of the Trampy file. * * XXX: We do not do any error handling in case the kill * fails. */ SEND_TRACER_SIGNAL(); #if 0 /* Break stuff for libSegFault */ #ifdef __arm__ __asm__("mov pc, #0\n"); #elif defined(__i386__) || defined(__x86_64__) __asm__("hlt\n"); #endif #endif /* Now the child keeps making sched_yield syscalls until * the tracer restores it. */ while(1) { MAKE_SYSCALL(SYS_sched_yield); } return; }
/** * Remember you have to export the hooker function if using syscall hook */ int hook_import_bynid(SceModule *pMod, char *library, unsigned int nid, void *func, int syscall) { PspModuleImport *pImp; void *stubTab; int stubLen; int i = 0; if(pMod == NULL) return -1; stubTab = pMod->stub_top; stubLen = pMod->stub_size; while(i<stubLen) { pImp = (PspModuleImport*)(stubTab+i); if((pImp->name) && (strcmp(pImp->name, library) == 0)) { int j; for(j=0; j<pImp->funcCount; j++) { if(pImp->fnids[j] == nid) { void *addr = (void*)(&pImp->funcs[j*2]); if(syscall) { u32 syscall_num; syscall_num = sctrlKernelQuerySystemCall(func); if(syscall_num == (u32)-1) { printk("%s: cannot find syscall in %s_%08X\n", __func__, library, nid); return -1; } _sw(0x03E00008, (u32)addr); _sw(MAKE_SYSCALL(syscall_num), (u32)(addr + 4)); } else { _sw(MAKE_JUMP(func), (u32)addr); _sw(NOP, (u32)(addr + 4)); } sceKernelDcacheWritebackInvalidateRange(addr, 8); sceKernelIcacheInvalidateRange(addr, 8); } } } i += (pImp->entLen * 4); } return 0; }
/** * Remember you have to export the hooker function if using syscall hook */ int hook_import_bynid(SceModule *pMod, char *library, unsigned int nid, void *func) { PspModuleImport *pImp; void *stubTab; int stubLen; int i = 0; if(pMod == NULL) return -1; stubTab = pMod->stub_top; stubLen = pMod->stub_size; while(i<stubLen) { pImp = (PspModuleImport*)(stubTab+i); if((pImp->name) && (strcmp(pImp->name, library) == 0)) { int j; for(j=0; j<pImp->funcCount; j++) { if(pImp->fnids[j] == nid) { void *addr = (void*)(&pImp->funcs[j*2]); if(func == NULL) { _sw(0x03E00008, (u32)addr); _sw(NOP, (u32)(addr + 4)); } else { // Partition Check SceModule2 * mod = (SceModule2 *)pMod; if(((mod->text_addr & 0x80000000) && (((uint32_t)func) & 0x80000000)) || ((mod->text_addr & 0x80000000) == 0 && (((uint32_t)func) & 0x80000000) == 0)) { REDIRECT_FUNCTION(func, addr); } else { _sw(0x03E00008, (u32)addr); _sw(MAKE_SYSCALL(sctrlKernelQuerySystemCall(func)), (u32)(addr + 4)); } } sceKernelDcacheWritebackInvalidateRange(addr, 8); sceKernelIcacheInvalidateRange(addr, 8); } } } i += (pImp->entLen * 4); } return 0; }
void api_hook_import_syscall(unsigned int address, void * function) { //valid address if(address) { //asm jr $ra *(unsigned int *)(address) = 0x03E00008; //asm syscall # MAKE_SYSCALL(address + 4, sceKernelQuerySystemCall(function)); //flush cache sceKernelDcacheWritebackInvalidateRange((const void *)address, 8); sceKernelIcacheInvalidateRange((const void *)address, 8); } }
int utime(const char *path, const struct utimbuf *times) { return MAKE_SYSCALL(unimplemented, "utime", true); }