#include <stdio.h> #include <stdlib.h> #include <asm/user.h> #include <asm/ptrace.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <sys/mman.h> #include <dlfcn.h> #include <dirent.h> #include <unistd.h> #include <string.h> #include <elf.h> #include <utils/PrintLog.h> #include <inject.h>
#define CPSR_T_MASK ( 1u << 5 ) const char *libc_path = "/system/lib/libc.so"; const char *linker_path = "/system/bin/linker";
int ptrace_continue(pid_t pid) { if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) { LOGD("ptrace cont error, pid:%d", pid); return -1; } return 0; }
int ptrace_attach(pid_t pid) { int status = 0; if (ptrace(PTRACE_ATTACH, pid, NULL, 0) < 0) { LOGD("attach process error, pid:%d", pid); return -1; } LOGD("attach process pid:%d", pid); waitpid(pid, &status , WUNTRACED); return 0; }
int ptrace_detach(pid_t pid) { if (ptrace(PTRACE_DETACH, pid, NULL, 0) < 0) { LOGD("detach process error, pid:%d", pid); return -1; } LOGD("detach process pid:%d", pid); return 0; }
int ptrace_getregs(pid_t pid, struct pt_regs *regs) { if (ptrace(PTRACE_GETREGS, pid, NULL, regs) < 0) { LOGD("Get Regs error, pid:%d", pid); return -1; } return 0; }
int ptrace_setregs(pid_t pid, struct pt_regs *regs) { if (ptrace(PTRACE_SETREGS, pid, NULL, regs) < 0) { LOGD("Set Regs error, pid:%d", pid); return -1; } return 0; }
long ptrace_getret(struct pt_regs * regs) { return regs->ARM_r0; }
long ptrace_getpc(struct pt_regs * regs) { return regs->ARM_pc; }
int ptrace_readdata(pid_t pid, uint8_t *pSrcBuf, uint8_t *pDestBuf, uint32_t size) { uint32_t nReadCount = 0; uint32_t nRemainCount = 0; uint8_t *pCurSrcBuf = pSrcBuf; uint8_t *pCurDestBuf = pDestBuf; long lTmpBuf = 0; uint32_t i = 0; nReadCount = size / sizeof(long); nRemainCount = size % sizeof(long);
for (i = 0; i < nReadCount; i ++ ) { lTmpBuf = ptrace(PTRACE_PEEKTEXT, pid, pCurSrcBuf, 0); memcpy(pCurDestBuf, (char *)(&lTmpBuf), sizeof(long)); pCurSrcBuf += sizeof(long); pCurDestBuf += sizeof(long); }
if ( nRemainCount > 0 ) { lTmpBuf = ptrace(PTRACE_PEEKTEXT, pid, pCurSrcBuf, 0); memcpy(pCurDestBuf, (char *)(&lTmpBuf), nRemainCount); }
return 0; }
int ptrace_writedata(pid_t pid, uint8_t *pWriteAddr, uint8_t *pWriteData, uint32_t size) { uint32_t nWriteCount = 0; uint32_t nRemainCount = 0; uint8_t *pCurSrcBuf = pWriteData; uint8_t *pCurDestBuf = pWriteAddr; long lTmpBuf = 0; uint32_t i = 0; nWriteCount = size / sizeof(long); nRemainCount = size % sizeof(long);
for (i = 0; i < nWriteCount; i ++) { memcpy((void *)(&lTmpBuf), pCurSrcBuf, sizeof(long)); if (ptrace(PTRACE_POKETEXT, pid, pCurDestBuf, lTmpBuf) < 0) { LOGD("Write Remote Memory error, MemoryAddr:0x%lx", (long)pCurDestBuf); return -1; } pCurSrcBuf += sizeof(long); pCurDestBuf += sizeof(long); } if (nRemainCount > 0) { lTmpBuf = ptrace(PTRACE_PEEKTEXT, pid, pCurDestBuf, NULL); memcpy((void *)(&lTmpBuf), pCurSrcBuf, nRemainCount); if (ptrace(PTRACE_POKETEXT, pid, pCurDestBuf, lTmpBuf) < 0) { LOGD("Write Remote Memory error, MemoryAddr:0x%lx", (long)pCurDestBuf); return -1; } } return 0; }
int ptrace_call(pid_t pid, uint32_t ExecuteAddr, long *parameters, long num_params, struct pt_regs* regs) { int i = 0; for (i = 0; i < num_params && i < 4; i ++) { regs->uregs[i] = parameters[i]; } if (i < num_params) { regs->ARM_sp -= (num_params - i) * sizeof(long) ; if (ptrace_writedata(pid, (void *)regs->ARM_sp, (uint8_t *)¶meters[i], (num_params - i) * sizeof(long)) == -1) return -1; } regs->ARM_pc = ExecuteAddr; if (regs->ARM_pc & 1) { regs->ARM_pc &= (~1u); regs->ARM_cpsr |= CPSR_T_MASK; } else { regs->ARM_cpsr &= ~CPSR_T_MASK; } regs->ARM_lr = 0; if (ptrace_setregs(pid, regs) == -1 || ptrace_continue(pid) == -1) { LOGD("ptrace set regs or continue error, pid:%d", pid); return -1; } int stat = 0; waitpid(pid, &stat, WUNTRACED); LOGD("ptrace call ret status is %d\n", stat); while (stat != 0xb7f) { if (ptrace_continue(pid) == -1) { LOGD("ptrace call error"); return -1; } waitpid(pid, &stat, WUNTRACED); }
if (ptrace_getregs(pid, regs) == -1) { LOGD("After call getregs error"); return -1; } return 0; }
void* GetModuleBaseAddr(pid_t pid, const char* ModuleName) { FILE *fp = NULL; long ModuleBaseAddr = 0; char *ModulePath, *MapFileLineItem; char szFileName[50] = {0}; char szMapFileLine[1024] = {0}; char szProcessInfo[1024] = {0}; if (pid < 0) { snprintf(szFileName, sizeof(szFileName), "/proc/self/maps"); } else { snprintf(szFileName, sizeof(szFileName), "/proc/%d/maps", pid); } fp = fopen(szFileName, "r"); if (fp != NULL) { while (fgets(szMapFileLine, sizeof(szMapFileLine), fp)) { if (strstr(szMapFileLine, ModuleName)) { MapFileLineItem = strtok(szMapFileLine, " \t"); char *Addr = strtok(szMapFileLine, "-"); ModuleBaseAddr = strtoul(Addr, NULL, 16 ); if (ModuleBaseAddr == 0x8000) ModuleBaseAddr = 0; break; } } fclose(fp) ; } return (void *)ModuleBaseAddr; }
void* GetRemoteFuncAddr(pid_t pid, const char *ModuleName, void *LocalFuncAddr) { void *LocalModuleAddr, *RemoteModuleAddr, *RemoteFuncAddr; LocalModuleAddr = GetModuleBaseAddr(-1, ModuleName); RemoteModuleAddr = GetModuleBaseAddr(pid, ModuleName); RemoteFuncAddr = (void *)((long)LocalFuncAddr - (long)LocalModuleAddr + (long)RemoteModuleAddr); return RemoteFuncAddr; }
int inject_remote_process(pid_t pid,char* LibPath,char* FunctionName,long* FuncParameter ,long NumParameter) { int iRet = -1; struct pt_regs CurrentRegs,OriginalRegs; void *mmap_addr,*dlopen_addr,*dlsym_addr,*dlclose_addr,*dlerror_addr; void *RemoteMapMemoryAddr, *RemoteModuleAddr, *RemoteModuleFuncAddr;
long parameters[6];
if(ptrace_attach(pid) == -1) return iRet;
if(ptrace_getregs(pid,&CurrentRegs) == -1) { ptrace_detach(pid); return iRet; } memcpy(&OriginalRegs,&CurrentRegs,sizeof(struct pt_regs));
mmap_addr = GetRemoteFuncAddr(pid,libc_path,(void*)mmap); LOGD("[+]mmap RemoteFuncAddr:0x%lx", (long)mmap_addr);
parameters[0] = 0; parameters[1] = 0x1000; parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; parameters[4] = 0; parameters[5] = 0; if(ptrace_call(pid , (long)mmap_addr , parameters , 6 , &CurrentRegs)) { LOGD("Call Remote mmap Func Failed"); ptrace_detach(pid); return iRet; }
RemoteMapMemoryAddr = (void*)ptrace_getret(&CurrentRegs); LOGD("[+]Remote Process Map Memory Addr:0x%lx", (long)RemoteMapMemoryAddr);
dlopen_addr = GetRemoteFuncAddr(pid, linker_path, (void *)dlopen); dlsym_addr = GetRemoteFuncAddr(pid, linker_path, (void *)dlsym); dlclose_addr = GetRemoteFuncAddr(pid, linker_path, (void *)dlclose); dlerror_addr = GetRemoteFuncAddr(pid, linker_path, (void *)dlerror);
LOGD("[+]dlopen RemoteFuncAddr:0x%lx", (long)dlopen_addr); LOGD("[+]dlsym RemoteFuncAddr:0x%lx", (long)dlsym_addr); LOGD("[+]dlclose RemoteFuncAddr:0x%lx", (long)dlclose_addr); LOGD("[+]dlerror RemoteFuncAddr:0x%lx", (long)dlerror_addr); if(ptrace_writedata(pid,RemoteMapMemoryAddr,LibPath,strlen(LibPath)+1) == -1) { LOGD("Write LibPath:%s to RemoteProcess error", LibPath); ptrace_detach(pid); return iRet; }
parameters[0] = (long)RemoteMapMemoryAddr; parameters[1] = RTLD_NOW| RTLD_GLOBAL;
if (ptrace_call(pid, (long)dlopen_addr, parameters, 2, &CurrentRegs) == -1) { LOGD("Call Remote dlopen Func Failed"); ptrace_detach(pid); return iRet; }
RemoteModuleAddr = (void *)ptrace_getret(&CurrentRegs); LOGD("Remote Process load module Addr:0x%lx", (long)RemoteModuleAddr); if ((long)RemoteModuleAddr == 0x0) { LOGD("dlopen error"); if (ptrace_call(pid, (long)dlerror_addr, parameters, 0, &CurrentRegs) == -1) { LOGD("Call Remote dlerror Func Failed"); ptrace_detach(pid); return iRet; } char *Error = (void *)ptrace_getret(&CurrentRegs); char LocalErrorInfo[1024] = {0}; ptrace_readdata(pid, Error, LocalErrorInfo, 1024); LOGD("dlopen error:%s", LocalErrorInfo); ptrace_detach(pid); return iRet; }
if (ptrace_writedata(pid, RemoteMapMemoryAddr + strlen(LibPath) + 2, FunctionName, strlen(FunctionName) + 1) == -1) { LOGD("Write FunctionName:%s to RemoteProcess error", FunctionName); ptrace_detach(pid); return iRet; } parameters[0] = (long)RemoteModuleAddr; parameters[1] = (long)(RemoteMapMemoryAddr + strlen(LibPath) + 2); if (ptrace_call(pid, (long)dlsym_addr, parameters, 2, &CurrentRegs) == -1) { LOGD("Call Remote dlsym Func Failed"); ptrace_detach(pid); return iRet; }
RemoteModuleFuncAddr = (void *)ptrace_getret(&CurrentRegs); LOGD("[+]Remote Process ModuleFunc Addr:0x%lx", (long)RemoteModuleFuncAddr);
if (ptrace_call(pid, (long)RemoteModuleFuncAddr, FuncParameter, NumParameter, &CurrentRegs) == -1) { LOGD("Call Remote injected Func Failed"); ptrace_detach(pid); return iRet; }
if (ptrace_setregs(pid, &OriginalRegs) == -1) { LOGD("Recover reges failed"); ptrace_detach(pid); return iRet; } LOGD("Recover Regs Success"); ptrace_getregs(pid, &CurrentRegs); if (memcmp(&OriginalRegs, &CurrentRegs, sizeof(CurrentRegs)) != 0) { LOGD("Set Regs Error"); } if (ptrace_detach(pid) == -1) { LOGD("ptrace detach failed"); return iRet; } return 0;
}
|