第62课 inline hook 注入游戏进程

适合游戏外挂的开发

  • 通过 ptrace 注入游戏进程
  • 通过 libsubstrate.so inline hook 替换游戏方法。

注入进程方法

/*************************************************
  Description:    使用ptrace远程call函数
  Input:          pid表示远程进程的ID,ExecuteAddr为远程进程函数的地址
                  parameters为函数参数的地址,regs为远程进程call函数前的寄存器环境
  Output:         无
  Return:         返回0表示call函数成功,返回-1表示失败
  Others:         无
*************************************************
int ptrace_call(pid_t pid, uint32_t ExecuteAddr, long *parameters, long num_params, struct pt_regs* regs)    
{    
    int i = 0;
    
    if (ExecuteAddr == 0 || (parameters == NULL && num_params != 0) || regs == NULL)
        return -1;
    
    // ARM处理器,函数传递参数,将前四个参数放到r0-r3,剩下的参数压入栈中
    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;           //设置ARM_pc寄存器为需要调用的函数地址
    // 与BX跳转指令类似,判断跳转的地址位[0]是否为1,如果为1,则将CPST寄存器的标志T置位,解释为Thumb代码
    // 若为0,则将CPSR寄存器的标志T复位,解释为ARM代码
    if (regs->ARM_pc & 1) {    
        /* thumb */    
        regs->ARM_pc &= (~1u);    
        regs->ARM_cpsr |= CPSR_T_MASK;    
    } else {    
        /* arm */    
        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;  
    // 对于使用ptrace_cont运行的子进程,它会在3种情况下进入暂停状态:①下一次系统调用;②子进程退出;③子进程的执行发生错误。
    // 参数WUNTRACED表示当进程进入暂停状态后,立即返回
    // 将ARM_lr(存放返回地址)设置为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;    
}    

inline hook

/*************************************************
  Description:    程序注入到游戏进程后马上执行的入口函数
  Input:          无
  Output:         无
  Return:         返回0表示成功,返回-1表示失败
  Others:         无
*************************************************/
int Inject_entry()
{
    LOGD("Inject_entry Func is called\n");
    
    void *handle = NULL;
    handle = dlopen("/data/local/tmp/main/libsubstrate.so", RTLD_NOW);
    if(!handle)
    {
        LOGD("dlopen libsubstrate.so fail.\n");
        return -1;
    }
    pfnMSHookFunction MSHookFunction = dlsym(handle, "MSHookFunction");

    handle = NULL;
    handle = dlopen("libcocos2dcpp.so", RTLD_NOW);
    if(!handle)
    {
        LOGD("dlopen libcocos2dcpp.so fail.\n");
        return -1;
    }
    void* uiAddrOfaddBoxAtIndexWithLevel = dlsym(handle, 
        "_ZN10Playground22addBoxAtIndexWithLevelEiib");
    //InlineHook操作
    MSHookFunction((void *)uiAddrOfaddBoxAtIndexWithLevel, 
                   (void *)replaced_addBoxAtIndexWithLevel, 
                   (void **)&old_addBoxAtIndexWithLevel);

    return 0;
}
``

你可能感兴趣的:(第62课 inline hook 注入游戏进程)