こんにちは、Habralyudi。 このトピックでは、単純なクラックミーをどのように探ったかを説明します。 このkryakmisは、まず、逆転を練習したい初心者向けです。 このテーマに関する一連の記事を、単純なものから複雑なものへと徐々に進めていきます。
開始する
それでは始めましょう。
必要なツール:
- 1. Crackme自体(crackmes.deを使用)
- 2.デバッガー(私は個人的にOllyを使用しています)
開始するには、クラックを実行します。 名前と登録コードを入力するための2つのフィールドがある単純なフォームが表示されます。 偽のデータを入力すると、シリアルが間違っているという不正なメッセージが表示されます。
MessageBoxA関数によって呼び出されたメッセージが表示され、フィールドのテキストがGetDlgItemTextA関数によってバッファに入力されると、状況はより明確になります。
アクションプラン
したがって、アクションのさらなるアルゴリズム:
1.クラックをデバッガーにロードします。
2. MessageBoxAおよびGetDlgItemTextA関数のすべての呼び出しにブレークを設定します(Ollyでは、Alt + F1キーの組み合わせを押して、表示されるフォームにbpx%function_name%コマンドを入力します)。
3.ブレークポイントまでプログラムを実行し、以下を実行します。a)虐待メッセージでブランチへの遷移の場所を探し、条件付き遷移を変更して、「正しい」メッセージでブランチに移動します。
b)シリアルの名前を変更する場所を探し、暗号化アルゴリズムを見つけて、keygenを記述します。
私の主な目標は調査することなので、計画bに従います。
デバッグ防止コード
ブレークを配置してプログラムを実行すると、MessageBoxAのブレークが機能したことがわかります。 しかし、デバッガなしで初めてプログラムを実行した後、メッセージが表示されなかった他のMessagBoxは何ですか? プログラムを一歩進めて(OlliでF8キーを押す)、次のように表示されます。
私たちのクラックには、デバッグ防止コードがあります。 それを回避する必要があります。 コードを少し上にスクロールし、「デバッグ対策メッセージボックス」へのジャンプ元を見つけます。 この場所からのコードは次のとおりです。
004027DA . 64:A1 18000000 MOV EAX,DWORD PTR FS:[18]
004027E0 . 8B40 30 MOV EAX,DWORD PTR DS:[EAX+30]
004027E3 . 8B40 18 MOV EAX,DWORD PTR DS:[EAX+18]
004027E6 . 8378 10 00 CMP DWORD PTR DS:[EAX+10],0
004027EA 75 01 JNZ SHORT crackme_.004027ED //
パッチを適用する必要があります。 JNZコマンド(opcode 75)をJE(opcode 74)に変更します。 パッチを適用し、デバッガーでプログラムを再起動しますが、不正なメッセージボックスは表示されません。
アルゴリズム
フィールドに偽のデータを入力し(someuser:somepasswordと入力)、[確認]をクリックします。 そして、GetDlgItemTextA関数の呼び出しでブレークダウンがトリガーされます。 このコードは次のとおりです。
00401D3E . E8 CD0D0000 CALL <JMP.&user32.GetDlgItemTextA> // GetDlgItemTextA
00401D43 . BE 64404000 MOV ESI,crackme_.00404064 // ESI
00401D48 > 8006 01 ADD BYTE PTR DS:[ESI],1 // 1 ESI
00401D4B . 83C6 02 ADD ESI,2 // ESI 2, ESI ,
00401D4E . 803E 00 CMP BYTE PTR DS:[ESI],0 // ESI
00401D51 .^75 F5 JNZ SHORT crackme_.00401D48 // "" 00401D48
00401D53 . E9 BB010000 JMP crackme_.00401F13 // "" 00401F13
したがって、ユーザー名暗号化アルゴリズムが表示されます。
さらにトレースすると、次のセクションに進みます。
00401F1D . 81F9 00500000 CMP ECX,5000
00401F23 -7F FE JG SHORT crackme_.00401F23
私の意見では、これはもう1つのデバッグ対策手法であるため、JGをJEに置き換え、静かにトレースします。 また、GetDlgItemTextA関数の内訳に出会います。 今回、彼女はregを読みます。 コード:
00401FE6 > E8 250B0000 CALL <JMP.&user32.GetDlgItemTextA> // GetDlgItemTextA
00401FEB . BE 64404000 MOV ESI,crackme_.00404064 // ESI ( . )
00401FF0 . BF 64484000 MOV EDI,crackme_.00404864 // EDI . ,
00401FF5 . 8B07 MOV EAX,DWORD PTR DS:[EDI] // EAX . ,
00401FF7 . 8B1E MOV EBX,DWORD PTR DS:[ESI] // EBX .
00401FF9 . 3BC3 CMP EAX,EBX //
00401FFB 0F85 C4020000 JNZ crackme_.004022C5 // , 004022C5
00402001 . 83C6 04 ADD ESI,4
00402004 . 83C7 04 ADD EDI,4
00402007 . 8B1E MOV EBX,DWORD PTR DS:[ESI] // EBX .
00402009 . 8B07 MOV EAX,DWORD PTR DS:[EDI] // EAX . ,
0040200B . 3BC3 CMP EAX,EBX //
0040200D 0F85 B2020000 JNZ crackme_.004022C5 // 004022C5
00402013 . E9 5C000000 JMP crackme_.00402074 // ""
おわりに
したがって、暗号化アルゴリズム全体は、名前の2文字ごとの文字をASCIIテーブル内の後続の文字に置き換えたものであることがわかります。
さらに、プログラムはシリアルの最初の8文字のみをチェックするため、欠点です。
Keygen
そして、keygenは次のとおりです。
var
s:string;
i:integer;
c:char;
begin
readln(s);
while i<= length(s) do begin
Inc(s[i]);
i:=i+2;
end;
writeln(s);
end.
ご清聴ありがとうございました。
PSパスカル、すみません、別のコンパイラが見つかりませんでした。
PPSそして、シンプルで申し訳ありません。