The experiment in this article comes from an experiment in chapter 3 in computer systems a programmer's perspective.
The author provides a program bufbomb. C that contains buffer overflow. What you need to do is to inject some special data into the buffer and use the buffer in the end.
1 //bufbomb.c 2 /* Bomb program that is solved using a buffer overflow attack */ 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <ctype.h> 6 /* Like gets, except that characters are typed as pairs of hex digits. 7 Nondigit characters are ignored. Stops when encounters newline */ 8 char *getxs(char *dest) 9 { 10 int c; 11 int even = 1; /* Have read even number of digits */ 12 int otherd = 0; /* Other hex digit of pair */ 13 char *sp = dest; 14 while ((c = getchar()) != EOF && c != '/n') { 15 if (isxdigit(c)) { 16 int val; 17 if ('0' <= c && c <= '9') 18 val = c - '0'; 19 else if ('A' <= c && c <= 'F') 20 val = c - 'A' + 10; 21 else 22 val = c - 'a' + 10; 23 if (even) { 24 otherd = val; 25 even = 0; 26 } else { 27 *sp++ = otherd * 16 + val; 28 even = 1; 29 } 30 } 31 } 32 *sp++ = '/0'; 33 return dest; 34 } 35 /* $begin getbuf-c */ 36 int getbuf() 37 { 38 char buf[12]; 39 getxs(buf); 40 return 1; 41 } 42 void test() 43 { 44 int val; 45 printf("Type Hex string:"); 46 val = getbuf(); 47 printf("getbuf returned 0x%x/n", val); 48 } 49 /* $end getbuf-c */ 50 int main() 51 { 52 int buf[16]; 53 /* This little hack is an attempt to get the stack to be in a 54 stable position 55 */ 56 test(); 57 return 0; 58 }
The getxs function is similar to the gets function of the library function, except for the characters that are read in hexadecimal number pairs. For example, to read the string "0123", you must provide the input string "30 31 32 33". This function will ignore spaces.
By analyzing this program, we can know that normally, this function will call the getxs function in getbuf to read the number pair, and then 0x1 will be returned to the test function in any case, then, the returned value of getbuf is printed by the printf function in test.
Now, your task is to use the buffer overflow vulnerability and enter some special numbers to print 0 xdeadbeef on the screen.
I solve this problem in Windows XP and Visual C ++ 6.0 environments.
Before doing this, you certainly need to know what the frame stack structure is (see chapter 3 of "understanding computer systems") to understand the meaning of % EBP and % ESP.
The question has already been said, "When analyzing this program, we can know that under normal circumstances, this function will call the getxs function in getbuf to read the number pair, and then in no case, the test function returns 0x1. "What should we do? Now we can think of the char Buf [12] defined in the getbuf function. We can see the while loop in the getxs function, the ending condition is based on the carriage return or EOF Terminator. Therefore, the number of char inputs is not determined! In this case, we can enter more than 12 numbers to overflow the buffer!
The frame stack structure is as follows:
+ ------------------------------- + High address
| N function parameters |
+ ------------------------------- +
| N-1 Number of function parameters |
+ ------------------------------- +
|... |
|... |
|... |
+ ------------------------------- +
| Function parameters: 1st |
+ ------------------------------- +
| Return address |
+ ------------------------------- +
| EBP pointer into Stack |
+ ------------------------------- +
| Local var (local variable) |
+ ------------------------------- +
| Others |
+ ------------------------------- + Low address
According to the storage of the function stack mentioned above, in the getbuf function, the function parameter does not exist. We don't care, and then the return address is followed by the EBP pointer, then there is Char Buf [12].
+ ------------------------------- + Low address
| Return address |
+ ------------------------------- +
| EBP pointer into Stack |
+ ------------------------------- +
| Buf [11] |
+ ------------------------------- +
| Buf [10] |
+ ------------------------------- +
:
:
:
+ ------------------------------- +
| Buf [0] |
+ ------------------------------- +
| Others |
+ ------------------------------- + High address
If we overflow the Buf, we can rewrite the EBP and return addresses! Let's take a look at the EBP and return address.
You need to know that % EBP stores % EBP of the test function, so we can get the value of % EBP in the test function during debugging, it should be the value of the Buf [12]-Buf [15] we write, and it should keep the original value, otherwise it will be messy after the return, it is 0x0012efa0 on my machine. This is easy and solves the first step.
Next let's look at the return address. Let's first look at a piece of assembly code (different machines are different ):
58: val = getbuf();004011C5 call @ILT+10(getbuf) (0040100f)004011CA mov dword ptr [ebp-4],eax59: printf("getbuf returned 0x%x/n", val);004011CD mov eax,dword ptr [ebp-4]004011D0 push eax004011D1 push offset string "getbuf returned 0x%x/n" (0042001c)004011D6 call _printf (00401510)004011DB add esp,8
After getbuf () returns, it will certainly continue to execute 004011ca. Can we execute it from here? Of course not! Otherwise, we need to push eax, which we don't want to see, because the value of eax is 1. So we will think of whether we can skip this? Of course. Change the return address! We use the Buf array to overwrite the returned address. In this case, we want it to jump directly to D1, so we can overwrite the return address by setting the value of BUF [16]-Buf [19.
After thinking about how to add deadbeef, after the return, the push offset string "getbuf returned 0x % x/N" (0042001c) will be executed directly. How can this problem be solved without eax? Otherwise, the printf function will lose the parameter. Return to the frame stack structure. Before calling printf, You need to press the parameter into Val, and then press the offset string "getbuf returned 0x % x/N ", that is to say, the parameter Val (equivalent to the eax) is placed on the offset string "getbuf returned 0x % x/N" and is next to it. At this point, we can think that since after the return (the returned address and the following elements have been popped up, the last byte of the returned address becomes the top of the stack) execute push offset string "getbuf returned 0x % x/N" (0042001c) to press the stack. In this case, the top priority of the stack is the parameter Val, which is originally on the return address, therefore, we can set the value of BUF [20]-Buf [23] to overwrite this place.
To sum up, the value of % EBP is 0x0012efa0, and the modified return address is 0x004011d1. Therefore, we can enter
00000000 00000000 00000000 a0ef1200 d1114000 efbeadde
The 24 0 values can be entered with no effect. The key is the number of the next 24 values.
[Transfer] http://blog.csdn.net/idoit0204/article/details/3935627