今天在学习溢出时写了个简单程序,源代码如下。
1
#include <stdio.h>
2
#include <stdlib.h>
3
4
int foo_normal(char*);
5
int foo_abnormal(char*);
6
7
int main()
8

{
9
int i;
10
char szTmp[] =
{
11
0x31, 0x31, 0x31, 0x31,
12
0x32, 0x32, 0x32, 0x32,
13
0x33, 0x33, 0x33, 0x33,
14
0x00, 0x40, 0x13, 0x45,
15
16
0x31, 0x31, 0x31, 0x31,
17
0x32, 0x32, 0x32, 0x32,
18
0x33, 0x33, 0x33, 0x33,
19
0x4e, 0x13, 0x40, 0x00
20
};
21
22
i = 0;
23
24
if (i == 0)
25
foo_normal(szTmp);
26
else
27
foo_abnormal(szTmp);
28
29
return(0);
30
}
31
32
33
int foo_normal(char* _sz)
34

{
35
char buffer[5];
36
memcpy(buffer, _sz, sizeof(char)*32);
37
printf("Application terminates normally.\n");
38
return(0);
39
}
40
int foo_abnormal(char* _sz)
41

{
42
char buffer[5];
43
memcpy(buffer, _sz, sizeof(char)*3);
44
printf("You should have never seen this.\n");
45
return (0);
46
}
打算通过foo_normal中的memcpy函数覆盖栈中的EIP,改为调用foo_abnormal处的语句,来达到溢出攻击的目的。按照正常情况看,在foo_normal中,栈里有4字节的CS和4字节的EIP,然后是5字节的字符串数组——对齐后是8字节,还有4字节的EBP。所以当往buffer中复制12字节数据就可以覆盖掉EIP而达到溢出的目的。但实际上使用32字节的数据覆盖buffer及其后的数据,才把EIP给照顾到。使用OllyDBG跟了一下:
1 004013F2 /$ 55 push ebp
2 004013F3 |. 89E5 mov ebp, esp
3 004013F5 |. 83EC 28 sub esp, 28
4 004013F8 |. C74424 08 050>mov dword ptr [esp+8], 5 ; ||
5 00401400 |. 8B45 08 mov eax, dword ptr [ebp+8] ; ||
6 00401403 |. 894424 04 mov dword ptr [esp+4], eax ; ||
7 00401407 |. 8D45 E8 lea eax, dword ptr [ebp-18] ; ||
8 0040140A |. 890424 mov dword ptr [esp], eax ; ||
9 0040140D |. E8 FE050000 call <jmp.&msvcrt.memcpy> ; |\memcpy
10 00401412 |. C70424 D01340>mov dword ptr [esp], 004013D0 ; |ASCII "Application terminates normally.",LF
11 00401419 |. E8 EA050000 call <jmp.&msvcrt.printf> ; \printf
12 0040141E |. B8 00000000 mov eax, 0
13 00401423 |. C9 leave
14 00401424 \. C3 retn
发现在进入函数的时候申请了28个字节的空间——除去12字节给memcpy的参数,比预想的多了6字节。看来使用的3.3.1版本的gcc是16字节对齐的。
……让我抓狂了一个小时。