今天在學(xué)習(xí)溢出時(shí)寫了個(gè)簡單程序,源代碼如下。
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函數(shù)覆蓋棧中的EIP,改為調(diào)用foo_abnormal處的語句,來達(dá)到溢出攻擊的目的。按照正常情況看,在foo_normal中,棧里有4字節(jié)的CS和4字節(jié)的EIP,然后是5字節(jié)的字符串?dāng)?shù)組——對(duì)齊后是8字節(jié),還有4字節(jié)的EBP。所以當(dāng)往buffer中復(fù)制12字節(jié)數(shù)據(jù)就可以覆蓋掉EIP而達(dá)到溢出的目的。但實(shí)際上使用32字節(jié)的數(shù)據(jù)覆蓋buffer及其后的數(shù)據(jù),才把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
發(fā)現(xiàn)在進(jìn)入函數(shù)的時(shí)候申請(qǐng)了28個(gè)字節(jié)的空間——除去12字節(jié)給memcpy的參數(shù),比預(yù)想的多了6字節(jié)??磥硎褂玫?.3.1版本的gcc是16字節(jié)對(duì)齊的。
……讓我抓狂了一個(gè)小時(shí)。