ELFファイル qasm
と、それの入力ファイル prog.qasm
が与えられた。
qasm
をmain
関数と、f00
からf71
までの「f」と16進数2桁を組み合わせた名前の関数があった。
An ELF file qasm
and an file to use as input of that prog.qasm
were given.
Decompiling qasm
via main
and functions from f00
to f71
, which are named with "f" and two-didit hexadecimal numbers.
これは、以下の特徴を持つ仮想マシンのプログラムのようである。
f00
~f71
の関数に対応していると推測できる。
これを踏まえ、以下の逆アセンブラを作成した。
なお、このプログラムは命令の引数の数を取得するためにファイルqasm
を参照する。
This looks like a program for virtual machine with these characteristics:
f00
to f71
, respectively.
Based on these information, I created this disassembler.
This program refers to the file qasm
to determine the number of arguments for each instructions.
以下が prog.qasm
を逆アセンブルした結果である。
This is disassembled prog.qasm
:
さらに可読性を高めるため、以下のように整理した。
なお、convert_res.txt
の後半部分は実行されなそうだったので、この結果には含まれていない。
For better readability, I organized what are done like this.
I didn't include latter part of convert_res.txt
which didn't seem to be executed.
解析の結果、これは、以下のような処理をしているようだった。
no >:(
を出力して終了する。yes :)
を、そうでなければ no >:(
を出力する。
入力がどのような数列に変換されるかを調べるため、f53
内のret
命令にブレークポイントを置き、変換結果の値を調べた。
ここでは変換結果と比較対象の値が交互に取得されるので、GDBのc 2
コマンドを用いて1回ブレークポイントを無視させることで、変換結果の値を連続で見ることができる。
また、ignore (ブレークポイント番号) 100
コマンドでブレークポイントを100回無視する設定にしてから実行を開始することで、57個中最後7個の値を見ることができる。
Analyzing this, I found this doing this process:
no >:(
and exit.yes :)
if all elements of the sequences are the same. Output no >:(
otherwise.
To investigate how the input is converted, I used GDB in
I set a breakpoint on the ret
instruction in the function f53
, which is used to fetch elements of the sequences for comparision, to obtain the values in the result of conversion.
This function is used to fetch the value in the conversion result and one in the target of comparision in turn.
We can use a command c 2
in GDB to have it ignore the breakpoint once and continuously watch the values in the conversion result.
Also, we can watch the last 7 elements out of 57 by using the ignore (the no. of breakpoint) 100
command to have it ignore the breakpoint 100 times before starting execution.
When I entered this:
を入力すると、変換結果の最初の6要素は
The first 6 elements in the conversion result were:
となり、隣り合う要素の差 (mod 127) が33 (!
の文字コード) ずつ変わっていることに気がついた。
また、変換結果の最後の7要素を見ると、
I found that the difference of the next elements (modulo 127) was changing by 33 (the character code for !
).
Also, the last 7 elements in the conversion result were:
となり、最後から順に0x21の1倍、3倍、6倍、10倍、15倍、21倍、28倍 (mod 127) となっていることに気がついた。
さらに、
I found that these are 1, 3, 6, 10, 15, 21, 28 times 0x21 modulo 127, respectively, from the last element.
Moreover, when I entered this:
を入力すると、最後の7要素は
The last 7 elements became:
となり、最後からn番目 (1-origin) の値は「最後からk番目の値をk倍したもの」の最後から1番目からn番目までの和 mod 127 になっていそうなことに気がついた。
これに基づき、以下のプログラムでflagが得られた。
And I guessed that the n-th element from the last is the sum of n elements of "k times the k-th element from the last" from the last modulo 127.
Based on this, I obtained the flag via this program:
このプログラムで用いたリストの値は、以下のRecipeにより prog.qasm
の逆アセンブル結果から抽出した。
The values in the list used in this program is extracted from the disassembled prog.qasm
using this Recipe:
Find / Replace, From Decimal, To Decimal - CyberChef