心のトレーニングとしての法的ハッキング

ITの従業員は、心のためのエクササイズをしばしば思い付きます;探究心は常にウォームアップを必要とします。 最も厳しくて物議を醸す方法の1つ-特別に保護されたパズルプログラム(多くの場合、crackmeと呼ばれます)のハッキングについてお話したいと思います。



このようなパズルが収集される場所の1つはcrackmes.deです。



ハッキングを試すことができる興味深いプログラムがたくさんあります。 犯罪なし-プログラムは、この目的のために特別に作成されています(いわゆるcrackmeおよびreverseme)。



多くの場合、彼らは「すべての防御がハッキングされる可能性があります」と言うのが好きです。 crackmeのいくつかを掘り下げることで、気が変わるかもしれません。





それでは始めましょう:



多くのcrackmeの一般的な作業スキーム-そして、このパスワードで復号化されたデータから作成されたハッシュに応じて、コード内のいくつかの手順、および「正しくないパスワード」を暗号化しましょうか?



または、オプションとして、SEH(構造化例外処理-ハードウェアおよびソフトウェア例外を処理するためのメカニズム)をフックします。ここに、不正なパスワードに関するメッセージボックスを配置します。 「真の」コマンドオペコード。そうでない場合、プロセッサは間違ったオペコードに関する例外をスローし、「コーシャ」はエラー通知を受け取るSEHを使用します。 一般的に、このオプションは「聖」ではありません。これは、解読後、「半無効」なオペコード、たとえば手順外のjmpコマンドも可能になるためです。



しかし、最初はこれで十分です。



だから、ここからクリームを取ります: crackmes.de/users/sharpe/unlockme_crackme_8_by_sharpe/downloadまたはここから:

crackmes.de/users/sharpe/unlockme_crackme_7_by_sharpe/download (ちなみに、7番目はまだハッキングされていません)をデバッガーにロードします-私はOlya(OllyDBG)を使用しました-プログラムは非常に小さく、コードセグメントは0x2B6 = 694バイトで、コードの一部を見つけるのは非常に簡単ですパスワードの読み取りを担当します。



 0040107F |. 3D F3030000 CMP EAX,3F3 00401084 |. 75 4E JNZ SHORT 004010D4 00401086 |. 6A 21 PUSH 21 ; /Count = 21 (33.) 00401088 |. 68 88314000 PUSH 403188 ; |Buffer = eight.00403188 0040108D |. 68 F1030000 PUSH 3F1 ; |ControlID = 3F1 (1009.) 00401092 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd 00401095 |. E8 04020000 CALL 0040129E ; \GetDlgItemTextA 0040109A |. 83F8 07 CMP EAX,7     0040109D |. 76 1F JBE SHORT 004010BE    0040109F |. 83F8 20 CMP EAX,20      004010A2 |. 73 1A JNB SHORT 004010BE 004010A4 |. E8 D9000000 CALL 00401182   004010A9 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] 004010AC |. E8 FD000000 CALL 004011AE   004010B1 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] 004010B4 |. E8 61010000 CALL 0040121A   004010B9 |. E9 85000000 JMP 00401143 ; eight.00401143 004010BE |> 6A 30 PUSH 30     ))) 004010C0 |. 68 34314000 PUSH 403134 ; |Title = "-=[ Unlock Code Error" 004010C5 |. 68 4A314000 PUSH 40314A ; |Text = "The entered Unlock Code is invalid. 004010CA |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hOwner 004010CD |. E8 D8010000 CALL 004012AA ; \MessageBoxA 004010D2 |. EB 6F JMP SHORT 00401143 ; eight.00401143
      
      







したがって、これに基づいて、パスワードの長さは8〜32文字の範囲である必要があることがわかります。その場合、元のパスワードを変換する関数にジャンプします。



 00401182 /$ 57 PUSH EDI 00401183 |. 33FF XOR EDI,EDI 00401185 |. BE 88314000 MOV ESI,403188 ;        0040118A |. B9 20000000 MOV ECX,20 0040118F |. C705 A8314000 >MOV DWORD PTR DS:[4031A8],0 ;    «» 00401199 |> AC /LODS BYTE PTR DS:[ESI] 0040119A |. 85C0 |TEST EAX,EAX 0040119C |. 74 08 |JE SHORT 004011A6 ; eight.004011A6 0040119E |. 8BC8 |MOV ECX,EAX ;   «»   004011A0 |. 03F8 |ADD EDI,EAX ;   004011A2 |. D3C7 |ROL EDI,CL ;    004011A4 |.^EB F3 \JMP SHORT 00401199 ; eight.00401199 004011A6 |> 893D A8314000 MOV DWORD PTR DS:[4031A8],EDI;    004011AC |. 5F POP EDI 004011AD \. C3 RETN
      
      







そして、ここにコードデコーダーがあります:



 004011AE /$ 55 PUSH EBP 004011AF |. 8BEC MOV EBP,ESP 004011B1 |. 83EC 04 SUB ESP,4 004011B4 |. 68 88314000 PUSH 403188 ;      004011B9 |. E8 C2000000 CALL 00401280 ;   –   004011BE |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX 004011C1 |. 837D FC 01 CMP DWORD PTR SS:[EBP-4],1 004011C5 |. 77 16 JA SHORT 004011DD ; eight.004011DD 004011C7 |. 6A 30 PUSH 30 004011C9 |. 68 34314000 PUSH 403134 ; |Title = "-=[ Unlock Code Error" 004011CE |. 68 4A314000 PUSH 40314A ; |Text = "The entered Unlock Code is invalid. 004011D3 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hOwner 004011D6 |. E8 CF000000 CALL 004012AA ; \MessageBoxA 004011DB |. EB 1E JMP SHORT 004011FB ; eight.004011FB 004011DD |> B8 49114000 MOV EAX,401149 ;       004011E2 |. B9 7F114000 MOV ECX,40117F 004011E7 |. 2BC8 SUB ECX,EAX 004011E9 |. 33DB XOR EBX,EBX 004011EB |> 8B1418 /MOV EDX,DWORD PTR DS:[EAX+EBX] 004011EE |. 3315 A8314000 |XOR EDX,DWORD PTR DS:[4031A8];    - 004011F4 |. 891418 |MOV DWORD PTR DS:[EAX+EBX],EDX 004011F7 |. 43 |INC EBX 004011F8 |. 49 |DEC ECX 004011F9 |.^75 F0 \JNZ SHORT 004011EB ;   004011FB |> C9 LEAVE 004011FC \. C2 0400 RETN 4
      
      







これで明らかです。しかし、正しいハッシュコードを見つける方法は?

バスティング?



非常に長い時間がかかります。最初に復号化してから、結果のコードの「エントロピー」を計算する必要があり、「エントロピー」が最小のコードが機能している可能性がありますが、このためにはすでに作成された逆アセンブルエンジンを作成または使用する必要があります;

また、SEHを使用して、その本体でbromforserコードを登録できますが、1つの「false-correct」命令でもプログラム実行の正しいコースを完全に変更できます。

しかし、プログラムが純粋なアセンブラーで書かれているにもかかわらず、作者はコードでスタックを「開く」ことを多く使用していることに気づいたので、「暗号化された」コードの最初の正しい4バイトは次のようになります。



 PUSH EBP MOV EBP,ESP
      
      





値:0x55、0x8V、0xES



そして、現在(暗号化手順を実行する前)の値は0x66、0x71、0x77ですが、「XOR」関数のプロパティを覚えて(見ることができます)、最終的なハッシュが既知になることがわかります。

「リトルエンディアン」契約について忘れないでください。



 77 71 66 ^    ^   ^  **********  8 55
      
      







したがって、「電卓」でこの問題を考慮すると、SS = 0x33であることがわかります。 BB = 0xC9; AA = 0x61、

結果のシーケンス:XX61C93。



残念ながら、「自己キー生成」a(バイナリパッチ)を使用してブルートフォースを使用して最後のバイトを検索する必要があり、最終的にE961C933を取得しました。



そして、復号化された手順には実際には多くのゴミが含まれています(「難読化」)

しかし、「スタックを開く」ことで私たちは救われ、解読された手順(本体内)は次のようになりました。

 00401149 $ 55 PUSH EBP 0040114A . 8BEC MOV EBP,ESP 0040114C . D3C8 ROR EAX,CL 0040114E . 58 POP EAX 0040114F . EB 04 JMP SHORT 00401155 ; eight.00401155 00401151 D6 DB D6 00401152 FE DB FE 00401153 . 32C9 XOR CL,CL 00401155 > BE 9C314000 MOV ESI,40319C ; ASCII "Secret: Marius!" 0040115A . C706 53656372 MOV DWORD PTR DS:[ESI],72636553 00401160 . C746 04 65743A>MOV DWORD PTR DS:[ESI+4],203A7465 00401167 . C746 08 4D6172>MOV DWORD PTR DS:[ESI+8],6972614D 0040116E . C746 0C 757321>MOV DWORD PTR DS:[ESI+C],217375 00401175 . EB 00 JMP SHORT 00401177 ; eight.00401177 00401177 > 58 POP EAX 00401178 . FFE0 JMP EAX 0040117A F7 DB F7 0040117B ED DB ED 0040117C 12 DB 12 0040117D DA DB DA 0040117E 3F DB 3F ; CHAR '?' 0040117F 4E DB 4E ; CHAR 'N' 00401180 40 DB 40 ; CHAR '@' 00401181 C4 DB C4
      
      







イータ手順は、「秘密:マリウス」という単語を記録するだけです。 対応するインデックスに従って。

その後、元のパスワードを見つけるために残ります-さて、ここで-あなたを助けるためにブルートフォース))))



変換手順は、プログラムで「リップ」することができ、このケースをアセンブラー挿入として作成できます。



  mov dword ptr [znach], 0 xor edi, edi mov esi, [str1] m: lodsb test al, al jz m1 mov ecx, eax add edi, eax rol edi, cl jmp m
      
      







はい、元のパスワードは005sjです[Vg



cudaのようなエキゾチックなものやシェーダー用にブルートフォースを書く場合にのみ、サイクリックシフト命令がないことを覚えておいてください-rol eax、5。それを2つの単純なシフト(左と右)に置き換え、受信した; 次の形式の実装:#define ROT(n、m)(((n)<<(m))|((n)>>(32-(m))))

以下の投稿では、破壊不可能な防御を破る他の興味深い方法について学びます。



PS。 記事の著者(アッシュ-彼はまだハブに参加していません)から、この記事の公開を依頼されました。



All Articles