搭框架
新建一个项目,然后把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
[分享]unicorn模拟linker加载so
139 浏览
0 回复
暂无回复,快来抢沙发吧!