我们对so文件的定位是拥有两个导出函数,可以正常被dlopen加载,可以通过dlsym获取我们的函数.
而且根据前面的分析so文件的dynmic段必须具有 DT_HASH, DT_STRTAB , DT_SYMTAB.
这个so文件我们不需要section但必须有program 头.
所以我打算是只定义两个必须的程序头 PT_LOAD 和一个 PT_DYNMIC.
大致安排结构如下.
我们先一步一步来:
所以ELF头的十六进制为:
ELF头之后紧接着就是程序头
现在so文件的内容为
现在我们先不填充DYNMIC段,先全部填充 77.DT_NULL就填充00.为了补齐我们后面也全部填满一行00
现在so文件的内容为
我们打算写两个函数AddNumber,SubNumber.
然后在Android Studio中获取函数的二进制数据即可.
方法1:
调试,在AddNumber,SubNumber,下断,触发这两个函数,当触发时切换到lldb界面
方法2:自己把编译的so文件拖出来定位到指定函数抽取二进制代码吧.
现在so文件的内容为
记录位置:0xD0
我们导入了两个函数所以str表只需要两个字符串
现在so文件的内容为(后面补齐一行0):
记录位置: 0xf0
我们有两个导出函数所以需要2个sym表.但第一个sym表必须是SH_UNDEF.所以有3个.
现在so文件的内容为(后面补齐一行0):
记录位置:0x120
hash表结构
在说hash表之前,我们得先说两个函数.
假如我们调用dlsym(so,"AddNumber");//查找函数地址的时候那么最终会有这样的调用
我们先算一下hash值:
AddNumber:157056866
SubNumber:123495026
因为我们只有2个符号,所以定义
nbucket = 2
那么
157056866 % 2 = 0
157056866 % 2 = 0
那么我们定义如下:
最终定义如下:
我们有两处需要修改的地方
一个是文件大小,一个是dynmic段.
现在我们先把信息汇总一下:
也就是把77 . . . 77 02改为以上内容:
最终so文件的内容为
新建一个ndk项目
写如下代码
native-lib.cpp
把我们手写的meso.so文件放入/data/data/com.example.mi.testmesotes/lib
结束再次运行发现缺奔溃了.
但我们发现打印了一行log.证明加载so文件是成功了,但是缺发生了错误
说明是在调用这两个函数的时候发生了错误.请看到前面我们抽取的函数代码.
我们抽取的函数代码是Thumb.要切换的Thumb一般都是通过把最后一位置为1:但函数Add:753930a0 Sub:753930b8.的地址最后一位都不是1.所以我们需要再次修改so文件.就是把两个sym符号的st_value的最后一位都置为1.
修改如下:
输出log:
证明我们手写的so文件成功了.此处应该有掌声
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)