2

我一直在为 Linux 开发一个简单的 PE 进程加载器。我想我已经掌握了基础知识;我使用的大部分代码来自binfmt_elf.cand binfmt_aout.c。我的测试可执行文件尽可能简单(FASM 格式):

format PE GUI 4.0
entry main

section '.text' code readable executable
main:
    mov eax, 4
    add eax, 5
    ret

这个程序(math1)是32位编译的,我运行的VM(Xubuntu 12.04)也是32位的。我将加载器编译为内核模块并使用insmod. 到目前为止,加载程序似乎可以正常工作,并且我已经在每个可能的步骤中检查了错误代码。它所做的只是mmap起始地址的代码部分0x401000并使用该地址调用start_thread()。如果我./math1.exe在命令行输入类似的内容,我的加载器确实被调用了。所以,如果一切按计划进行,我应该9每次都得到返回值。然而,不是math1每次都执行段错误,所以我打开它gdb看看发生了什么。

在执行之前,一切看起来都很正常。如果我在起始地址转储,我会看到我应该看到的确切内容(我可以确认这是上述程序的机器代码):

(gdb) x/9xb 0x401000
0x401000:   0xb8    0x04    0x00    0x00    0x00    0x83    0xc0    0x05
0x401008:   0xc3
(gdb) run
Starting program: /media/sf_Sandbox/math1.exe 

Program received signal SIGSEGV, Segmentation fault.
0x00401002 in ?? ()

在段错误之后,转储到相同的地址,内存已经完全改变,并且从寄存器转储来看,第一条指令似乎没有被执行:

(gdb) x/9xb 0x401000
0x401000:   0x4d    0x5a    0x80    0x00    0x01    0x00    0x00    0x00
0x401008:   0x04
(gdb) info all-registers
eax            0x0  0
ecx            0x81394e8    135501032
edx            0x64656d2f   1684368687
ebx            0x8139548    135501128
esp            0xbfffe5a0   0xbfffe5a0
ebp            0xffffffff   0xffffffff
esi            0x81394e8    135501032
edi            0x2f7ff4 3112948
eip            0x401002 0x401002
eflags         0x210296 [ PF AF SF IF RF ID ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x0  0
...more registers...

我想知道什么会导致这样的事情发生,以及我可以做些什么来解决它。我怀疑我用来设置堆栈框架的代码可能有点……关闭,但我不确定如何判断这是否是导致这种情况的原因。我知道这是一个非常具体的问题,但我希望有人能给我一些建议。

4

1 回答 1

0

该错误是由于我的页面对齐错误引起的,而神秘的十六进制转储内容实际上是相关 PE 文件的 MS-DOS 标头。我通过使用kernel_readandcopy_to_user而不是来修复它,do_mmap以避免在非页面对齐的部分上失败。

于 2012-08-16T23:59:49.533 回答