ELF Hook原理
2016-04-05 21:12
465 查看
首先写一段C代码,用arm-linux-androideabi-gcc 编译成可执行文件:
图1. C代码Demo
arm-linux-androideabi-objdump -D 反汇编出所有的段,下面的截图,只截取我们感兴趣的几个段:
.text 的<main>
.plt 的 <strlen@plt>
.got
.rodata
.data
1. int b = strlen(helloworld); 函数重定位:
<main>:0x384 中的指令 bl 294 对应C代码中的strlen(helloworld);
bl 294 的机器码是 eb ff ff ff c2, 其中 高8位 eb 是条件跳转指令,低24位是相对于当前PC的偏移地址, 偏移地址 = (目的地址 - 当前PC) >> 2
当前PC 等于当前指令的地址 + 8 所以:offset = (0x294 - (0x384+0x8)) >> 2
(0x294 - (0x384 + 0x8) ) = 0xF8, 用24位补码表示就是FFFF08, 算术右移2位就是FFFFC2
然后<strlen@plt>:294 位置 三条汇编指令,等价于 ip = pc + 0 , ip = ip + 0x1000, pc = [ip + 0xd60]
也就是 将 (0x294 + 0x8) + 0x1000 + 0xd60 = 0x1FFC 指向的内存区的值取出来 赋给PC
我们来看0x1FFC 是在 <_GLOABLE_OFFSET_TABLE>中的表项,内容是0x268, <__libc_init@plt-0x14>的地址,这个应该就是作lazy load用。
再来看0x1FFC地址,图三中 .rel.plt 表 strlen函数对应的offset值。
2. int a = g_strlen(helloworld); 全局函数变量的重定位:
对应的汇编代码在 <main>:0x368-0x378, 写成伪代码如下:
0x368: r3 = [0x3a0] = 0x1c8c
0x36c: r3 = pc + 0x1c8c = 0x36c + 0x08+ 0x1c8c = 0x2000
0x370: r3 = [r3] = [0x2000]
0x378: call r3
图三.rel.dyn 表中 offset = 0x2000 对应的sym name 为strlen.
图二中最后一行也可以看到对应0x2000 的值是0, 当linker链接后会置为符号strlen的实际地址.
图2. 反汇编代码
图3. ELF Header
[libElfHook Demo : https://github.com/wadahana/ElfHook]
[ref : http://blog.csdn.net/l173864930/article/details/40507359]
图1. C代码Demo
arm-linux-androideabi-objdump -D 反汇编出所有的段,下面的截图,只截取我们感兴趣的几个段:
.text 的<main>
.plt 的 <strlen@plt>
.got
.rodata
.data
1. int b = strlen(helloworld); 函数重定位:
<main>:0x384 中的指令 bl 294 对应C代码中的strlen(helloworld);
bl 294 的机器码是 eb ff ff ff c2, 其中 高8位 eb 是条件跳转指令,低24位是相对于当前PC的偏移地址, 偏移地址 = (目的地址 - 当前PC) >> 2
当前PC 等于当前指令的地址 + 8 所以:offset = (0x294 - (0x384+0x8)) >> 2
(0x294 - (0x384 + 0x8) ) = 0xF8, 用24位补码表示就是FFFF08, 算术右移2位就是FFFFC2
然后<strlen@plt>:294 位置 三条汇编指令,等价于 ip = pc + 0 , ip = ip + 0x1000, pc = [ip + 0xd60]
也就是 将 (0x294 + 0x8) + 0x1000 + 0xd60 = 0x1FFC 指向的内存区的值取出来 赋给PC
我们来看0x1FFC 是在 <_GLOABLE_OFFSET_TABLE>中的表项,内容是0x268, <__libc_init@plt-0x14>的地址,这个应该就是作lazy load用。
再来看0x1FFC地址,图三中 .rel.plt 表 strlen函数对应的offset值。
2. int a = g_strlen(helloworld); 全局函数变量的重定位:
对应的汇编代码在 <main>:0x368-0x378, 写成伪代码如下:
0x368: r3 = [0x3a0] = 0x1c8c
0x36c: r3 = pc + 0x1c8c = 0x36c + 0x08+ 0x1c8c = 0x2000
0x370: r3 = [r3] = [0x2000]
0x378: call r3
图三.rel.dyn 表中 offset = 0x2000 对应的sym name 为strlen.
图二中最后一行也可以看到对应0x2000 的值是0, 当linker链接后会置为符号strlen的实际地址.
图2. 反汇编代码
图3. ELF Header
[libElfHook Demo : https://github.com/wadahana/ElfHook]
[ref : http://blog.csdn.net/l173864930/article/details/40507359]
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories