我会解释一下:
假设我有兴趣替换rand()某个应用程序使用的函数.
所以我将gdb附加到此进程并使其加载我的自定义共享库(具有自定义rand()函数):
call (int) dlopen("path_to_library/asdf.so")
这会将自定义rand()函数放在进程的内存中.但是,此时符号rand仍将指向默认rand()功能.有没有办法让gdb将符号指向新rand()函数,迫使进程使用我的版本?
我必须说我也不允许使用LD_PRELOAD(linux)或DYLD_INSERT_LIBRARIES(mac os x)方法,因为它们只允许在程序执行开始时注入代码.
我想要替换的应用程序rand()启动多个线程,其中一些启动新进程,我有兴趣在其中一个新进程上注入代码.正如我上面提到的,GDB非常适合这个目的,因为它允许代码注入特定的进程.
Ale*_*x B 12
我按照这篇文章和本演示文稿,为OSX提供了以下一组带有x86-64可执行文件的gdb命令,可以-x在附加到进程时加载选项:
set $s = dyld_stub_rand
set $p = ($s+6+*(int*)($s+2))
call (void*)dlsym((void*)dlopen("myrand.dylib"), "my_rand")
set *(void**)$p = my_rand
c
神奇的是set $p = ...命令.dyld_stub_rand是一个6字节的跳转指令.跳转偏移量为dyld_stub_rand+2(4个字节).这是一个$rip相对跳跃,因此$rip在此时(在指令之后dyld_stub_rand+6)添加偏移量.
这指向一个符号表条目,它应该是rand加载它的实际或动态链接器例程(如果它从未被调用过).然后它被替换为my_rand.
有时gdb dyld_stub_rand将从libSystem或其他共享库中获取,如果发生这种情况,请remove-symbol-file在运行其他命令之前先将其卸载.
这个问题引起了我的兴趣,所以我做了一点研究.您正在寻找的是' dll注入 '.你编写了一个函数来替换一些库函数,把它放在.so中,并告诉ld预加载你的dll.我只是试了一下,效果很好!我意识到这并没有真正回答你关于gdb的问题,但我认为它提供了一个可行的解决方法.
对于仅限gdb的解决方案,请参阅我的其他解决方案.
// -*- compile-command: "gcc -Wall -ggdb -o test test.c"; -*-
// test.c
#include "stdio.h"
#include "stdlib.h"
int main(int argc, char** argv)
{
    //should print a fairly random number...
    printf("Super random number: %d\n", rand());
    return 0;
}
/ -*- compile-command: "gcc -Wall -fPIC -shared my_rand.c -o my_rand.so"; -*-
//my_rand.c
int rand(void)
{
    return 42;
}
编译两个文件,然后运行:
LD_PRELOAD="./my_rand.so" ./test
Super random number: 42
我有一个新的解决方案,基于 新原始约束.(我没有删除我的第一个答案,因为其他人可能觉得它很有用.)  
我一直在做一堆研究,我认为它会更有效.
info functions找到的地址rand在符号表使用dlopen然后dlsym将函数加载到内存中并获取其地址
call (int) dlopen("my_rand.so", 1) - > -val-
call (unsigned int) dlsym(-val-, "my_rand") - > my_rand_addr
jumpq 0x*my_rand_addr*指令的十六进制代码set {int}*rand_addr* = *my_rand_addr*改变符号表指示Continue执行:现在,每当rand被调用时,它会跳到my_rand代替这有点复杂,非常圆润,但我很确定它会起作用.我还没有完成的唯一事情是创建jumpq指令代码.到目前为止一切正常.
| 归档时间: | 
 | 
| 查看次数: | 5591 次 | 
| 最近记录: |