您的位置:首页 > 移动开发 > Android开发

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]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  APIHook ELFHook PLT GOT Android