Android PLT/GOT 符号重定向过程

   0x00 项目工程

    项目地址:http://download.csdn.net/detail/jltxgcy/9602851

    下面列出核心代码:

#include "com_example_ndkplt_PLTUtils.h"
#include <android/log.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#define LOG_TAG "PLTUtils"
#define ALOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
//typedef int (*strlen_fun)(const char *);
//strlen_fun global_strlen1 = (strlen_fun)strlen;
//strlen_fun global_strlen2 = (strlen_fun)strlen;
typedef void (*puts_fun)(const char *);
puts_fun global_fun = (puts_fun)puts;
JNIEXPORT jint JNICALL Java_com_example_ndkplt_PLTUtils_pltTest
  (JNIEnv *, jobject) {
	const char *str = "helloworld";

	puts_fun local_fun = (puts_fun)puts;

	local_fun("call the method");
	puts("[+]another call the method of puts from libc.\n");
	global_fun("[+]call the method of puts from libc.\n");
	
	return 0;
}
     
   0x01 分析生成的libPLTUtils.so 

    讲上面的工程使用ndk-build编译生成libPLTUtils.so,这个就是上文Android SO文件结构及readelf命令用来分析的so。

    通过arm-linux-androideabi-readelf -r ~/Public/libPLTUtils.so,得到:

Relocation section '.rel.dyn' at offset 0xc24 contains 10 entries:  
 Offset     Info    Type            Sym.Value  Sym. Name  
00003e80  00000017 R_ARM_RELATIVE     
00003fb4  00000017 R_ARM_RELATIVE     
00003fb8  00000017 R_ARM_RELATIVE     
00003fbc  00000017 R_ARM_RELATIVE     
00003fc0  00000017 R_ARM_RELATIVE     
00003fc8  00000017 R_ARM_RELATIVE     
00003fcc  00000017 R_ARM_RELATIVE     
00004004  00000402 R_ARM_ABS32       00000000   puts  
00003fc4  00000915 R_ARM_GLOB_DAT    00000000   __gnu_Unwind_Find_exid  
00003fd0  00001f15 R_ARM_GLOB_DAT    00000000   __cxa_call_unexpected  
  
Relocation section '.rel.plt' at offset 0xc74 contains 8 entries:  
 Offset     Info    Type            Sym.Value  Sym. Name  
00003fe0  00000216 R_ARM_JUMP_SLOT   00000000   __cxa_atexit  
00003fe4  00000116 R_ARM_JUMP_SLOT   00000000   __cxa_finalize  
00003fe8  00000416 R_ARM_JUMP_SLOT   00000000   puts  
00003fec  00000916 R_ARM_JUMP_SLOT   00000000   __gnu_Unwind_Find_exid  
00003ff0  00000f16 R_ARM_JUMP_SLOT   00000000   abort  
00003ff4  00001116 R_ARM_JUMP_SLOT   00000000   memcpy  
00003ff8  00001c16 R_ARM_JUMP_SLOT   00000000   __cxa_begin_cleanup  
00003ffc  00001d16 R_ARM_JUMP_SLOT   00000000   __cxa_type_match 

    R_ARM_JUMP_SLOT和R_ARM_GLOB_DAT属性的重定位地址一般位于GOT表,R_ARM_COPY和R_ARM_ABS32属性的重定位一般位于.data节或.text节中。

    通过ida打开libPLTUtils.so,可以看到R_ARM_JUMP_SLOT属性,地址为0x00003FE8位于.got段中。而R_ARM_ABS32属性,地址为0x00004004位于.data段中。

.data:00004004 global_fun      DCD __imp_puts          ; DATA XREF: Java_com_example_ndkplt_PLTUtils_pltTest+18o
.got:00003FE8 puts_ptr        DCD __imp_puts          ; DATA XREF: puts+8r
    0x00004004和0x00003FE8这两个地址中的内容,是动态链接时被赋值为libc.so中puts函数的地址。 详细请参考 Android So加载深入分析.pdf


    0x02 全局函数指针,局部函数指针,直接调用函数指针

    先说局部函数指针和直接调用函数指针,他们的操作是一样的。用ida打开libPLTUtils.so,找到Java_com_example_ndkplt_PLTUtils_pltTest函数,下面列出的是动态调试状态下的arm汇编代码。

.text:4C57BD64                 EXPORT Java_com_example_ndkplt_PLTUtils_pltTest
.text:4C57BD64 Java_com_example_ndkplt_PLTUtils_pltTest
.text:4C57BD64
.text:4C57BD64 ; FUNCTION CHUNK AT .text:4C57D2B8 SIZE 00000002 BYTES
.text:4C57BD64
.text:4C57BD64                 LDR     R0, =(aCallTheMethod - 0x4C57BD6C)
.text:4C57BD66                 PUSH    {R3,LR}
.text:4C57BD68                 ADD     R0, PC          ; "call the method"
.text:4C57BD6A                 BL      loc_4C57D2B8
.text:4C57BD6E ; ---------------------------------------------------------------------------
.text:4C57BD6E                 LDR     R0, =(aAnotherCallThe - 0x4C57BD74)
.text:4C57BD70                 ADD     R0, PC          ; "[+]another call the method of puts from"...
.text:4C57BD72                 BL      loc_4C57D2B8
.text:4C57BD76 ; ---------------------------------------------------------------------------
.text:4C57BD76                 LDR     R3, =(global_fun_ptr - 0x4C57BD7E)
.text:4C57BD78                 LDR     R0, =(aCallTheMethodO - 0x4C57BD82)
.text:4C57BD7A                 ADD     R3, PC ; global_fun_ptr
.text:4C57BD7C                 LDR     R3, [R3] ; global_fun
.text:4C57BD7E                 ADD     R0, PC          ; "[+]call the method of puts from libc.\n"
.text:4C57BD80                 LDR     R3, [R3]
.text:4C57BD82                 BLX     R3
.text:4C57BD84                 MOVS    R0, #0
.text:4C57BD86                 POP     {R3,PC}
.text:4C57BD86 ; End of function Java_com_example_ndkplt_PLTUtils_pltTest
     局部函数指针和直接调用函数指针均调用的是loc_4C57D2B8,这个函数如下:

.text:4C57D2B8 loc_4C57D2B8                            ; CODE XREF: Java_com_example_ndkplt_PLTUtils_pltTest+6j
.text:4C57D2B8                                         ; Java_com_example_ndkplt_PLTUtils_pltTest+Ej
.text:4C57D2B8                 BX      PC
.text:4C57D2B8 ; END OF FUNCTION CHUNK FOR Java_com_example_ndkplt_PLTUtils_pltTest
.text:4C57D2B8 ; ---------------------------------------------------------------------------
.text:4C57D2BA                 ALIGN 4
.text:4C57D2BC                 CODE32
.text:4C57D2BC
.text:4C57D2BC ; =============== S U B R O U T I N E =======================================
.text:4C57D2BC
.text:4C57D2BC ; Attributes: thunk
.text:4C57D2BC
.text:4C57D2BC ; int j_puts(const char *s)
.text:4C57D2BC j_puts                                  ; CODE XREF: Java_com_example_ndkplt_PLTUtils_pltTest:loc_4C57D2B8j
.text:4C57D2BC                 LDR     R12, =(puts - 0x4C57D2C8)
.text:4C57D2C0                 ADD     PC, R12, PC ; puts
.text:4C57D2C0 ; End of function j_puts
    在0x4C47D2C0处,PC已经指向了PLT表:

.plt:4C57BCE0 ; int puts(const char *s)
.plt:4C57BCE0 puts                                    ; DATA XREF: j_puts+4o
.plt:4C57BCE0                                         ; .text:off_4C57D2C4o
.plt:4C57BCE0                 ADR     R12, 0x4C57BCE8
.plt:4C57BCE4                 ADD     R12, R12, #0x3000
.plt:4C57BCE8                 LDR     PC, [R12,#(puts_ptr - 0x4C57ECE8)]! ; __imp_puts
    LDR PC, [R12,#(puts_ptr - 0x4C57ECE8)]! 从got表中对应的位置取出puts的地址,并开始执行。而这个对应的位置,就是0x00003fe8:

00003fe8 00000416 R_ARM_JUMP_SLOT 00000000 puts
     局部函数指针和直接调用函数指针,它的重定位类型是R_ARM_JUMP_SLOT,并且位于.re.plt节区,其Offset指向最终调用函数地址的地址(也就是函数指针的指针)。整个过程是先到.plt,再到.got,最后才定位到真正的函数地址。


    接着说全局调用函数指针,在Java_com_example_ndkplt_PLTUtils_pltTest函数中对应的代码是:

.text:4C57BD76                 LDR     R3, =(global_fun_ptr - 0x4C57BD7E)
.text:4C57BD78                 LDR     R0, =(aCallTheMethodO - 0x4C57BD82)
.text:4C57BD7A                 ADD     R3, PC ; global_fun_ptr
.text:4C57BD7C                 LDR     R3, [R3] ; global_fun
.text:4C57BD7E                 ADD     R0, PC          ; "[+]call the method of puts from libc.\n"
.text:4C57BD80                 LDR     R3, [R3]
.text:4C57BD82                 BLX     R3
.text:4C57BD84                 MOVS    R0, #0
.text:4C57BD86                 POP     {R3,PC}
.got:4C57EFB4 global_fun_ptr  DCD global_fun          ; DATA XREF: Java_com_example_ndkplt_PLTUtils_pltTest+16o
.data:4C57F004 global_fun      DCD puts+1              ; DATA XREF: Java_com_example_ndkplt_PLTUtils_pltTest+18o
    通过全局函数指针的方式调用外部函数,它的重定位类型是R_ARM_ABS32,并且位于.rel.dyn节区。

    因此R_ARM_ABS32重定位项的Offset指向最终调用函数地址的地址(也就是函数指针的指针),整个重定位过程是先位到.got,再从.got定位到.date。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值