2012-08-16 28 views
2

我一直在研究一个简单的用于Linux的PE进程加载器。我想我已经掌握了基础知识;我使用的大部分代码来自binfmt_elf.cbinfmt_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位和虚拟机,我在(Xubuntu上12.04)运行也是32位。我将loader作为内核模块编译并使用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... 

我想知道什么可以让这样的事情发生,我可能能够做到要解决这个问题。我怀疑我用来设置堆栈框架的代码可能有点...关闭,但我不确定如何判断这是什么原因造成的。我知道这是一个非常具体的问题,但我希望有人能给我一些建议。

+0

mmap:ed内存是否获得执行权限? – 2012-08-16 16:37:25

+0

@JensBjörnhager它被映射到保护'PROT_READ | PROT_EXEC'和标志'MAP_PRIVATE | MAP_FIXED | MAP_DENYWRITE'。据我所知,这与ELF加载程序的做法是一样的。 – nosuchthingasstars 2012-08-16 16:52:48

+2

'4d 5a ...'看起来像一个MS-DOS标题。你确定你没有意外地映射过吗? – atomicinf 2012-08-16 17:26:36

回答

0

错误是由我的错误页面对齐引起的,神秘的十六进制转储内容实际上是所讨论的PE文件的MS-DOS标题。我通过使用kernel_readcopy_to_user而不是do_mmap来修复它,以避免在非页面对齐的部分出现故障。