コルサダーのブルータスクラックメ#03

エントリー



私は逆の経験はありません。条件付きブランチハックを作成できる基本的なアセンブラー知識があり、入力された値に関係なく、このアプリケーションは常にsuccess-pathになります。 しかし、これはあまりにもありふれたものであり、ここで公開することはできず、入力されたキーをチェックするためのアルゴリズムの完全な再現にまだ熟成していないため、ブルート方式、つまり 順次キー選択。 もちろん、この方法はその急峻さでも注目に値するとは言えませんが、少なくともこの方法の詳細な説明は、逆の記事ではそれほど一般的ではありません。



画像








出所



crackme#03オリジナル投稿へのリンク。



このクラックが投稿されたブランチで、ユーザーARCHANGELはC ++でブルートフォースメソッドを公開しました。これは、このクラックの正しいパスワードを実際に生成します。 彼は、アルゴリズムを再現し、値0x23a06032を見つけ、結果のcrcと比較することができたため、ブルータスを高級言語で書く余裕がありました。



私はまだasm-eのアルゴリズムを深く分析する方法を学んでいないので、キャッシュデスクを離れることなく、クラック自体の検証アルゴリズムをブラックボックスとして使用して作業します。



条件付きジャンプ分析



クラックから始めて、コンピューターのサウンドをオフにします(明らかにこれは作成者が行ったもので、サウンドを追加します)。



画像






OllyExtプラグインを使用してOllyDbg 2.01を起動すると、次の設定が表示されます。



画像






このプラグインは、潜在的なアンチデバッグ技術を取り除くのに役立ちます。



Olgaから実行中のcrackme#03.exeプロセスにアタッチします:ファイル→アタッチ...



画像






次に、入力フィールドに値を入力して、処理されるコードを簡単に見つけようとします。 これを行うには、テキスト(特にGetDlgItemTextA)を取得するための潜在的な関数にブレークポイントを設定するか、ソースモジュールのコードをめくる(ここでは小さいため)。 [チェック]ボタンをクリックします。



画像






ブレークポイントは機能し、F8を1回クリックしてリストを確認します。 入力した文字列が004095BCに保存されていることがわかります。 0040101Fの説明も参照してください。 入力された文字列の長さと値12を比較し、不等の場合は004010AFになります。



次に、 00401028の命令に注意してください。この命令は、入力された値の12バイト目を値72と比較します。これはASCIIエンコードの文字rです。 不平等の場合は、 004010AFで再びスローされます 。 これはどのような住所ですか? これについては後で詳しく説明します。



ここで、 00401031-0040104Cの範囲の命令に注意を払いましょう。 repneおよびscasコマンドのアセンブラコマンドリファレンスをスモークし、コードの選択領域をトレースしたことから、aehnprwyが必要なキーの有効なアルファベットであると結論付けました。



画像



004010AFにあるものを見てみましょう。 パスワードの入力に失敗したというメッセージがあります。



画像



したがって、初期分析を要約するには:



1)キーは12文字で構成する必要があります。

2)キーの最後の文字はrでなければなりません。

3)キー文字はアルファベットaehnprwyに属している必要があります。



ブルートフォース



ブルートメソッドの実装に進みます。 最初に概念レベルで実装します。 ブロック図では可能ですが、高級言語でも可能です。 プロトタイプをC ++で実装しました。 さらに資料を理解するには、ネタバレの下でコードをダイジェストする必要があります。



非表示のテキスト
#include <stdio.h> #include <string.h> const char *Alphabet = "aeyhpnwr"; int Password_len = 12; int CheckPassword(char pass[]) //    . { if (strcmp(pass, "aaaaaaahaahr") == 0) //    return 0; return 1; } int main() { int Alphabet_len = strlen(Alphabet); char* CodeArray = new char[Password_len + 1]; char* Password = new char[Password_len + 1]; int n; //  ,       (.. )   Password[Password_len] = 0; for (int i = 0; i < Password_len; i++) { CodeArray[i] = 0; Password[i] = Alphabet[CodeArray[i]]; } //    r Password[Password_len - 1] = 'r'; while (true) { //printf("\nCurrent pass = %s", Password); if (CheckPassword(Password) == 0) { printf("\nRight Password = %s\n", Password); break; } n = Password_len - 2; while (n >= 0) { CodeArray[n]++; if (CodeArray[n] >= Alphabet_len) { CodeArray[n] = 0; Password[n] = Alphabet[0]; n--; continue; } Password[n] = Alphabet[CodeArray[n]]; break; } } delete[] CodeArray; delete[] Password; }
      
      





主な段階:



1)初期値を使用したキー(パスワード)の初期化。

2)鍵の検証。

3)キーが正しくない場合は、次のキーを生成して手順2に進みます。キーが正しい場合は、手順4に進みます。すべてのキーを調べてもキーがまったく表示されない場合は、手順5に進みます。

4)Crackmeがハッキングされています。

5)Crackmeはハッキングされていません。 どこかで間違えた。



キーの初期化



プログラムは、アドレス004095BCでキーを保存し、アクセスします-そこで、それを初期化します。 アルファベットは00409071にあります。



004095CCは、 CodeArrayを保存するメモリアドレスです。



キーを初期化するために、コードセクションの未使用領域を見つけ、そこに命令を挿入します。 アドレス00404122を選択しました



この初期化を実際に完了するために、GetDlgItemTextAが呼び出される場所に移動し、その呼び出しを00404122のコードへの無条件ジャンプに慎重に置き換え、以前のプッシュコマンドをnop-sに置き換えます。 CMP EAX、0Cコマンドのコマンドアドレスが同じままになるように、すべてを慎重に行います: 0040101F



画像



以下の図は、初期化コード自体を示しています。 最後に、無条件の0040101Fへの移行の結果として、キー検証アルゴリズムに進みます。



画像



非表示のテキスト
反復あたり4バイトの3回の反復で、12個のシングルバイト値のCodeArray配列を無効にすることができます。



 00404122 B9 03000000 MOV ECX,3 00404127 BA CC954000 MOV EDX,004095CC ;   CodeArray 0040412C C7448A FC 000 MOV DWORD PTR DS:[ECX*4+EDX-4],0 00404134 E2 F6 LOOP SHORT 0040412C
      
      





次に、アドレス004095BCの文字列の各バイトに最初の(つまりゼロの)アルファベット文字を付加します



 for (int i = 0; i < Password_len; i++) { Password[i] = Alphabet[CodeArray[i]]; }
      
      





 00404136 BB BC954000 MOV EBX,004095BC ;   ,    crackme 0040413B B9 0C000000 MOV ECX,0C 00404140 31C0 XOR EAX,EAX 00404142 8A4411 FF MOV AL,BYTE PTR DS:[EDX+ECX-1] 00404146 8A80 71904000 MOV AL,BYTE PTR DS:[EAX+409071] ; 409071 -   0040414C 884419 FF MOV BYTE PTR DS:[EBX+ECX-1],AL 00404150 E2 F0 LOOP SHORT 00404142 00404152 C643 0B 72 MOV BYTE PTR DS:[EBX+0B],72 ;    r 00404156 C643 0C 00 MOV BYTE PTR DS:[EBX+0C],0 ;     0040415A B8 0C000000 MOV EAX,0C ;     12 0040415F ^ E9 BFCEFFFF JMP 0040101F ;     
      
      







次のキー値を取得する



次のキー値を取得するためのコードを実装する必要があります。 このために、アドレス00404165 (初期化コードの直後)を選択し、プログラムがラマーと呼んでいる場所からアドレスに移行します。



アドレス004010AFおよび004010B1 命令を変更します。



画像



さて、アドレス00404165で 、新しいキーを取得するためのコード実装します。



画像



非表示のテキスト
 00404165 B9 0B000000 MOV ECX,0B ;   ,    0040416A BA CC954000 MOV EDX,004095CC ;   CodeArray 0040416F BB BC954000 MOV EBX,004095BC ;   ,    crackme 00404174 31C0 XOR EAX,EAX 00404176 FE4411 FF INC BYTE PTR DS:[EDX+ECX-1] ;        0040417A 807C11 FF 08 CMP BYTE PTR DS:[EDX+ECX-1],8 ; ,       0040417F 7D 15 JGE SHORT 00404196 00404181 8A4411 FF MOV AL,BYTE PTR DS:[EDX+ECX-1] ;   ,    AL 00404185 8A80 71904000 MOV AL,BYTE PTR DS:[EAX+409071] ;       . 409071 -   0040418B 884419 FF MOV BYTE PTR DS:[EBX+ECX-1],AL ;    -   0040418F B8 0C000000 MOV EAX,0C ;     12 00404194 ^ EB C9 JMP SHORT 0040415F ;      00404196 83F9 01 CMP ECX,1 ;     , ,       00404199 7F 02 JG SHORT 0040419D ; 0040419B CD 03 INT 3 ;  ,     0040419D C64411 FF 00 MOV BYTE PTR DS:[EDX+ECX-1],0 ;  ecx (i) > 1, CodeArray[i] = 0; 004041A2 A0 71904000 MOV AL,BYTE PTR DS:[409071] ;  AL   ()  . 409071 -   004041A7 884419 FF MOV BYTE PTR DS:[EBX+ECX-1],AL ;    -   004041AB 49 DEC ECX ;   .  004041AC ^ EB C6 JMP SHORT 00404174 ;     
      
      







打ち上げ



チェックボタンをクリックして、お茶を飲みに行きます。 くそー、そしてお茶は長い間沸騰している、それは再び沸騰する必要があります。



画像






しばらくすると、次のようになります



画像






004095BCにあるものを見る



画像



happynewyear-これは望ましいキーです。



All Articles