Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Japan VCC 2025 問題解説

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for smz smz
October 24, 2025
170

Japan VCC 2025 問題解説

Avatar for smz

smz

October 24, 2025
Tweet

Transcript

  1. パスワード検証のロジック 16 • ⽂字数をカウントし、11⽂字か検証 • ⼀⽂字ずつforループで検証 ◦ 検証する⽂字位置(pos)を配列から取得 • 戻り値ok_flagは11回(⽂字)のループ全てで

    条件式を満たすと1になる ◦ ok_flag = ok_flag & 条件式 • 条件式 ◦ (複雑な演算) == entered_password[pos] ◦ (複雑な演算)結果が正しいパスワードのpos ⽂字⽬
  2. 固定整数除算の最適化 17 • (複雑な演算)=((PTR_DAT_08001b20[idx + (uint)((ulonglong)0x4EC4EC4F * (ulonglong)idx >>0x22) *

    -0xd] ^ PTR_DAT_08001b24[pos]) - (pos * pos + 3 & 7)) ◦ 配列のインデックスをマジックナンバー0x4EC4EC4Fを使って計算している ◦ これは idx mod 13 = idx + idx / 0xd * -0xdをコンパイラが最適化したもの • ⼀般に除算命令は遅いため、32bit整数の除算 x / dは x * magic >> ( 32 + post_shift )のように乗算と右シフトで最適化される ◦ magicとpost_shiftはすべてのxで誤差が⽣じないように計算される ◦ gccでの実装はgcc/expmed.cのchoose_multiplier() ◦ 理論的基盤はGranlund-Montgomery, Division by Invariant Integers using Multiplication(1994)による
  3. Solverを書いて解く 18 def solve_password(): password = ['?'] * 11 #

    11文字のパスワード for i in range(11): pos = PTR_DAT_08001b18[i] # この反復でチェックする位置 # インデックス計算 idx = pos * 7 + 3 # 期待される文字を計算。idx % 13は固定整数除算最適化の結果に対応 expected = (PTR_DAT_08001b20[idx % 13] ^ PTR_DAT_08001b24[pos]) - ((pos * pos + 3) & 7) password[pos] = chr(expected) return ''.join(password) # ”ELITEHAXXOR”が返る >flag ELITEHAXXOR flag{medi3val_scr3w}