Paic_CitronによるKeygenMe#2分析

crackmes.deのKeygenMeページ
有効なシリアルを見つける必要があります。

唯一の保護はシリアルです...!

これは一種の頭痛です...:D

頑張って
難易度:5-解決すべき専門的な問題
プラットフォーム:Windows
言語:Borland Delphi


このkeygenmeはコンソールアプリケーションであるため、ボタンクリックハンドラーなどを探す必要はありません。 そのため、条件付き遷移を探しています。完了すると、実行の成功に関するメッセージが表示されます。
 コード:0040A71D mov edx、オフセットaSerial;  「シリアル:」
コード:0040A722はWrite0LStringを呼び出します
コード:0040A727 call @ Flush $ qqrr15System @ TTextRec; フラッシュ(システム:: TTextRec&)
コード:0040A72C呼び出し@_IOTest
コード:0040A731 mov edx、オフセットシリアル
コード:0040A736 mov eax、ds:off_40B370
コード:0040A73B @ReadLStringを呼び出す
コード:0040A740 mov eax、ds:off_40B370
コード:0040A745 @ReadLnを呼び出す
コード:0040A74A呼び出し@_IOTest
コード:0040A74F mov eax、ds:シリアル
コード:0040A754はLStrLenを呼び出します
コード:0040A759 mov edi、eax
コード:0040A75Bテストedi、edi
コード:0040A75D jle _end_of_serial
コード:0040A763 mov ds:pos、1
コード:0040A76D
コード:0040A76D _next_char :; コードXREF:開始+ 2FE j
コード:0040A76D mov eax、ds:シリアル
コード:0040A772 mov edx、ds:pos
コード:0040A778 movzx edx、バイトptr [eax + edx-1]
コード:0040A77D mov eax、esi
コード:0040A77F call ProcessCommand
コード:0040A784プッシュオフセットtest_z;  a4
コード:0040A789 mov ecx、オフセットtest_y;  a3
コード:0040A78E mov edx、オフセットtest_x;  a2
コード:0040A793 mov eax、esi;  a1
コード:0040A795 GetPosMarker3Dを呼び出す
コード:0040A79A cmp ds:test_x、2
コード:0040A7A1 jnz _incorrect_pos
コード:0040A7A7 cmp ds:test_y、4
コード:0040A7AE jnz _incorrect_pos
コード:0040A7B4 cmp ds:test_z、4
コード:0040A7BB jnz _incorrect_pos
コード:0040A7C1 cmp dword ptr [esi + 218h]、0Ch
コード:0040A7C8 jnz _incorrect_pos
 ...キーが正常に検出されたことを示すメッセージ出力...
コード:0040A97B _incorrect_pos :; コードXREF:開始+ 11D j
コード:0040A97B; 開始+ 12A j ...
コード:0040A97B inc ds:pos
コード:0040A981 dec edi
コード:0040A982 jnz _next_char
コード:0040A988
コード:0040A988 _end_of_serial :; コードXREF:開始+ D9 j
コード:0040A988 mov eax、ebx
コード:0040A98A呼び出し@WriteLn
コード:0040A98F呼び出し@_IOTest
コード:0040A994 mov eax、ebx
コード:0040A996 mov edx、オフセットaNanCEstPasBon;  「ナン、パパボン:)」
コード:0040A99BはWrite0LStringを呼び出します
コード:0040A9A0呼び出し@WriteLn 


Delphi構文の同じコードは次のようになります。

したがって、シリアル番号の次の文字を処理した後にタスクを正常に完了するには、ラベルの座標が(2、4、4)であり、変数が12である必要があります。

関数GetPosMarker3D( 00409D88 )の内容を見てみましょう。

要素は、マーカーが設定されている3次元配列(キューブ)で検索されます。 ここで、キューブの寸法-5x5x5を確認できます。
キューブの各要素は、0〜15の数字で記述されます。
キューブの初期化は、アドレス00408D90関数で発生します。
展開された形式の初期化されたキューブの内容:


キューブ要素で可能な値のリスト:
0普通の畑
1通行不可能なフィールド(壁)
2開始位置
3ID = 4のフィールドを通過するためのキー
4イベントトリガーフィールド
5ID = 6のフィールドを通過するためのイベントフィールド
6イベントトリガーフィールド
7別のレベルへのゲートウェイ
8現在のレベルを90度回転
9テレポート開始点
Aテレポート先
B定数(1,2,3,6)を持つフィールド
C算術演算のフィールド(+、-、/、*)
D最初のオペランドの結果を入れます
Eカウント式
Fキューブを出る


機能0040A2C0処理された入力シリアル番号の文字であるコマンドのリスト:
P左に移動(X + 1)
私は右に移動(X-1)
A上に移動(Y-1)
C下に移動(Y + 1)
D1レベル下に移動(Z + 1)
うん1レベル上に移動(Z-1)
-アクションを実行する

DおよびUコマンドに必要な条件は、ID = 7のセル内のマーカーの位置と、同じ座標(X、Y)の別のレイヤー上の同じ受信ゲートウェイの存在です。
ID = 00409FEC 、B、C、D、Eのフィールドにアクションコマンドを適用できます。アクションは、アドレス00409FECプロシージャで処理されます。

基本的に、このキーゲンム内には小さなターンベースのクエストがあります。 主なタスクは、座標(1,0,0)のフィールドから座標(2、4、4)のフィールドに移動することです。

第4レベルのテレポートでの通信は次のとおりです。


最初の4つのレイヤーの通過は、マップ内を移動することのみです。 最後の5番目のレイヤーでは、キューブを終了するための追加条件をまだ満たす必要があります。
数字のセット1,3,4,6(ID = Bのフィールド)と算術演算+、-、*、/(ID = Cのフィールド)を使用すると、12の数字を取得する必要があり、すべての定数を使用する必要があります。 つまり オプション(3-1)* 6は適切ではありません。
このミニ計算機を使用するには、最初にID = Bの2つのフィールドとID = Cの1つのフィールドでアクション(コマンド-)を実行する必要があります。その後、ID = Eのフィールドを踏んでアクションを実行します。 結果を第1オペランドとして使用するには、ID = Dのフィールドでアクションを実行する必要があります。すべての操作の後、ID = Fのフィールドで立ち上がります。

最初のレイヤーを渡すためのコード:
CIIAIPCPPPCCCIIIAIA--AD

第2層と第3層の通過は密接に相互接続されているため、解決策は一度に2対1です。
CCCAAAAII---AAPPPDC-AUIIICC---PPAADCI---APUIIPPDIC-PAUIIDIAD

4番目のレイヤーのコード:
PAICP--CPIUC-ADIICAI-ICAAAAPAD

最後に、最後の5番目のレイヤーについて:
CCP-A-II-CC-PP-AAA-II-CCC-PP-AAP-IIII-PCC-P-

合計シリアル番号があります:
CIIAIPCPPPCCCIIIAIA--ADCCCAAAAII---AAPPPDC-AUIIICC---PPAADCI---APUIIPPDIC-PAUIIDIADPAICP--CPIUC-ADIICAI-ICAAAAPADCCP-A-II-CC-PP-AAA-II-CCC-PP-AAP-IIII-PCC-P-

keygenmeに入力して、おめでとうございます。


記事に加えて、キューブのすべてのレイヤーをバイナリ形式および擬似グラフィック形式で通過する2つのビデオ。

各文字の処理後にキューブの内容を分析するために、keygenmeアドレススペースに埋め込まれた簡単なdllが作成されました。

Source: https://habr.com/ru/post/J180919/


All Articles