基于Android的ELF PLT/GOT符号重定向过程及ELF Hook实现(by 低端码农 2014.10.27)

基于Android的ELF PLT/GOT符号重定向过程及ELF Hook实现——by 低端码农 2014.10.27引言写这篇技术文的原因,主要有两个:其一是发现网上大部分描述PLT/GOT符号重定向过程的文章都是针对x86的,比如《Redirecting functions in shared ELF libraries》就写得非常不错。虽然其过程跟ARM非常类似,但由于C
摘要由CSDN通过智能技术生成


引言

写这篇技术文的原因,主要有两个:

  • 其一是发现网上大部分描述PLT/GOT符号重定向过程的文章都是针对x86的,比如《Redirecting functions in shared ELF libraries》就写得非常不错。虽然其过程跟ARM非常类似,但由于CPU体系不同,指令实现差异非常大;
  • 其二是网上大部分关于ELF文件格式的介绍,都是基于链接视图(Linking View),链接视图是基于节(Section)对ELF进行解析的。然而动态链接库在加载的过程中,linker只关注ELF中的段(Segment)信息。因此ELF中的节信息被完全篡改或者甚至删除掉,并不会影响linker的加载过程,这样做可以防止静态分析工具(比如IDA,readelf等)对其进行分析,一般加过壳的ELF文件都会有这方面的处理。对于这种ELF文件,如果要实现hook功能,则必须要基于执行视图(Execution View)进行符号解析;

准备

在往下阅读之前,请先确保对ELF文件格式和ARM汇编有个大概了解,参考指引:

准备工具:

  • readelf(NDK包含)
  • objdump(NDK包含)
  • IDA Pro 6.4或以上
  • Android真机或者模拟器

符号重定向

在ARM上,常见的重定向类型,主要有三种,分别是R_ARM_JUMP_SLOTR_ARM_ABS32R_ARM_GLOB_DAT,而我们要hook elf函数,则需要同时处理好这三种重定向类型。

例子

先看示例代码

typedef int (*strlen_fun)(const char *);
strlen_fun global_strlen1 = (strlen_fun)strlen;
strlen_fun global_strlen2 = (strlen_fun)strlen;

#define SHOW(x) LOGI("%s is %d", #x, x)

extern "C" jint Java_com_example_allhookinone_HookUtils_elfhook(JNIEnv *env, jobject thiz){
    const char *str = "helloworld";

    strlen_fun local_strlen1 = (strlen_fun)strlen;
    strlen_fun local_strlen2 = (strlen_fun)strlen;

    int len0 = global_strlen1(str);
    int len1 = global_strlen2(str);
    int len2 = local_strlen1(str);
    int len3 = local_strlen2(str);
    int len4 = strlen(str);
    int len5 = strlen(str);

    SHOW(len0);
    SHOW(len1);
    SHOW(len2);
    SHOW(len3);
    SHOW(len4);
    SHOW(len5);

    return 0;
}


这段代码分别以三种不同的方式调用strlen,分别是全局函数指针、局部函数指针以及直接调用,下而我们针对这个例子,分别对三种调用分析进行分析。

先通过readelf,我们查看一下重定向表,如下所示:

Relocation section '.rel.dyn' at offset 0x2a48 contains 17 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0000ade0  00000017 R_ARM_RELATIVE   
0000af00  00000017 R_ARM_RELATIVE   
0000af0c  00000017 R_ARM_RELATIVE   
0000af10  00000017 R_ARM_RELATIVE   
0000af18  00000017 R_ARM_RELATIVE   
0000af1c  00000017 R_ARM_RELATIVE   
0000af20  00000017 R_ARM_RELATIVE   
0000af24  00000017 R_ARM_RELATIVE   
0000af28  00000017 R_ARM_RELATIVE   
0000af30  00000017 R_ARM_RELATIVE   
0000aefc  00003215 R_ARM_GLOB_DAT    00000000   __stack_chk_guard
0000af04  00003715 R_ARM_GLOB_DAT    00000000   __page_size
0000af08  00004e15 R_ARM_GLOB_DAT    00000000   strlen
0000b004  00004e02 R_ARM_ABS32       00000000   strlen
0000b008  00004e02 R_ARM_ABS32       00000000   strlen
0000af14  00006615 R_ARM_GLOB_DAT    00000000   __gnu_Unwind_Find_exid
0000af2c  00007415 R_ARM_GLOB_DAT    00000000   __cxa_call_unexpected

...
...

Relocation section '.rel.plt' at offset 0x2ad0 contains 48 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0000af40  00000216 R_ARM_JUMP_SLOT   00000000   __cxa_atexit
0000af44  00000116 R_ARM_JUMP_SLOT   00000000   __cxa_finalize
0000af48  00001716 R_ARM_JUMP_SLOT   00000000   memcpy
...
0000afd4  00004c16 R_ARM_JUMP_SLOT   00000000   fgets
0000afd8  00004d16 R_ARM_JUMP_SLOT   00000000   fclose
0000afdc  00004e16 R_ARM_JUMP_SLOT   00000000   strlen
0000afe0  00004f16 R_ARM_JUMP_SLOT   00000000   strncmp
...
...


在.rel.plt和.rel.dyn两个section中,我们发现一共出现了4个strlen,我们先把它们的关键信息记录下来,后面分析会非常有用。它们分别是

.rel.dyn 0000AF08 R_ARM_GLOB_DAT

.rel.dyn 0000B004 R_ARM_ABS32.rel.dyn 0000B008 R_ARM_ABS32.rel.plt 0000
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值