IDA PRO 和 Dos Load Exec

逆向工程 艾达 反编译 x86
2021-06-15 20:05:07

我正在尝试在 IDA pro(5.0 演示)中反转一些 DOS 游戏。我在尝试加载覆盖文件时卡住了。是否可以将第二个可执行文件加载到原始命名空间中?

它已经为常用例程设置了视频、中断和一些跳转表。

我想我几年前尝试过,只是通过 DosBox 倾倒了完整的 1meg ram。然而,它打破了细分市场等。


seg001:0672                 mov     ax, bx
seg001:0674                 sub     ax, offset string_of_space ;
seg001:0677                 mov     byte_108CA, al
seg001:067A                 mov     bx, offset param_block
seg001:067D                 mov     dx, cs:filename
seg001:0682                 mov     ax, 4B00h
seg001:0685                 mov     cs:saved_ss, ss
seg001:068A                 mov     cs:saved_sp, sp
seg001:068F                 int     21h             ; DOS - 2+ - LOAD OR EXECUTE     (EXEC)
seg001:068F                                         ; DS:DX -> ASCIZ filename
seg001:068F                                         ; ES:BX -> parameter block
seg001:068F                                         ; AL = subfunc: load & execute     program
seg001:0691                 cli
seg001:0692                 mov     ss, cs:saved_ss
seg001:0697                 assume ss:nothing
seg001:0697                 mov     sp, cs:saved_sp
1个回答

等待本机 IDA 解决方案,我可以使用使用以下过程的 C 程序为自己解决这个问题:

  1. 基本可执行文件入内存;
  2. 覆盖入内存。请注意,这本身就是一个常规的可执行文件。
  3. 基本可执行文件中,调整以下 EXE 标题项:
    a. 设置bytes_in_last_block0
    b。blocks_in_file覆盖层添加到基部,
    c。num_relocs覆盖层添加到基础的。
  4. 计算新的可执行文件大小;这是blocks_in_file* 512 - original_header_paragraphs* 16的总数新堆栈段需要此编号ss
  5. 新的header_paragraphs大小 - 即原始大小加上覆盖层中的重定位 - 将是reloc_table_offset + 4*num_relocs. 确保四舍五入到段落大小,16.

此时,新标题应该已完成。将其写入新文件。主可执行文件的重定位表应该保持不变,您也可以编写它。

覆盖的那么重定位表需要进行调整。

重定位表本身包含segment:offset每个重定位对,指向二进制可执行映像到存储从零开始的段值的位置(即,“第一个段”的值将是0000h,加载时,实际段添加到此值)。

由于你在可执行部分添加了数据,所以需要调整线性偏移到文件中;添加原始可执行代码的大小(应向上舍入为 512 字节长的页面)。读取该位置segment,在段落中加上原始可执行代码的大小,写回。然后segment在原重定位部分加上原可执行代码的大小对覆盖表中的每个重定位执行此操作。

调整覆盖的重定位表后,将其写入您的输出文件,紧接着是原始可执行文件的数据(完全未更改)。然后将更改的叠加数据添加到输出文件中。

需要注意的一件事是,我测试的可执行文件(只有一个!)也在可执行文件中存储了一个非常小的堆栈。我不知道这是否正常;我不得不从“主”代码中删除保存的堆栈,并在组合主代码+覆盖代码之后再次添加它。


重要的提示!

这个过程对我有用,因为我测试它的程序使用动态加载的叠加层。主程序加载覆盖并将一些数据和代码地址复制到主dseg段中。之后,它通过这些指针调用覆盖的代码。覆盖代码ds“像往常一样”使用,它只是使用主要的dseg.

当然,现在没有调用“初始化”例程,这些指向覆盖例程的指针未初始化,您必须手动找出复制到何处的内容。但至少可以一次性将所有代码加载到 IDA 中。

它还会运行吗?

当然会。主要代码调用LOAD/EXEC,加载覆盖层,复制指针,一切都很好。唯一的问题是主要的可执行文件突然变大了很多......但是原始代码从未见过或使用过额外的部分。(当然,主要的可执行文件现在可能太大了,以至于没有更多的内存来加载覆盖。)
这个练习的目的不是消除加载覆盖的需要,只是为了能够将整个事物分解为一个二进制。

您可以在此处下载 C 源代码:http : //www.jongware.com/binaries/combine_exe_ovl.zip
- 请注意,这是一段非常肮脏的黑客代码,因此不提供任何保证