首页
社区
课程
招聘
[分享]unicorn模拟linker加载so
发表于: 1天前 429

[分享]unicorn模拟linker加载so

1天前
429

搭框架

新建一个项目,然后把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原理与实操课程内容,复写一遍使自己记忆深刻一些





传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 4
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回