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文件,跑不起来。

分类: ELF

pareto

未来什么方向不管,先做自己喜欢做的事情。

0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注