1. 重建phdr
由于从内存中dump,将文件偏移和大小 覆写为 内存大小和偏移。
2. 获取Dynamic load
牛的 , 从program header 中获取找到PT_DYNAMIC 。将dynamic 作为构建section header 的关键信息。
3. 重建section header
我们知道dynamic 记录中有很多信息,如图
这其实和section entry 很多信息有很多重合部分。
仅将dynamic 存在的记录还原到section header。
4. 重建重定位
原本以为sofix 这个项目不用传基址,是有特殊方法算出来。结果是不传偏移那么就不做重定位表的修复。
内部模块的重定位 : *目标地址 = *目标地址 – base
外部模块的重定位: 讲道理没有看懂 , 实际上可能不需要做修复。*目标地址 = syminfo.st_value ? 这个值的作用,这个介绍说可能是一个地址也可能是一个偏移。。。,。。。嗯。。没有说出具体什么情况是偏移,什么时候是个地址。
template <bool isRela>
void ElfRebuilder::relocate(uint8_t * base, Elf_Rel* rel, Elf_Addr dump_base) {
if(rel == nullptr) return ;
#ifndef __SO64__
auto type = ELF32_R_TYPE(rel->r_info);
auto sym = ELF32_R_SYM(rel->r_info);
#else
auto type = ELF64_R_TYPE(rel->r_info);
auto sym = ELF64_R_SYM(rel->r_info);
#endif
auto prel = reinterpret_cast<Elf_Addr *>(base + rel->r_offset);
switch (type) {
// I don't known other so info, if i want to fix it, I must dump other so file
case R_386_RELATIVE:
case R_ARM_RELATIVE:
*prel = *prel - dump_base;
break;
case 0x402:{
auto syminfo = si.symtab[sym];
if (syminfo.st_value != 0) {
*prel = syminfo.st_value;
} else {
auto load_size = si.max_load - si.min_load;
*prel = load_size + external_pointer;
external_pointer += sizeof(*prel);
}
break;
}
default:
break;
}
if (isRela){
Elf_Rela* rela = (Elf_Rela*)rel;
switch (type){
case 0x403:
*prel = rela->r_addend;
break;
default:
break;
}
}
};
拿了一个有值数据来看,这里这个数据是个偏移
从内存中将这个偏移的值打印出来。指向了libc++的地址。
这里 类型为403 404 ,从elf文件类型中确实没有找到,盲猜是外部模块的符号,即导入的符号,不过这种在elf文件重定位阶段 , 目标地址会被重写有需要重写吗?
测试下该工具修复后的ELF文件,跑不起来。
0 条评论