Attack-lab记录
前言
一定要仔细要看Write Up,跟着它一步步来会轻松很多
因为这个Lab涉及到的内容比较多,Write Up中有一步一步的提示
我在做BombLab的时候以为我会gdb的基础使用就没看Write Up,然后我忘记有objdump这个东西了,导致我在gdb里把反汇编一张一张截图下来…🤣
Part1-Code Injection Attacks
1-1
先看看ctarget是什么情况
1 |
|
-q参数表示不连接打分服务器(我们不是cmu的学生所以连接不上服务器)
根据提示,我们的输入是由一个叫做getbuf
的函数处理的,我们的目标是利用缓冲区溢出跳转到touch1
函数
1 |
|
用反汇编程序objdump
查看getbuf
函数的汇编代码objdump -d ctarget > ctarget.txt
sub $0x28,%rsp
在内存中开辟了一块0x28
大小的空间,也就是40字节,rsp(栈顶指针)被赋值给了rdi作为get的参数,所以我们的输入存储在栈顶
搜索touch1
函数,发现它的地址是0x4017c0
,又由于Intel采用了小端序,所以输入应该是
输入cat in.txt | ./hex2raw | ./ctarget -q
运行,
成功!
1-2
第二个就没有第一个那么简单了,先看看touch2
函数的代码
1 |
|
我们不仅仅需要跳转到touch2,还要把cookies作为参数传进去
由于这个函数只有一个参数,参数是通过rdi寄存器来传递的,所以应该把cookie放在rdi中
所以应该在输入中构建一串机器代码,然后利用修改返回值让它指向栈顶,以运行我们的代码
对应的汇编代码为:
1 |
|
把它存在as.s中gcc -c as.s
,objdump -d as.o > as.txt
就可以看到反汇编代码了
用gdb给getbuf
打上断点,info reg rsp
查看当时栈顶的地址,是0x5561dc78
所以应该是这样
PASS!
1-3
touch3需要传递一个字符串,先看看touch3的代码
1 |
|
传递的字符串应该是coookie
同时,还有一个hexmatch函数
1 |
|
要注意的是,在调用hexmatch
和strncmp
的时候,栈上的空间可能会被覆盖掉
我的cookie是59b997fa
,查询ascii码对照表,应该是35 39 62 39 39 37 66 61
,由于小端法,应该把它分成39 62 39 35
和61 66 37 39
两块,我先把它放置在栈顶,同上可得
运行,发现不太行
传入的是一个空字符串,说明栈顶的空间被覆盖了
于是我用gdb给getbuf
打上断点,查看当时栈的情况
我发现在getbuf分配的空间后有大段没有使用的空间,于是我打算把cookies存放在这里
1 |
|
结束!
cat in2.txt | ./hex2raw | ./ctarget -q
Part2-Return-Oriented Programming
2-2
照常使用objdump -d rtarget > rtarget.txt
查看rtarget的汇编代码
Write UP中提示我们这道题只需要使用从start_farm
到mid_farm
之间的代码,使用%rax–%rdi
之间的寄存器,注意movq
,popq
,ret
,nop
这几个函数就行了,并且需要两次跳转,并且可能要用到的指令编码给了我们
我们可以使用pop来把cookie存入寄存器中,我们依次在函数中寻找pop
的编码发现只能找到popq %rax
的编码58
1 |
|
由于需要把cookie存入%rdi
中,所以我们需要找到movq %rax,%rdi
的编码48 89 c7
,我发现在setval_426
和addval_273
中有合适的编码
1 |
|
随便选择一个都行,我选择了setval_273
所以我们的输入应该是
其中第11行是返回地址,修改成了第一个”gadget”的地址,它从栈中取出cookie,并把它存入寄存器%rax
中,并跳转到第15行存储的地址(第二个”gadget”)
第二个”gadget”把%rax
的值存入%rdi
中,并返回到第17行存储的地址(touch2
函数)
2-3
先看看来自CMU的官方劝退:😁
Phase 5 requires you to do an ROP attack on RTARGET to invoke function touch3 with a pointer to a string
representation of your cookie. That may not seem significantly more difficult than using an ROP attack to
invoke touch2, except that we have made it so. Moreover, Phase 5 counts for only 5 points, which is not a
true measure of the effort it will require. Think of it as more an extra credit problem for those who want to go beyond the normal expectations for the course.
最后道题,显而易见地难多了,Write Up中提示我们这道题可以使用从start_farm
到end_farm
的全部内容,需要用到8次”gadget”,而且可能相同.
由于启动了栈随机化,每次运行栈的位置都会变化,所以应该先获取rsp
的值,再加上一个偏移量来计算cookie字符串的地址
很容易就能想到leaq
指令,我还以为要再通过编码找leaq,但我很快就发现在add_xy
函数里有现成的lea
指令可以用
1 |
|
所以首先要想办法把rsp的值拷贝出来,搜索48 89 e
,发现只有把rsp存入rax的指令
1 |
|
正好,找到一个”gadget”(48 89 c7
)能把rax
复制到rdi
1 |
|
偏移量就只能用popq
pop到rax
中了,但是在可以使用的函数中只能查找到movq %rax %rdi
的编码48 89 c7
,却又无法找到把rdi
的值存入其他寄存器中的”gadget”
在这个地方我卡壳了好久,然后我发现有一张movl
编码的表我还没有用到
我突然意识到,这个数据是用来存放偏置值的,所以movl
绝对够用
经过一番查找,我发现可以利用下面几个”gadget”来完成这个任务
1 |
|
综上,我的思路是:
然后就可以编写输入了
PASS!