Android下实现injectso

http://photonwen.i.sohu.com/blog/view/201923753.htm 

 

参考资料

Linux中ELF文件动态链接的加载、解析及实例分析
ELF动态解析符号过程
android linker 浅析
ORACLE链接程序和库指南
Modern Day ELF Runtime infection via GOT poisoning
 
看了几天elf,找到不少文章,不过大多写的很难看明白,上面的链接里最后一个还算比较清晰。
不过我关心的是arm下的,而找到的资料大多是x86下的,还是有些不一样。
写了个小程序,里面定义了myfunc函数,这个函数里调用了dlopen。在android ndk环境下编译通过。
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 void myfunc(){
  4     dlopen("sdfasdfa",2);
  5 }
  6 main(){   
  7     myfunc();
  8 }
 
下面我用objdump和readelf来分析下dlopen这个外部函数是如何被调用的。
 
不废话,直接看看
 
00008570 <myfunc>:
    8570:   4803        ldr r0, [pc, #12]   ; (8580 <myfunc+0x10>)
    8572:   2102        movs    r1, #2
    8574:   b510        push    {r4, lr}
    8576:   4478        add r0, pc               //r0,r1保存调用参数
    8578:   f7ff efd0   blx 851c <_start-0x24>  //原来dlopen的地址在0x851c
    857c:   bd10        pop {r4, pc}
    857e:   bf00        nop  
    8580:   0000150e    andeq   r1, r0, lr, lsl #10
    ...
接着在.plt里找到了0x851c
 
000084d8 <.plt>:
    84d8:   e52de004    push    {lr}        ; (str lr, [sp, #-4]!)
    84dc:   e59fe004    ldr lr, [pc, #4]    ; 84e8 <_start-0x58> //lr = 0x9790
    84e0:   e08fe00e    add lr, pc, lr  //lr = 0x9790+0x84e8
    84e4:   e5bef008    ldr pc, [lr, #8]!  //pc = [ 0x9790+0x84e8+8] = [0x11C80]
    84e8:   00009790    muleq   r0, r0, r7
    84ec:   e28fc600    add ip, pc, #0
    84f0:   e28cca09    add ip, ip, #36864  ; 0x9000
    84f4:   e5bcf790    ldr pc, [ip, #1936]!    ; 0x790
    84f8:   e28fc600    add ip, pc, #0
    84fc:   e28cca09    add ip, ip, #36864  ; 0x9000
    8500:   e5bcf788    ldr pc, [ip, #1928]!    ; 0x788
    8504:   e28fc600    add ip, pc, #0
    8508:   e28cca09    add ip, ip, #36864  ; 0x9000
    850c:   e5bcf780    ldr pc, [ip, #1920]!    ; 0x780
    8510:   e28fc600    add ip, pc, #0
    8514:   e28cca09    add ip, ip, #36864  ; 0x9000
    8518:   e5bcf778    ldr pc, [ip, #1912]!    ; 0x778
     851c:   e28fc600    add ip, pc, #0       //注意:pc总是指向当前地址+8
     8520:   e28cca09    add ip, ip, #36864  ; 0x9000
    8524:   e5bcf770    ldr pc, [ip, #1904]!    ; 0x770   //pc=[0x8524+0x9000+0x770]=[0x11c94]
    8528:   e28fc600    add ip, pc, #0
    852c:   e28cca09    add ip, ip, #36864  ; 0x9000
    8530:   e5bcf768    ldr pc, [ip, #1896]!    ; 0x768
    8534:   e28fc600    add ip, pc, #0
    8538:   e28cca09    add ip, ip, #36864  ; 0x9000
    853c:   e5bcf760    ldr pc, [ip, #1888]!    ; 0x760
 
0x11c94是.got节中的一项
 
Disassembly of section .got:
 
00011c78 <_GLOBAL_OFFSET_TABLE_>:
   11c78:   00011b90    muleq   r1, r0, fp
   11c7c
   11c80
    ...
   11c84:   000084d8    ldrdeq  r8, [r0], -r8
   11c88:   000084d8    ldrdeq  r8, [r0], -r8
   11c8c:   000084d8    ldrdeq  r8, [r0], -r8
   11c90:   000084d8    ldrdeq  r8, [r0], -r8
    11c94:   000084d8    ldrdeq  r8, [r0], -r8    
   11c98:   000084d8    ldrdeq  r8, [r0], -r8
   11c9c:   000084d8    ldrdeq  r8, [r0], -r8
    ...
 
所以pc现在指向0x84d8,看最前面的.plt节,就知道这就是plt0
plt0会跳转到[0x11C80],注意这个0x11c80也在.got节里。
 
从上面的分析得到一个疑惑,无论调用哪个外部函数都会去调用plt0,可plt0怎么知道我们到底在调用哪个外部函数? x86平台下是有传参数(got中的地址,和函数对应的符号表项)。在arm下我是没看到什么参数,只有ip比较可疑(见 绿色行)。
 
不过Android下现在是不支持lazy binding的,所以就算上面的plt0只是个摆设也没关系。可执行文件加载时其调用的外部函数对应的.got项就被修改了。这只是猜测,为了验证现在去看看linker的实现。
 
 
 

你可能感兴趣的:(android,injectso)