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

Android PLT/GOT 符号重定向过程

2016-08-14 15:45 369 查看
   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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: