LakeCTF Qualifications Writeup

この大会は2022/9/25 3:00(JST)~2022/9/26 3:00(JST)に開催されました。
今回もチームで参戦。結果は61点で191チーム中88位でした。
自分で解けた問題をWriteupとして書いておきます。

Sanity Check (sanity)

Discordに入り、#sanity-checkチャネルのメッセージを見ると、こう書いてある。

Please connect to nc chall.polygl0ts.ch 5200 
$ nc chall.polygl0ts.ch 5200 
EPFL{533ms_s4ne_t0_m3}
EPFL{533ms_s4ne_t0_m3}

Baby rev (rev)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  FILE *__stream;
  __ssize_t _Var1;
  undefined8 uVar2;
  byte bVar3;
  long lVar4;
  uint uVar5;
  long in_FS_OFFSET;
  uint local_24;
  size_t local_20;
  char *local_18;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  __printf_chk(1,"What\'s your your number:");
  fflush(stdout);
  __isoc99_scanf(&DAT_0010201d);
  lVar4 = 0;
  uVar5 = 0;
  if (local_24 - 0x10000 < 0x7fff0001) {
    do {
      bVar3 = (byte)lVar4;
      lVar4 = lVar4 + 1;
      uVar5 = (local_24 >> (bVar3 & 0x1f) & 1) + uVar5 * 2;
    } while (lVar4 != 0x20);
    if (local_24 == uVar5) {
      __stream = fopen("flag.txt","r");
      if (__stream == (FILE *)0x0) {
        puts("No flag found");
        uVar2 = 0xffffffff;
      }
      else {
        local_20 = 0;
        local_18 = (char *)0x0;
        _Var1 = getline(&local_18,&local_20,__stream);
        if (_Var1 == -1) {
          puts("Unable to read flag");
          uVar2 = 0xffffffff;
        }
        else {
          __printf_chk(1,&DAT_0010205d,local_18);
          uVar2 = 0;
        }
      }
      goto LAB_001011a6;
    }
  }
  puts("Bad number >:-(");
  uVar2 = 0;
LAB_001011a6:
  if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
    return uVar2;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

主要な条件は以下の部分。

・if (local_24 - 0x10000 < 0x7fff0001) {
・uVar5 = (local_24 >> (bVar3 & 0x1f) & 1) + uVar5 * 2;

この条件を満たす数値をz3で求め、答える。

#!/usr/bin/env python3
import socket
from z3 import *

def recvuntil(s, tail):
    data = b''
    while True:
        if tail in data:
            return data.decode()
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chall.polygl0ts.ch', 3600))

x = BitVec('x', 64)
slv = Solver()

slv.add(x - 0x10000 < 0x7fff0001)

v = 0
for i in range(0x20):
    v = (x >> i & 1) + v * 2
slv.add(x == v)

r = slv.check()
assert r == sat
m = slv.model()
ans = m[x].as_long()

data = recvuntil(s, b':')
print(data + str(ans))
s.sendall(str(ans).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)

実行結果は以下の通り。

What's your your number:8659200
EPFL{4ft3r_th15_h0w_h4rD_caN_r3V_8e?}
EPFL{4ft3r_th15_h0w_h4rD_caN_r3V_8e?}

Feedback form (misc)

アンケートに答えたら、フラグが書いてあった。

EPFL{Thank_you_for_playing_we_hope_you_have_fun}