elf可执行文件如何动态加载一个so

elf可执行文件如何动态加载一个so,第1张

有三个做法:

1、在elf尾部插入shellcode,然后,修改elf文件的最后一个pt_load段头的增长该段的长度。把DT_INIT节或DT_INITARRAY的指针指向你的shellcode里,一般的加固技术也是这种做法。

2、把这个elf文件A打包到另一个elf文件B里面去,在B里干完你要干的事情后,再加载A,如果不想把A释放到文件系统里,就要自己实现一个linker。娜迦的加固也是这样做的。

3、修改elf文件里的DYNAMIC节,添加一个类型为DT_NEEDED的节点,还要把要加载的so的名字写入到DT_STRSZ节里去,由于elf文件里的里的地址都是写死的,不一定有空位置让你插一个新的结点,可能要抹掉现有的才有位置插,如果对llvm熟悉,可以利用llvm把elf文件转换成一个地址无关的lir语言,再进行修改。

Android下so注入是基于ptrace系统调用,因此要想学会android下的so注入,首先需要了解ptrace的用法。

ptrace用法可以参考博客:http://blog.sina.com.cn/s/blog_4ac74e9a0100n7w1.html,也可以在ubuntu下输入man ptrace命令,查看具体描述。

android中进程系统调用劫持可参考博客:http://www.kanxue.com/bbs/showthread.php?t=180461,这是一个android简单的ptrace监控远程进程监控调用的例子。

Android系统是基于Linux系统,在linux系统中可以通过ptrace系统调用实现进程注入。ptrace注入过程大致过程如下:

(1)基于shellcode加载

[1]编写shellcode,shellcode是使用汇编语言写一段汇编程序,该程序实现so库的加载、so库函数查找以及执行库中的函数。

[2]通过远程进程pid,ATTACH到远程进程。

[3]获取远程进程寄存器值,并保存,以便注入完成后恢复进程原有状态。

[4]获取远程进程系统调用mmap、dlopen、dlsym调用地址。

[5]调用远程进程mmap分配一段存储空间,并在空间中写入shellcode、so库路径以及函数调用参数。

[6]执行远程进程shellcode代码。

[7]恢复远程进程寄存器。

[8]detach远程进程。

基于shellcode注入可看雪古河大哥写的libInject,网址: http://bbs.pediy.com/showthread.php?t=141355

(2)直接加载

[1]通过远程进程pid,ATTACH到远程进程。

[2]获取远程进程寄存器值,并保存,以便注入完成后恢复进程原有状态。

[3]获取远程进程系统调用mmap、dlopen、dlsym调用地址。

[4]调用远程进程mmap分配一段存储空间,并在空间中写入so库路径以及函数调用参数。

[5]执行远程进程dlopen,加载so库。

[6]执行远程进程dlsym,获取so库中需要执行的函数地址。

[7]执行远程进程中的函数。

[7]恢复远程进程寄存器。

[8]DETACH远程进程。

目前android so注入的版本基本上都是基于古河大哥的libInject修改而来。关于so注入的项目,还可以参考洗大师的一个开源项目,网址:https://code.google.com/p/libandroidinjector/downloads/list。洗大师注入需要修改elf文件。

提供一个方便测试so注入成功与否的小测试库,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

#include <unstd.h>

#include <stdio.h>

#include <android/log.h>

#define LOG_TAG"test"

__attribute__((constructor))

void

inject

()

{

__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,"Hello,I

am injected.")

}

说明:若函数被设定为constructor属性,则该函数会在main()函数执行之前被自动的执行。因此,so注入测试中,只需注入以上代码编译的so库,无需调用注入so的相关函数,即可测试是否注入到远程进程。

你好,我现在能够用NDK的如下方式写几个简单的文件,然后打包为SO,再用另外的一个.C文件调用SO,然后生成最终的供Android使用的SO文件,具体方式如下:

下载一个从android模拟器里取system lib的工具busybox,然后调用命令

$adb push busybox /dev/sample/busybox

$adb shell chmod 777 /dev/sample/busybox

$adb shell ./dev/sample/busybox tar -cf /dev/sample/libs.tar /system/lib

$adb pull /dev/sample/libs.tar libs.tar

这样就将模拟器下的 /system/lib 目录的所有库(so)文件打包并下载下来了,解压libs.tar就得到了我们所需要的所有库文件。

接着将所有的文件copy 到 $(NDK)\build\prebuilt\windows\arm-eabi-4.2.1\lib\gcc\arm-eabi\4.2.1,这个时候基本的配置工作就结束了。

然后建立tutorial01.c调用tutorial02.c中的方法,通过写makefile文件将之打包为SO

CC = /cygdrive/e/android-ndk-1.5_r1/build/prebuilt/windows/arm-eabi-4.2.1/bin/arm-eabi-gcc

CFLAGS = -g -O2 -fPIC -DANDROID -I ./ -I ../ -I /cygdrive/e/android-ndk-1.5_r1/build/platforms/android-1.5/arch-arm/usr/include

SDFLAGS = -nostdlib -Wl,-T,armelf.xsc -Wl,-soname,$@ -Wl,-shared,-Bsymbolic -lc

CRT_OBJS= -lz -lm

# source files:

SRCS= tutorial01.c tutorial02.c tutorial02.h

all: libtutorial.so

libtutorial.so: tutorial01.o tutorial02.o

$(CC) $(SDFLAGS) -o $@ tutorial01.o tutorial02.o $(CRT_OBJS)

tutorial01.o: tutorial02.h

tutorial02.o: tutorial02.h

clean:

rm -f libtutorial.so *.o

然后make,这个时候会报错 can't find "armelf.xsc", 在ndk的目录里搜索一下,搜到之后copy 到$(NDK)\build\prebuilt\windows\arm-eabi-4.2.1\lib\gcc\arm-eabi\4.2.1,然后make,成功。

接着建立一个文件test01.c,动态加载so文件,然后写一个makefile文件,最后make成功。

建立一个Android工程 testapp来测试其运行情况,实验表明是能够正确运行的。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11860384.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-19
下一篇 2023-05-19

发表评论

登录后才能评论

评论列表(0条)

保存