首页
社区
课程
招聘
[原创]自定义Linker SO修复
发表于: 3小时前 174

[原创]自定义Linker SO修复

3小时前
174

看之前最好是对linker相关的知识有一定了解,这里推荐文章Android从ELF-Loader到自定义Linker的实现及原理,该文章写的很详细,很好。

因为这是一个壳so(Shell SO)内嵌一个so(Payload SO)。system.loadlibray加载壳so,遵循linker加载so的流程。内嵌so是由壳so通过自定义Linker去加载。

本文目的主要针对壳so和内嵌so的修复,方便IDA等工具分析。

ida加载so,主要可以看到这里,大部分节区信息都被抹掉,导致ida无法正常识别。因为ida是静态分析的,所以依赖section节区。

这里的sub_2A30sub_2A50很明显分别是dlopendlsym,但是这里也没有识别出来。

所以后面需要把壳入口.init_array系统函数进行修复还原。

这里会优先执行.init_array节区里的函数,所以先找到这个节区里有哪些函数。

PT_DYNAMIC:动态链接信息节

Program里 PT_DYNAMIC(.dynamic) 找 DT_INIT_ARRAY(d_tag: 0x19)和 DT_INIT_ARRAYSZ (d_tag: 0x1b)

.dynamic里每个表项数据有16字节,相关结构如下。

typedef struct {

Elf64_Sxword d_tag;

union {

} d_un;

} Elf64_Dyn;

.dynamic表数据:

19 00 00 00 00 00 00 00 08 4D 01 00 00 00 00 00

DT_INIT_ARRAY:0x14D08

1B 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00

DT_INIT_ARRAYSZ: 0x10

这里可以看到,.init_array节区起始是0x14D08,大小为0x10个字节,每8个字节为1个函数槽,也就是有两个函数槽在里面。

进入ida查看,这里的地址0x14D08里面怎么没有对应存储的函数呢,接下来就要去.rela.dyn里去找0x14D08地址存储的函数。因为这里是变量赋值,所以要去重定位表.rela.dyn里查看。

这里在节表里没有发现.rela.dyn,看来也是抹除了,所以需要再去.dynamic里找到.rela.dyn并修复。

.dynamic表获取对应数据

07 00 00 00 00 00 00 00 E8 26 00 00 00 00 00 00

DT_RELA : 0x26e8

08 00 00 00 00 00 00 00 48 00 00 00 00 00 00 00

DT_RELASZ: 0x48

然后点开节表所有的SHN_UNDEF,找里面的s_type为SHT_RELA的节,这里找到两个重定位表,那么用哪一个呢?因为.rela.dyn的s_info为0,所以这里我们就选s_info为0的节。

把上面获取的0x26e8和0x48对应填入。然后s_name的偏移也要在.shstrtab里找到.rela.dyn的字符串偏移。

然后F5刷新下修改的文件。

ida打开,在ida里可以看到,有需要被修复的地址就自动填充进去了,这里只有一个函数槽需要被修复。

但是这样感觉还不得劲,想让它的.init_array节区显示出来,继续去SHN_UNDEF找s_type为SHT_INIT_ARRAY

修复后:

这里的s_offset可以不填。我们只保证虚拟内存地址(s_addr)是正确的就行了。

进入ida可以看到.init_array已经被修复了。

进入0x4780系统函数,明显看出sub_2A30是dlopen函数,sub_2A50是dlsym函数,但是这里都是以函数偏移显示的,没有正常的符号名。那么接下来就要修复这类符号名显示问题。

看.dynsym是否正常显示

看来.dynsym里的所有数据也是被抹除了。

06 00 00 00 00 00 00 00 00 90 16 00 00 00 00 00

DT_SYMTAB: 0x169000

原始的是0x2268,所以这里是假的.dynsym。

修复后:

为什么这里s_offset是0x129000?

这里有个小细节,一个程序头表是由多个节表组成,程序头表里,p_offset和p_vaddr的差值是多少,那么应用在对应的节表里时,s_offset和s_addr也应该是这个差值。ida这里工具解析ELF文件时,会以内存的模式去加载,这里就会去把物理文件的偏移s_offset的数据复制到虚拟内存的偏移s_addr处。

因为0x169000刚好处在segment 0x47000~(0x47000+0x1256d0) 这个范围里。p_vaddr是在p_offset的基础上增加了0x40000。所以这里文件偏移应该是0x169000-0x40000=0x129000

函数在010Editor里已经能正常显示了,这里就好了吗?不是,还需要去修复.rela.plt 函数重定位表。

17 00 00 00 00 00 00 00 30 27 00 00 00 00 00 00

DT_JMPREL:0x2730

02 00 00 00 00 00 00 00 40 02 00 00 00 00 00 00

DT_PLTRELSZ:0x240

修复后:

s_flags: 这里需要的模式是ALLOC|INFO_LINK,也就是0x42。

s_link: 链接的节.dynsym,在节表的索引。

s_info: 这是got/.got.plt表在节表的索引。

由上可知,s_info我们还不清楚是多少,并且节表字符串里有.got,这里我们要去修复.got表。

怎么选?

只要s_type为SHT_PROGBITS ,s_flags为SF64_Alloc_Exec ,都可以作为.got表。这里就选节表索引14作为.got表。

查询.dynamic

03 00 00 00 00 00 00 00 18 4F 01 00 00 00 00 00

DT_PLTGOT: 0x14f18

.got表的大小需要自己计算,上面已知DT_PLTRELSZ大小为0x240,因为.rela.plt的每项大小为24字节,这里就有0x240/24=24 个函数,并且.got表的前3个槽位是填充,每个槽位大小为8字节,这里.got size则为(24+3)*8=0xd8

修复后:

这里.got表也修复了,接着就可以补全上面.rela.plt的s_info信息,也就是got表在节表的索引为0xE

ida查看,这里函数符号也都能正常显示了

这里是在init_array里进行内嵌so的解密操作,并用自定义linker去加载内嵌so

init_array的运作函数sub_4780

这些地址处的数据比较重要

dword_15040 = dword_15008;

dword_15064 = dword_1500C;

dword_15078 = dword_15010;

dword_15030 = dword_15014;

dword_15088 = dword_15018;

dword_15084 = dword_1501C;

dword_1507C = dword_15020;

dword_15040:内嵌so在壳so的起始地址

dword_15064:壳.dynsym节区的大小

dword_15078:壳.dynstr节区的大小

dword_15030:壳.dynsym节区在内存里的地址(s_addr)

dword_15088:壳.dynstr节区在内存里的地址(s_addr)

dword_15084:壳.hash节区在内存里的地址(s_addr)

dword_1507C:解密内嵌so的密钥偏移地址

垃圾代码,主要是干扰静态分析的,不用理会

读取dword_1507C地址0x14个字节的内容到qword_15050处,前16个字节是rc4解密的密钥,后4个字节是异或解密的密钥(这里值是单字节)。

010Editor查看可知

rc4密钥:2F CE A7 38 12 73 AC 59 57 7E 56 B5 5F 59 C9 85

xor密钥字节:0x95

sub_3184:rc4解密函数

sub_2B1C:xor异或解密函数

这里解密内嵌so前0x1000字节内容,主要解密出程序头表的内容。用于后续装载PT_Load段数据,和重定位修复。

解密PT_Load

这里是解密第二个PT_Load段

从内嵌so偏移64字节开始解密,这里是解密第一个PT_Load段


[内核课程]《Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

最后于 3小时前 被九天666编辑 ,原因:
收藏
免费 11
打赏
分享
最新回复 (4)
雪    币: 9116
活跃值: (7492)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
3小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
学习
2小时前
0
雪    币: 300
活跃值: (1725)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
学到了
2小时前
0
雪    币: 1549
活跃值: (5108)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
5
666
2分钟前
0
游客
登录 | 注册 方可回帖
返回