如何恢复Windows可执行文件的原始入口点?

时间:2014-08-11 13:23:56

标签: c++ windows assembly portable-executable

我正在尝试学习如何修改Windows PE并制作一个打包器。我目前所做的是获取一个exe文件,向其添加一个新的部分并将oep更改为该新部分。新部分只是跳回文件的原始地址。以下是新部分的代码:

__asm {
    pushad
        mov eax, 0x0044F125 //oep
        jmp eax
}

正如您所看到的,我必须对oep地址进行硬编码。有什么方法可以存储oep或计算它吗?

3 个答案:

答案 0 :(得分:1)

首先,PE文件的入口点在标题中,总之,PE格式包含:

  • MZ标头(出于兼容性目的,但包含PE标头的偏移量)。
  • PE标头(包含有关文件的信息,有多少部分,导入等...)。包含:File Header,Optional Header(这是包含PE文件入口点的标题。
  • 章节标题
  • 部分数据

有关PE的更多信息:

如果你想做一个包装工,你需要:

  1. 走PE标头结构以找到原始入口点
  2. 使用新的入口点保存并更新
  3. 添加新添加的部分的信息。
  4. 第2点和第3点可以按任何顺序执行,如果您先执行第2点,则需要知道该部分的位置,并且可以轻松计算读取现有部分。如果您首先执行第3点,则您已经知道新的入口点。

    如果您需要,可以查看UPX packer以获取有关如何修改PE格式以及如何一般地执行打包程序的更多提示。

答案 1 :(得分:0)

OEP作为RVA存储在PE文件中。您修改该值,此时原始值将丢失。如果你想获得原始值,你必须在修改值之前阅读它并记住它。

答案 2 :(得分:0)

好的,我发现它实际上是在文件本身写oep:

void write_stub_entry_point(PIMAGE_NT_HEADERS nt_headers, void *stub_addr) {
    if (stub_addr != NULL) {
        const char *signature = "\xFF\xEE\xDD\xCC";
        unsigned int index = 0;
        while (memcmp(((unsigned char *)stub_addr + index), signature, sizeof(int)) != 0) {
            ++index;
        }
        DWORD old_protections = 0;
        VirtualProtect(((unsigned char *)stub_addr + index), sizeof(DWORD), PAGE_EXECUTE_READWRITE, &old_protections);
        memcpy(((unsigned char *)stub_addr + index), &nt_headers->OptionalHeader.AddressOfEntryPoint, sizeof(DWORD));
        VirtualProtect(((unsigned char *)stub_addr + index), sizeof(DWORD), old_protections, NULL);
    }
}

现在他们只能从文件中恢复它:

__asm { //Epilogue, stub exit point
    mov eax, target_image_base
        add eax, 0xCCDDEEFF     //Signature to be replaced by original entry point (OEP)
        mov esp, ebp
        mov[esp + 0x20], eax     //Store OEP in EAX through ESP to preserve across popad
        pop ebp
        popad                   //Restore thread context, with OEP in EAX
        jmp eax                 //Jump to OEP
}