1. 程式人生 > >ELF Hook原理

ELF Hook原理


首先寫一段C程式碼,用arm-linux-androideabi-gcc 編譯成可執行檔案:



圖1. C程式碼Demo

arm-linux-androideabi-objdump -D 反彙編出所有的段,下面的截圖,只擷取我們感興趣的幾個段:


     .text 的<main>      .plt 的 <[email protected]>      .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
    然後<[email protected]>:294 位置 三條彙編指令,等價於 ip = pc + 0 ,  ip = ip + 0x1000, pc = [ip + 0xd60]     也就是 將 (0x294 + 0x8) + 0x1000 + 0xd60 = 0x1FFC 指向的記憶體區的值取出來 賦給PC
    我們來看0x1FFC 是在 <_GLOABLE_OFFSET_TABLE>中的表項,內容是0x268, <
[email protected]
>的地址,這個應該就是作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]