我正在使用Ubuntu 12.04和64位機器。我正在閱讀一本關於緩衝區溢出的書,並且在玩一個例子時發現了一個奇怪的時刻。緩衝區溢出期間EIP值不正確
我有這個非常簡單的C代碼:
void getInput (void){
char array[8];
gets (array);
printf("%s\n", array);
}
main() {
getInput();
return 0;
}
文件中overflow.c
我與32位標誌編譯它導致了書中所有例子假定32位的機器,我這樣做這樣
gcc -fno-stack-protector -g -m32 -o ./overflow ./overflow.c
在代碼字符數組是隻有8個字節,但在看拆卸我發現,陣列開始從在堆棧上保存的EBP 16個字節遠,所以執行該行:
printf "aaaaaaaaaaaaaaaaaaaa\x10\x10\x10\x20" | ./overflow
,並得到:
aaaaaaaaaaaaaaaaaaaa
Segmentation fault (core dumped)
然後我打開核心文件:
gdb ./overflow core
#0 0x20101010 in ??()
(gdb) info registers
eax 0x19 25
ecx 0xffffffff -1
edx 0xf77118b8 -143583048
ebx 0xf770fff4 -143589388
esp 0xffef6370 0xffef6370
ebp 0x61616161 0x61616161
esi 0x0 0
edi 0x0 0
eip 0x20101010 0x20101010
正如你看到的EIP其實有了新的價值,這是我想要的。但是,當我想要把一些有用的值這樣的0x08048410
printf "aaaaaaaaaaaaaaaaaaaa\x10\x84\x04\x08" | ./overflow
程序崩潰像往常一樣,但比一些奇怪的事情發生了,當我試圖觀察EIP寄存器的值:
#0 0xf765be1f in ??() from /lib/i386-linux-gnu/libc.so.6
(gdb) info registers
eax 0x61616151 1633771857
ecx 0xf77828c4 -143120188
edx 0x1 1
ebx 0xf7780ff4 -143126540
esp 0xff92dffc 0xff92dffc
ebp 0x61616161 0x61616161
esi 0x0 0
edi 0x0 0
eip 0xf765be1f 0xf765be1f
突然EIP開始看起來像這個0xf765be1f,它看起來不像0x08048410。事實上,我注意到從0開始的任何十六進制值就足以得到這個崩潰的EIP值。你知道爲什麼會發生這種情況嗎?是因爲我在64位機器上嗎?
UPD
好球員在要求更多的信息,意見,這裏是getInput功能的拆卸:
(gdb) disas getInput
Dump of assembler code for function getInput:
0x08048404 <+0>: push %ebp
0x08048405 <+1>: mov %esp,%ebp
0x08048407 <+3>: sub $0x28,%esp
0x0804840a <+6>: lea -0x10(%ebp),%eax
0x0804840d <+9>: mov %eax,(%esp)
0x08048410 <+12>: call 0x8048310 <[email protected]>
0x08048415 <+17>: lea -0x10(%ebp),%eax
0x08048418 <+20>: mov %eax,(%esp)
0x0804841b <+23>: call 0x8048320 <[email protected]>
0x08048420 <+28>: leave
0x08048421 <+29>: ret
聽起來不太有說服力。無論如何,0xf765be1f是如何到達EIP的?有沒有RET?無論如何,這需要更詳細的調試。 – m0skit0
@ m0skit0,一旦開始破壞堆棧並執行通配地址,事情變得非常不可預測。 '0x08048410'處的代碼可能不會簡單地跳轉到0xf765be1f,但它可能會按照您的建議返回,或者通過寄存器調用函數。 – ugoren
那麼地址0x08048410就是getInput函數裏調用get函數的地址,我只是試圖再次調用這個函數,這是非常確鑿的證據,我重定向了程序的流程 –