论坛首页 安全编程开发区 阅读主题

[分享]unicorn模拟linker加载so

139 浏览 0 回复
#1 楼主 2026-06-01 21:09:12
搭框架
新建一个项目,然后把ElfParser直接拿来用

把ElfParser当作模块
然后测试一下test能不能跑起来

新建r0dbg-android模块

新建包导入模块

然后把框架搭好
加载
然后就可以实现linker了
从dl_open开始,对比着源码一点点复写do_dlopen的返回值是soinfo,我们也创建个soinfo对象命名为ElfModule
find_library 中  调用了find_library_library_internal返回了soinfo指针,然后做了个引用计数,si->ref_count为0才能释放

find_library_library_internal

elfName的优先级高

find_loaded_library,维护一个列表,如果该so文件已经加载过就不会重复加载

load_library中就是打开该so文件,然后初始化一个ElfReader对象,调用elf_reader.Load方法,最后给soinfo对象初始化一些值Load方法

ReadElfHeader是读elf头 ,VerifyElfHeader是验证elf头格式是否有问题,ReadProgramHeader是读程序头
对应java代码,前三步在ElfFile对象初始化中已经完成

往下看ReserveAddressSpace,主要是调用phdr_table_get_load_size方法,重要的是load_bias_, 他是实际内存地址和期望内存地址的差值。比如实际内存地址为0x1000,期望内存地址为0x100,比如elf文件中要找0x1200,0x1200-0x100=x-0x1000,   x=0x2100 ,   所有0x1200在实际内存中被映射到0x2100,  那么0x1200+(0x1000-0x100)就能找到0x2100
phdr_table_get_load_size中做的事情就是遍历所有程序头,只取p_type=PT_LOAD的元素,找到所有PT_LOAD元素中p_vaddr的最小值赋值给min_vaddr,找到p_vaddr+p_memsz最大值赋值给max_vaddr, 然后页对齐,最后返回所有PT_LOAD段所需内存大小。

ReserveAddressSpace对应的java代码

然后看LoadSegments, 就是把PT_LOAD段加载到内存loadSegments中存放的都是PT_LOAD段,就不用再筛选了
然后回到上面的load_library方法
链接
以上就加载完了,接下来是 链接 和重定位,回到上面代码
接下来看soinfo_link_image

对应的java代码找到PT_DYNAMIC段找到所有tag=DT_NEEDED,意思是需要依赖的其他so文件
dt_StringTable的赋值在这里

dtNeeded的赋值
接下来看重定位操作,soinfo_relocate方法

前置:

然后看soinfo_do_lookup

然后看soinfo_elf_lookup对应的java代码是一样的操作

这里只是单纯的去依赖库里面找
初始化
完成链接和重定位后,回过头来看初始化 ,先调用依赖模块的初始化函数,然后调用自己的初始化函数
对应的java实现模拟执行
注:上述内容均为unidbg原理与实操课程内容,复写一遍使自己记忆深刻一些


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


#基础理论

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-291388.htm

暂无回复,快来抢沙发吧!

请登录后参与讨论

立即登录 注册账号