9.2 シンボルファイル#
ターゲットファイル:HOLA_REVERSER.exe
ターゲットファイルのアーキテクチャを確認します:
ターゲットファイルは 32 ビットプログラムで、VC++ 2015 でコンパイルされています。
プログラムをダブルクリックして実行し、数字を入力するように求められます。
プログラムは入力された文字が正しいかどうかを判断します。
9.3 main 関数の特定#
まず、文字列を見てみましょう。
ターゲットプログラムが実行時に出力するいくつかの文字列が見つかりました。上の図で赤線で示された部分をダブルクリックします。
次の場所に移動します:
上の図では、0x402108 はこの文字列のアドレスであり、アドレスの右側の 16 進数はマシンコードです。マシンコードの右側の aPoneUnNumerito はこの文字列のマークまたは名前であり、文字列の前の a は ASCII コードを表し、後の db はバイトシーケンスを表します。
D キーを押すと、各バイトの値を表示できます:
A キーを押すと、再び文字列として表示されます。
右側の矢印が示す引用位置にマウスを置くと、具体的な引用位置を表示できます。X キーを押すと、具体的な引用位置に移動できます。
この引用から main 関数を見つけることができます。
9.4 関数のスタック#
上記の図では、ローカル変数 var_4 があり、サイズは dword です。
32 ビット関数呼び出しスタックビュー
まず、すべての関数引数がスタックに渡され、次に戻りアドレスがあります。戻りアドレスの上には、上位関数の EBP があります。これは関数の最初の命令PUSH EBP
で生成されます。一番上にはローカル変数があります。
9.5 Main 関数の引数#
main 関数に移動します
X キーを押して、main 関数がどこで参照されているかを確認します。
main 関数の呼び出し
上の図では、3 つの push 命令があり、これらの命令を使用して引数が渡されます。3 つの命令のコメントによって、argc、argv、envp などの 3 つのパラメータが渡されることがわかります。これらは関数のデフォルトの引数です。
9.6 ローカル変数#
var_c はローカル変数です。X キーを押すと、このローカル変数がどこで参照されているかを確認できます。以下の図から、このローカル変数が 2 つの場所で参照されていることがわかります。
9.7 Atoi 関数#
atoi 関数は文字列を整数に変換します。数字が大きすぎて変換できない場合、エラーが発生し、0 が返されます。もちろん、最小の負の整数 (int) よりも小さい場合もエラーが発生し、0 が返されます。入力された内容はすべて整数に変換されます。たとえば、41424344 と入力すると、16 進数として EAX に保存されます。
#include <stdlib.h>
int atoi(const char *string);
上の図からわかるように、ターゲットプログラムは入力されたすべての文字列を整数に変換します。atoi
または_wtoi
が入力の内容を日本のタイプに変換できない場合、0 が返されます。
atoi の戻り値
eax の戻り値が esi に渡され、ユーザーが入力した元の文字列を出力した後、esi の値が0x12457
と比較されます。
ユーザーが入力した 10 進数の文字列は解析され、16 進数に変換され、それからハードコーディングされた値と比較されます。入力された文字列がハードコーディングされた値に対応する 10 進数であれば、成功するはずです。
上の図では、jnz 命令(not zero)が使用されているため、「bad reverser」と出力されます。等しければ、「good reverser」と出力されます。
0x124578
を 16 進数から 10 進数に変換すると 1197432 になります。
ターゲットプログラムでこの 10 進数 1197432 を入力すると、成功したことが確認でき、good reverser
が出力されます。
ターゲットプログラムの解析はここで終了です。この章では、関数スタックの逆アセンブリ解析について学びました。関数の引数の渡し方、ローカル変数、atoi 関数などが含まれます。