动态库加载后的函数解析

综述       

最近做一个demo,简单来说就是通过ptrace的功能,把自己写的一个so(内有咱们要hook后的函数实现),动态加载到目标程序后,通过修改GOT表的方式,把目标函数替换成咱们自己的函数,后面在目标程序的代码里,再调用该函数时,调用的就是咱们hook后的函数。这种实现方式之前被广泛的用在外挂开发、动态调试等领域,也是hacker们的一种手段。

      闲话少说,进入正文,本文的重点放在动态加载后的函数解析上,具体demo的实现过程可以参考下面链接:

https://xz.aliyun.com/t/6883#reply-14029

PS:这个demo有代码可以直接下载,编译后直接运行,但有几个小bug,在此就不贴出来了,大家可以自行查找并修改,主要是内存泄漏以及遍历取得link_map信息时候的一些细节上;

我hook了malloc函数:

实现后,跟同事讨论这个问题,为什么在hook_so里的MyMalloc里调用malloc——在上面的demo里是newputs 和 puts——不会出现递归调用,现象就是死循环,简单来说,就是在主程序里调用malloc调用的是MyMalloc,而在MyMalloc里调用malloc时,调用的就是glibc里的malloc?

这里面涉及到动态加载的一些知识点,在这里不展开描述,感兴趣的同学可以搜索一下 ELF、动态加载等关键字;

下面就说一下我的分析过程;

测试1

首先跟大家安利一个gdb调试的神器插件:peda,下载链接:

https://github.com/longld/peda

参考了这个链接的调试过程:

http://rickgray.me/2015/08/07/use-gdb-to-study-got-and-plt/

自己写了一个简单的target程序:

编译后GDB之,前面不管,在84行打断点:

查看一下:

一句话总结就是:

”在程序刚开始运行时,GOT 表项是空的,当符号第一次被调用时会动态解析符号的绝对地址然后转去执行,并将被解析符号的绝对地址记录在 GOT 中,第二次调用同一符号时,由于 GOT 中已经记录了其绝对地址,直接转去执行即可(不用重新解析)“

——http://rickgray.me/2015/08/07/use-gdb-to-study-got-and-plt/

再执行下面的86行malloc时,就不需要再次解析了,而是直接通过GOT-->PLT-->绝对地址:

测试2

下面进行另外的测试,重启启动目标程序,然后在第一个malloc和第二个malloc之间,使用hook技术,对malloc进行hook,那么hook后马上detach,然后gdb attach之;

替换的目标函数是malloc,替换后的MyMalloc如下:

 

开始调试:

可以看到,当hook后,第一次解析MyMalloc里的malloc时,是通过so中的GOT来进行寻址的;

这里也展示出:主程序中的GOT和hook方式加入的so中的GOT是两个不同的GOT!!!

——其实对我来说,这是我做这个测试的最需要的答案。

下面接续最后一个malloc的解析:

顺便说一句,通过target的打印,可以看到hook已经成功,调用malloc时,实际上调用的已经是MyMalloc了;

最后一个malloc的解析过程,和上面一个的malloc的解析是完全一样的,即:在主程序中通过GOT和PLT寻址到MyMalloc,然后在so中,再通过so的GOT和PLT寻址到malloc的调用——这里对应的是glibc的malloc的地址;就不再贴图了,感兴趣的可以自己去尝试一下下;

 

总结

1.主程序中的malloc的调用——如果没有动态注入so的情况下——第一次调用malloc时,会有一个重定位的过程,第一次重定位完成后,就会把malloc的绝对地址写入到GOT中,后面再调用malloc时,就不用再进行重定位了,直接通过GOT和PLT定位到函数地址;

2.动态注入so的情况下,进行了malloc的hook,那么除了主程序的GOT和PLT寻址,还需要so内的GOT和PLT寻址,通过这种方式来实现真正的malloc的调用;

 

当前对GOT和PLT的理解还很肤浅,本文中的描述可能存在不准确的地方,如果错误,敬请指正,谢谢;

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lqw198421

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值