ღ Miranda

pwnable.kr的PWN挑战之Toddler’s Bottle(三)

pwnable.kr is a non-commercial site which provides various pwn challenges regarding system exploitation. the main purpose of pwnable.kr is fun.

refer:
https://gist.github.com/ihciah/0ca68da3e32e38818bb9
http://rickgray.me/2015/07/24/toddler-s-bottle-writeup-pwnable-kr.html
http://weaponx.site/2017/02/21/unlink-Writeup-pwnable-kr/
https://github.com/Qwaz/solved-hacking-problem/tree/master/pwnable.kr

uaf-8pt

这题是考察UAF(Use After Free)漏洞的题目,当应用程序调用delete释放内存时,如果内存块小于256kb,并不马上将内存块释放回内存,而是将内存块标记为空闲状态。当下次分配大小相同的内存空间时会优先使用这一块内存区域,如果某个指针被释放后仍然能使用就可能会有UAF漏洞。case 3释放了变量m, w的内存,case 2可以向释放的内存写入我们要的代码,case 1可以被用来执行我们的代码。在IDA里分析部分主函数如下:

找到Man的构造函数:

这里rbp+var_38就是rbp-38:

还可以看出0x400F8D地址处是m, w变量分配完内存的地址,还可以从0x400F59地址看出分配的空间大小是0x16也就是24 bytes:

其实可以直接在IDA里搜索vtable关键字,找到Manvtable:

gdb里查看Manvtable:

这里是case 1部分的代码,调用了两个introducerax中是两个对象的虚函数表,introduce执行的是rax+8位置的代码,通过跟踪知道是introduce函数的位置,在Manvtable中可以看到introducegive_shell8 bytes:

也就是如果把rax里的值减小0x8,那调用introduce实际上就调用了give_shell,构造payloadecho -en处理特殊字符而且不换行:

注意这里要两次allocate,有两块内存空间需要填,不然在case 1中会有一句的内存无法访问,会报Segmentation fault错误。

memcpy-10pt

要在本地编译需要安装下面的包然后编译:

先尝试运行:

程序在fast_memcpy函数退出,打印dst地址可以发现当地址不是16的倍数时会出错:

movntps指令:

所以要构造地址为16的倍数:

asm-6pt

asm.c:

看了readme可以知道flag文件在asm_pwn的家目录下,需要nc 0 9026来用asm_pwn权限运行asm,看代码可以知道程序分配了0x1000的内存给sh指针,然后将这段内存清空,将寄存器清空的代码填入:

由于沙盒只允许运行openreadwrite函数,所以我们可以使用x64rax, rsp寄存器存放我们需要的内容然后输出到标准输出流,可以使用pwntools生成shellcode:

unlink-10pt

这题用到了unlink函数的堆溢出,需要一些前提知识:https://sploitfun.wordpress.com/2015/02/26/heap-overflow-using-unlink/。拿到程序可以用gdb调试,先反编译主函数:

由于要利用堆溢出需要先知道堆的结构,先看主函数中这段代码:

这就对应了双向链表的建立操作,然后单步调试,仔细看edx寄存器的内容就可以知道堆的结构如下:

一个chunk有24字节大小:

再看源代码可以发现:

[A->buf]之后的内存空间我们可以随意填入数据,最后调用unlink(B)时会做如下操作:

但由于之后没有别的函数调用,所以一般的堆溢出攻击方法不适用,注意看main函数的最后部分:

这段代码等效于:

最后esp寄存器的值就是ecx-0x4ecx的值又是ebp-0x4地址中的值,思路就是只要能最后retesp的值为shell()函数的地址就可以getshell,也就是ECX - 0x4地址处要存放shell的地址。

仔细分析栈的地址可以发现ebp-0x4的地址为题目给出的stack地址加0x10,那么思路就是只要能使DWORD PTR [stack + 0x10] = &(shell + 0x4)就可以了,再看unlink的操作,想一下怎样构造堆,由于DWORD PTR [FD + 0x4] = BK,那么FD的值为stack + 0xc

如果这样安排堆:

那么BK的值就应该为heap + 12,这样:

shell.py:

运行:

其实使用unlink的第二句也可以,堆构造为:

发表评论

电子邮件地址不会被公开。