首页
社区
课程
招聘
[原创]Linux x64 inline hook详解及代码实现
发表于: 2022-5-14 21:15 15933

[原创]Linux x64 inline hook详解及代码实现

2022-5-14 21:15
15933

前段时间需要写一个libc探针,用来监测libc函数的调用,在google和github上找了很久,Windows和Android平台的inline hook都有比较详细的教程,但是Linux平台的教程比较缺乏,所以决定自己写一篇,思路参考了一篇Windows的inline hook文章,链接放在最后。

简单地说,inline hook就是通过直接修改程序的汇编代码来实现hook,举个例子:
假设这是一个函数开头的几条汇编代码

通过inline hook我们可以将其改为这样:

那么,当执行流进入这个函数时,它就会跳转到0x7fffff898688这个地址,并执行这个地址上的代码,我们可以将jmp的地址指定为hook函数的地址,以达到hook的目的

流程

我们的目标是libc中的库函数,所以我们需要先得到libc的基地址
只需要将进程的pid作为参数传入函数就可以得到目标进程的libc基地址

得到libc基地址后,再加上libc函数的偏移地址就可以得到libc函数的实际地址

为什么要保存目标函数的前面几条指令?
如果不在hook函数中调用原函数,那么不保存也行,但是大部分情况下,我们还是需要调用原函数来完成任务的,在后面的步骤中,我们会修改目标函数的前几条指令,如果不保存,就无法再次调用原函数

所以保存几条指令合适呢?
保存几条指令取决于要插入什么指令,inline hook常见的插入指令有三种:

三种指令各有优缺点
||jmp offset|jmp reg|push & ret|
|:-:|:-:|:-:|:-:|
|优点|编码简单,不改变环境|编码相对简单,跳转距离长|跳转距离长,不改变环境
|缺点|跳转距离短|改变环境(寄存器)|编码复杂
|一般适用|32位|32位或64位|64位

我们的inline hook将选择第三种类型的跳转,其硬编码如下所示:

硬编码的长度为14字节,所以我们要将目标函数大于等于十四字节的最少条数指令保存下来(有点绕口,请仔细揣摩)
但是我们如何知道最少应该保存多少字节的机器码呢? 答案是使用capstone

capstone的安装请自行搜索资料,并不是很难安装
通过下面的函数,我们只需要传入一个地址,就能得到应该保存多少字节的机器码

得到函数的返回之后,再使用memcpy从函数开始的地址复制合适个数的字节就行,完整代码会在后面给出

func_hook函数的参数分别是:目标函数的名称,目标函数的hook函数,目标函数的跳板函数(相当与原来的目标函数)
func_hook函数中,我们首先获得了目标函数的地址,然后使用mprotect函数将目标函数所在页的权限改为可读可写可执行,接着获取需要保存的字节数,再分配一块空间来存放保存的指令,在保存指令的后面放一个push&ret跳转,使之回到目标函数保存的指令的后一条指令,这就是跳板函数,执行跳板函数就相当于执行原函数,最后将这个地址赋值给跳板函数

一不小心把第二步和第三步都讲了,不过不影响

这一步比较简单,我们只需要使用push&ret编码覆盖目标函数的开始几条指令,使之跳转到我们写好的hook函数

在第二步的代码后面加三行代码就行

在最后我定义了fopen和fclose的hook函数,并在main函数中安装了hook
编译并运行

输出如下:
开始的两个fopen是因为先安装了fopen的hook,然后在安装fclose的hook的时候调用了fopen,触发了fopen的hook

以上的代码实现了本进程的hook,如果我们想要跨进程hook,可以将代码稍作修改并编译成so,然后使用so注入工具将其注入到其他进程

修改后的代码:

将其编译为so文件

新建一个sample.c文件,文件内容:

编译并运行sample

去github找一个开源的so注入工具 linux_so_injector,按引导构建好项目
新开一个终端,使用ps获取sample的pid,然后使用injector注入so

显示注入成功后,sample的输出如下:
除去最前面的两次fopen,刚好hook了十次

让我们来看看malloc函数的开头几条指令:

mov rdx,QWORD PTR [rip+0x11c3c] 这条指令使用了rip偏移寻址,需要用到当前的rip寄存器的值,如果我们贸然将其保存到跳板函数,当程序执行到跳板函数时,rip已经变了
要想得到正确的执行结果,就必须修改这条指令的偏移

当我们将so注入某个进程时,有可能出现安装hook的同时,进程的其他线程正好执行到了目标函数,这是程序就有可能崩溃

以上两个问题的答案都可以在参考文章中找到答案,本文旨在介绍inline hook,就不针对这两个问题做代码实现了

Windows inline hook详解

push ebp
mov ebp, esp
sub esp, 0x20
push ebp
mov ebp, esp
sub esp, 0x20
jmp 0x7fffff898688
...
jmp 0x7fffff898688
...
//获取libc的基地址
intptr_t get_libc_base(pid_t pid)
{
    intptr_t libcAddr;
    char* buf;
    char* end;
    FILE* fd = fopen("/proc/self/maps", "r");
    if(!fd)
    {
        printf("open maps error!");
        exit(1);
    }
    buf = (char*) malloc(0x100);
    do{
        fgets(buf, 0x100, fd);
    } while(!strstr(buf, "libc-"));
    end = strchr(buf, '-');
    libcAddr = strtol(buf, &end, 16);
    // printf("The process %d's libcbase is: 0x%lx\n", pid, libcAddr);
    fclose(fd);
    return libcAddr;
}
//获取libc的基地址
intptr_t get_libc_base(pid_t pid)
{
    intptr_t libcAddr;
    char* buf;
    char* end;
    FILE* fd = fopen("/proc/self/maps", "r");
    if(!fd)
    {
        printf("open maps error!");
        exit(1);
    }
    buf = (char*) malloc(0x100);
    do{
        fgets(buf, 0x100, fd);
    } while(!strstr(buf, "libc-"));
    end = strchr(buf, '-');
    libcAddr = strtol(buf, &end, 16);
    // printf("The process %d's libcbase is: 0x%lx\n", pid, libcAddr);
    fclose(fd);
    return libcAddr;
}
//获取目标函数的地址
intptr_t get_target_addr(intptr_t libc_base, const char* func_name)
{
    intptr_t funcAddr;
 
    funcAddr = (size_t)dlsym(0, func_name);
    funcAddr -= get_libc_base(getpid());
    funcAddr += libc_base;
    // printf("function %s address is: 0x%lx\n", func_name, funcAddr);
    return funcAddr;
}
//获取目标函数的地址
intptr_t get_target_addr(intptr_t libc_base, const char* func_name)
{
    intptr_t funcAddr;
 
    funcAddr = (size_t)dlsym(0, func_name);
    funcAddr -= get_libc_base(getpid());
    funcAddr += libc_base;
    // printf("function %s address is: 0x%lx\n", func_name, funcAddr);
    return funcAddr;
}
 
 
push Low_address                            ;0x68,0,0,0,0
mov dword ptr ss:[rsp+4], high_address      ;0xC7,0x44,0x24,0x04,0,0,0,0
ret                                         ;0xC3
push Low_address                            ;0x68,0,0,0,0
mov dword ptr ss:[rsp+4], high_address      ;0xC7,0x44,0x24,0x04,0,0,0,0
ret                                         ;0xC3
 
//获取目标函数前几条指令的长度
int get_asm_len(intptr_t target)
{
    csh handle;
    cs_insn* insn;
    size_t count;
    char code[30] = {0};
    int rv;
 
    memcpy((void*)code, (void*)target, 30);
    if(cs_open(CS_ARCH_X86, CS_MODE_64, &handle))
    {
        printf("Error: cs_open\n");
        return -1;
    }
 
    count = cs_disasm(handle, code, 30, 0, 0, &insn);
    if(count)
    {
        for(size_t i = 0; i < count; i++)
        {
            if (insn[i].address >= 14)
            {
                rv = insn[i].address;
                break;
            }
        }
        cs_free(insn, count);
    }
    else
    {
        printf("Error: cs_disasm\n");
        return -1;
    }
    cs_close(&handle);
    return rv;
}
//获取目标函数前几条指令的长度
int get_asm_len(intptr_t target)
{
    csh handle;
    cs_insn* insn;
    size_t count;
    char code[30] = {0};
    int rv;
 
    memcpy((void*)code, (void*)target, 30);
    if(cs_open(CS_ARCH_X86, CS_MODE_64, &handle))
    {
        printf("Error: cs_open\n");
        return -1;
    }
 
    count = cs_disasm(handle, code, 30, 0, 0, &insn);
    if(count)
    {
        for(size_t i = 0; i < count; i++)
        {
            if (insn[i].address >= 14)
            {
                rv = insn[i].address;
                break;
            }
        }
        cs_free(insn, count);
    }
    else
    {
        printf("Error: cs_disasm\n");
        return -1;
    }
    cs_close(&handle);
    return rv;
}
void func_hook(const char* funcname, void* hook_func, void** origin_func)
{
    intptr_t libc_base =  get_libc_base(getpid());
    intptr_t target_addr = get_target_addr(libc_base, funcname);
 
    //根据目标函数的地址确定目标函数所在的页,并将该页的权限改为可读可写可执行
    intptr_t page_start = target_addr & 0xfffffffff000;
    mprotect((void*)page_start, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC);
 
 
    int asm_len = get_asm_len(target_addr);
    if(asm_len <= 0)
    {
        printf("Error: get_asm_len\n");
        exit(-1);
    }
    char* temp_func = (char*)mmap(NULL, 4096, PROT_WRITE|PROT_EXEC|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
 
    memcpy((void*)temp_func, (void*)target_addr, asm_len);
    intptr_t y = (intptr_t)target_addr + asm_len;
    //构造push&ret跳转,填入目标地址
    char jmp_code[14] = {0x68,y&0xff,(y&0xff00)>>8,(y&0xff0000)>>16,(y&0xff000000)>>24,
        0xC7,0x44,0x24,0x04,(y&0xff00000000)>>32,(y&0xff0000000000)>>40,(y&0xff000000000000)>>48,
        (y&0xff00000000000000)>>56,0xC3};
    memcpy((void*)(temp_func+asm_len), (void*)jmp_code, 14);
 
    *origin_func = (void*)temp_func;
}
void func_hook(const char* funcname, void* hook_func, void** origin_func)
{
    intptr_t libc_base =  get_libc_base(getpid());
    intptr_t target_addr = get_target_addr(libc_base, funcname);
 
    //根据目标函数的地址确定目标函数所在的页,并将该页的权限改为可读可写可执行
    intptr_t page_start = target_addr & 0xfffffffff000;
    mprotect((void*)page_start, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC);
 
 
    int asm_len = get_asm_len(target_addr);
    if(asm_len <= 0)
    {
        printf("Error: get_asm_len\n");
        exit(-1);
    }
    char* temp_func = (char*)mmap(NULL, 4096, PROT_WRITE|PROT_EXEC|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
 
    memcpy((void*)temp_func, (void*)target_addr, asm_len);
    intptr_t y = (intptr_t)target_addr + asm_len;
    //构造push&ret跳转,填入目标地址
    char jmp_code[14] = {0x68,y&0xff,(y&0xff00)>>8,(y&0xff0000)>>16,(y&0xff000000)>>24,
        0xC7,0x44,0x24,0x04,(y&0xff00000000)>>32,(y&0xff0000000000)>>40,(y&0xff000000000000)>>48,
        (y&0xff00000000000000)>>56,0xC3};
    memcpy((void*)(temp_func+asm_len), (void*)jmp_code, 14);
 
    *origin_func = (void*)temp_func;
}
 
//替换目标函数的前len个字节,使之跳转到hook函数
void change_bytes(intptr_t addr, const char code[], int len)
{
    memcpy((void*)addr, code, len);
}
 
 
void func_hook(const char* funcname, void* hook_func, void** origin_func)
{
    intptr_t libc_base =  get_libc_base(getpid());
    intptr_t target_addr = get_target_addr(libc_base, funcname);
 
    //根据目标函数的地址确定目标函数所在的页,并将该页的权限改为可读可写可执行
    intptr_t page_start = target_addr & 0xfffffffff000;
    mprotect((void*)page_start, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC);
 
 
    int asm_len = get_asm_len(target_addr);
    if(asm_len <= 0)
    {
        printf("Error: get_asm_len\n");
        exit(-1);
    }
    char* temp_func = (char*)mmap(NULL, 4096, PROT_WRITE|PROT_EXEC|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
 
    memcpy((void*)temp_func, (void*)target_addr, asm_len);
    intptr_t y = (intptr_t)target_addr + asm_len;
    //构造push&ret跳转,填入目标地址
    char jmp_code[14] = {0x68,y&0xff,(y&0xff00)>>8,(y&0xff0000)>>16,(y&0xff000000)>>24,
        0xC7,0x44,0x24,0x04,(y&0xff00000000)>>32,(y&0xff0000000000)>>40,(y&0xff000000000000)>>48,
        (y&0xff00000000000000)>>56,0xC3};
    memcpy((void*)(temp_func+asm_len), (void*)jmp_code, 14);
 
    *origin_func = (void*)temp_func;
 
    intptr_t x = (intptr_t)hook_func;
    char hard_code[14] = {0x68,x&0xff,(x&0xff00)>>8,(x&0xff0000)>>16,(x&0xff000000)>>24,
        0xC7,0x44,0x24,0x04,(x&0xff00000000)>>32,(x&0xff0000000000)>>40,(x&0xff000000000000)>>48,
        (x&0xff00000000000000)>>56,0xC3};
    change_bytes(target_addr, hard_code, 14);
}
//替换目标函数的前len个字节,使之跳转到hook函数
void change_bytes(intptr_t addr, const char code[], int len)
{
    memcpy((void*)addr, code, len);
}
 
 
void func_hook(const char* funcname, void* hook_func, void** origin_func)
{
    intptr_t libc_base =  get_libc_base(getpid());
    intptr_t target_addr = get_target_addr(libc_base, funcname);
 
    //根据目标函数的地址确定目标函数所在的页,并将该页的权限改为可读可写可执行
    intptr_t page_start = target_addr & 0xfffffffff000;
    mprotect((void*)page_start, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC);
 
 
    int asm_len = get_asm_len(target_addr);
    if(asm_len <= 0)
    {
        printf("Error: get_asm_len\n");
        exit(-1);
    }
    char* temp_func = (char*)mmap(NULL, 4096, PROT_WRITE|PROT_EXEC|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
 
    memcpy((void*)temp_func, (void*)target_addr, asm_len);
    intptr_t y = (intptr_t)target_addr + asm_len;
    //构造push&ret跳转,填入目标地址
    char jmp_code[14] = {0x68,y&0xff,(y&0xff00)>>8,(y&0xff0000)>>16,(y&0xff000000)>>24,
        0xC7,0x44,0x24,0x04,(y&0xff00000000)>>32,(y&0xff0000000000)>>40,(y&0xff000000000000)>>48,
        (y&0xff00000000000000)>>56,0xC3};
    memcpy((void*)(temp_func+asm_len), (void*)jmp_code, 14);
 
    *origin_func = (void*)temp_func;
 
    intptr_t x = (intptr_t)hook_func;
    char hard_code[14] = {0x68,x&0xff,(x&0xff00)>>8,(x&0xff0000)>>16,(x&0xff000000)>>24,
        0xC7,0x44,0x24,0x04,(x&0xff00000000)>>32,(x&0xff0000000000)>>40,(x&0xff000000000000)>>48,
        (x&0xff00000000000000)>>56,0xC3};
    change_bytes(target_addr, hard_code, 14);
}
#include<stdio.h>
#include<stdlib.h>
#include<capstone/capstone.h>
#include<unistd.h>
#include<sys/types.h>
#include<dlfcn.h>
#include<sys/mman.h>
#include<string.h>
#include<stdint.h>
 
//获取libc的基地址
intptr_t get_libc_base(pid_t pid)
{
    intptr_t libcAddr;
    char* buf;
    char* end;
    FILE* fd = fopen("/proc/self/maps", "r");
    if(!fd)
    {
        printf("open maps error!");
        exit(1);
    }
    buf = (char*) malloc(0x100);
    do{
        fgets(buf, 0x100, fd);
    } while(!strstr(buf, "libc-"));
    end = strchr(buf, '-');
    libcAddr = strtol(buf, &end, 16);
    // printf("The process %d's libcbase is: 0x%lx\n", pid, libcAddr);
    fclose(fd);
    return libcAddr;
}
 
 
//获取目标函数的地址
intptr_t get_target_addr(intptr_t libc_base, const char* func_name)
{
    intptr_t funcAddr;
 
    funcAddr = (size_t)dlsym(0, func_name);
    funcAddr -= get_libc_base(getpid());
    funcAddr += libc_base;
    // printf("function %s address is: 0x%lx\n", func_name, funcAddr);
    return funcAddr;
}
 
 
//获取目标函数前几条指令的长度
int get_asm_len(intptr_t target)
{
    csh handle;
    cs_insn* insn;
    size_t count;
    char code[30] = {0};
    int rv;
 
    memcpy((void*)code, (void*)target, 30);
    if(cs_open(CS_ARCH_X86, CS_MODE_64, &handle))
    {
        printf("Error: cs_open\n");
        return -1;
    }
 
    count = cs_disasm(handle, code, 30, 0, 0, &insn);
    if(count)
    {
        for(size_t i = 0; i < count; i++)
        {
            if (insn[i].address >= 14)
            {
                rv = insn[i].address;
                break;
            }
        }
        cs_free(insn, count);
    }
    else
    {
        printf("Error: cs_disasm\n");
        return -1;
    }
    cs_close(&handle);
    return rv;
}
 
 
//替换目标函数的前len个字节,使之跳转到hook函数
void change_bytes(intptr_t addr, const char code[], int len)
{
    memcpy((void*)addr, code, len);
}
 
 
void func_hook(const char* funcname, void* hook_func, void** origin_func)
{
    intptr_t libc_base =  get_libc_base(getpid());
    intptr_t target_addr = get_target_addr(libc_base, funcname);
 
    //根据目标函数的地址确定目标函数所在的页,并将该页的权限改为可读可写可执行
    intptr_t page_start = target_addr & 0xfffffffff000;
    mprotect((void*)page_start, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC);
 
 
    int asm_len = get_asm_len(target_addr);
    if(asm_len <= 0)
    {
        printf("Error: get_asm_len\n");
        exit(-1);
    }
    char* temp_func = (char*)mmap(NULL, 4096, PROT_WRITE|PROT_EXEC|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
 
    memcpy((void*)temp_func, (void*)target_addr, asm_len);
    intptr_t y = (intptr_t)target_addr + asm_len;
    //构造push&ret跳转,填入目标地址
    char jmp_code[14] = {0x68,y&0xff,(y&0xff00)>>8,(y&0xff0000)>>16,(y&0xff000000)>>24,
        0xC7,0x44,0x24,0x04,(y&0xff00000000)>>32,(y&0xff0000000000)>>40,(y&0xff000000000000)>>48,
        (y&0xff00000000000000)>>56,0xC3};
    memcpy((void*)(temp_func+asm_len), (void*)jmp_code, 14);
 
    *origin_func = (void*)temp_func;
 
    intptr_t x = (intptr_t)hook_func;
    char hard_code[14] = {0x68,x&0xff,(x&0xff00)>>8,(x&0xff0000)>>16,(x&0xff000000)>>24,
        0xC7,0x44,0x24,0x04,(x&0xff00000000)>>32,(x&0xff0000000000)>>40,(x&0xff000000000000)>>48,
        (x&0xff00000000000000)>>56,0xC3};
    change_bytes(target_addr, hard_code, 14);
}
 
static FILE* (*origin_fopen)(const char* filename, const char* mod);
static int   (*origin_fclose)(FILE* fp);
 
static FILE* fopen_hook(const char* filename, const char* mod)
{
    FILE* rv = origin_fopen(filename, mod);
    printf("fopen(\"%s\", \"%s\")\n\treturn: %p\n", filename, mod, rv);
    return rv;
}
 
static int fclose_hook(FILE* fp)
{
    int rv = origin_fclose(fp);
    printf("fclose(%p)\n\treturn: %d\n", fp, rv);
    return rv;
}
 
int main()
{
    func_hook("fopen", (void*)fopen_hook, (void**)&origin_fopen);
    func_hook("fclose", (void*)fclose_hook, (void**)&origin_fclose);
 
    FILE* file = fopen("sample.txt", "r");
    if (file != NULL)
    {
        fclose(file);
    }
 
    return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<capstone/capstone.h>
#include<unistd.h>
#include<sys/types.h>
#include<dlfcn.h>
#include<sys/mman.h>
#include<string.h>
#include<stdint.h>
 
//获取libc的基地址
intptr_t get_libc_base(pid_t pid)
{
    intptr_t libcAddr;
    char* buf;
    char* end;
    FILE* fd = fopen("/proc/self/maps", "r");
    if(!fd)
    {
        printf("open maps error!");
        exit(1);
    }
    buf = (char*) malloc(0x100);
    do{
        fgets(buf, 0x100, fd);
    } while(!strstr(buf, "libc-"));
    end = strchr(buf, '-');
    libcAddr = strtol(buf, &end, 16);
    // printf("The process %d's libcbase is: 0x%lx\n", pid, libcAddr);
    fclose(fd);
    return libcAddr;
}
 
 
//获取目标函数的地址
intptr_t get_target_addr(intptr_t libc_base, const char* func_name)
{
    intptr_t funcAddr;
 
    funcAddr = (size_t)dlsym(0, func_name);
    funcAddr -= get_libc_base(getpid());
    funcAddr += libc_base;
    // printf("function %s address is: 0x%lx\n", func_name, funcAddr);
    return funcAddr;
}
 
 
//获取目标函数前几条指令的长度
int get_asm_len(intptr_t target)
{
    csh handle;
    cs_insn* insn;
    size_t count;
    char code[30] = {0};
    int rv;
 
    memcpy((void*)code, (void*)target, 30);
    if(cs_open(CS_ARCH_X86, CS_MODE_64, &handle))
    {
        printf("Error: cs_open\n");
        return -1;
    }
 
    count = cs_disasm(handle, code, 30, 0, 0, &insn);
    if(count)
    {
        for(size_t i = 0; i < count; i++)
        {
            if (insn[i].address >= 14)
            {
                rv = insn[i].address;
                break;
            }
        }
        cs_free(insn, count);
    }
    else
    {
        printf("Error: cs_disasm\n");
        return -1;
    }
    cs_close(&handle);
    return rv;
}
 
 
//替换目标函数的前len个字节,使之跳转到hook函数
void change_bytes(intptr_t addr, const char code[], int len)
{
    memcpy((void*)addr, code, len);
}
 
 
void func_hook(const char* funcname, void* hook_func, void** origin_func)
{
    intptr_t libc_base =  get_libc_base(getpid());
    intptr_t target_addr = get_target_addr(libc_base, funcname);
 
    //根据目标函数的地址确定目标函数所在的页,并将该页的权限改为可读可写可执行
    intptr_t page_start = target_addr & 0xfffffffff000;
    mprotect((void*)page_start, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC);
 
 
    int asm_len = get_asm_len(target_addr);
    if(asm_len <= 0)
    {
        printf("Error: get_asm_len\n");
        exit(-1);
    }
    char* temp_func = (char*)mmap(NULL, 4096, PROT_WRITE|PROT_EXEC|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
 
    memcpy((void*)temp_func, (void*)target_addr, asm_len);
    intptr_t y = (intptr_t)target_addr + asm_len;
    //构造push&ret跳转,填入目标地址
    char jmp_code[14] = {0x68,y&0xff,(y&0xff00)>>8,(y&0xff0000)>>16,(y&0xff000000)>>24,
        0xC7,0x44,0x24,0x04,(y&0xff00000000)>>32,(y&0xff0000000000)>>40,(y&0xff000000000000)>>48,
        (y&0xff00000000000000)>>56,0xC3};
    memcpy((void*)(temp_func+asm_len), (void*)jmp_code, 14);
 
    *origin_func = (void*)temp_func;
 
    intptr_t x = (intptr_t)hook_func;
    char hard_code[14] = {0x68,x&0xff,(x&0xff00)>>8,(x&0xff0000)>>16,(x&0xff000000)>>24,
        0xC7,0x44,0x24,0x04,(x&0xff00000000)>>32,(x&0xff0000000000)>>40,(x&0xff000000000000)>>48,
        (x&0xff00000000000000)>>56,0xC3};
    change_bytes(target_addr, hard_code, 14);
}
 
static FILE* (*origin_fopen)(const char* filename, const char* mod);

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 12
支持
分享
最新回复 (7)
雪    币: 380
活跃值: (840)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
tql!!! orz
2022-5-14 21:29
1
雪    币: 178
活跃值: (8389)
能力值: ( LV13,RANK:438 )
在线值:
发帖
回帖
粉丝
3
学习一下
2022-5-15 08:20
0
雪    币: 6704
活跃值: (4682)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2022-5-15 08:54
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
哈喽,这里不需要保存原始的执行环境吗,push pop之类的,那我们的hook函数破坏了堆栈和寄存器的话,原始函数怎么执行呢?
2023-3-20 17:00
0
雪    币: 213
活跃值: (210)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
牛的。大佬受我一拜。
2023-6-6 15:02
0
雪    币: 3785
活跃值: (3947)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
感谢分享。
2023-6-6 15:13
0
雪    币: 3573
活跃值: (31026)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
感谢分享
2023-6-7 09:06
1
游客
登录 | 注册 方可回帖
返回
//