最小のリバヌス゚ンゞニアリングBreaking Keygen

この投皿は、このトピックに興味を持ち始めたばかりの人にずっお本圓に興味深いものになりたす。 経隓のある人では、圌はあくびを起こすだけです。 おそらく゚ピロヌグを陀いお...

自瀟補品のデバッグや最適化に関係しない、それほど法的ではない郚分のリバヌス゚ンゞニアリングには、「それがどのように機胜するかを調べる」ずいうタスクも含たれたす。 蚀い換えれば、プログラムの元のアルゎリズムを埩元し、その実行可胜ファむルを手にしたす。

基本を守り、いく぀かの問題を回避するために、䜕かを「クラック」するのではなく、... keygen。 90では、囜際法を含め、梱包、暗号化、たたはその他の方法で保護されたせん...



最初は蚀葉でした。 ダブル


そのため、keygenず逆アセンブラヌが必芁です。 2番目に぀いおは、それがIda Proであるず仮定したしょう。 Webで芋぀かった実隓的な名前のないkeygen

画像








Idaでkeygenファむルを開くず、関数のリストが衚瀺されたす。

画像



このリストを分析した埌、いく぀かの暙準関数WinMain、start、DialogFuncず倚数の補助システム関数が衚瀺されたす。 これらはすべお、フレヌムワヌクを構成する暙準機胜です。

逆アセンブラは、プログラムのタスクの実装を衚すナヌザヌ関数を認識せず、APIおよびシステムコヌルのラッパヌではなく、単にsub_digitsを呌び出したす。 そのような関数が1぀しかないこずを考えるず、関心のあるアルゎリズムたたはその䞀郚を含む可胜性が最も高いず思われたす。

画像



keygenを実行したしょう。 圌は2぀の4桁の行を芁求したす。 8文字が䞀床にキヌ蚈算機胜に送信されるずしたす。 機胜コヌドsub_401100を分析したす。 仮説に察する答えは、最初の2行に含たれおいたす。

var_4 = dword ptr -4

arg_0 = dword ptr 8


2行目は、関数匕数をオフセット8で取埗するこずを明確に瀺しおいたす。ただし、匕数のサむズは8ではなく4バむトに等しいダブルワヌドです。したがっお、ほずんどの堎合、関数は1パスで4文字の1行を凊理し、2回呌び出されたす。

確かに生じる可胜性のある質問は、なぜ関数匕数を受け取るために8バむトのオフセットが予玄されおいたすが、匕数が1぀しかないため4を指しおいるのですか 思い出すず、スタックは小さくなりたす。 スタックに倀が远加されるず、スタックポむンタヌは察応するバむト数だけ枛少したす。 したがっお、スタックに関数の匕数を远加した埌、動䜜を開始する前に、䜕か他のものがスタックに远加されたす。 これは明らかに、システムコヌル関数を呌び出した埌にスタックに远加されるリタヌンアドレスです。



sub401100関数呌び出しが芋぀かったプログラム内の堎所を芋぀けたす。 実際には、DialogFunc + 97ずDialogFunc + 113の2぀がありたす。 興味のある手順はここから始たりたす

比范的長いコヌド
loc_401196: mov esi, [ebp+hDlg] mov edi, ds:SendDlgItemMessageA lea ecx, [ebp+lParam] push ecx ; lParam push 0Ah ; wParam push 0Dh ; Msg push 3E8h ; nIDDlgItem push esi ; hDlg call edi ; SendDlgItemMessageA lea edx, [ebp+var_1C] push edx ; lParam push 0Ah ; wParam push 0Dh ; Msg push 3E9h ; nIDDlgItem push esi ; hDlg call edi ; SendDlgItemMessageA pusha movsx ecx, byte ptr [ebp+lParam+2] movsx edx, byte ptr [ebp+lParam+1] movsx eax, byte ptr [ebp+lParam+3] shl eax, 8 or eax, ecx movsx ecx, byte ptr [ebp+lParam] shl eax, 8 or eax, edx shl eax, 8 or eax, ecx mov [ebp+arg_4], eax popa mov eax, [ebp+arg_4] push eax call sub_401100
      
      







最初に、2぀のSendDlgItemMessageA関数が連続しお呌び出されたす。 この関数は、芁玠のハンドルを取埗し、メッセヌゞシステムメッセヌゞを送信したす。 私たちのケヌスでは、䞡方のケヌスでMsgは0Dhであり、これはWM_GETTEXT定数に盞圓する16進数です。 ここでは、ナヌザヌが「2぀の4文字の文字列」を入力した2぀のテキストフィヌルドの倀が取埗されたす。 関数名の文字Aは、ASCII圢匏が䜿甚されおいるこずを瀺したす文字ごずに1バむト。

最初の行はlParamオフセットで曞き蟌たれ、2番目の行は明らかです-var_1Cオフセットで。

したがっお、SendDlgItemMessageA関数が実行された埌、レゞスタの珟圚の状態がpushaコマンドを䜿甚しおスタックに保存され、1行の1バむトがecx、edx、eaxレゞスタに曞き蟌たれたす。 その結果、各レゞスタは000000 ##の圢匏を取りたす。 次に

  1. SHLコマンドは、eaxレゞスタのビットの内容を1バむトシフトしたす。぀たり、算術の内容に16進法で100を乗算するか、10進法で256を乗算したす。 その結果、eaxの圢匏は0000 ## 00たずえば、00001200になりたす。
  2. OR挔算は、受信したeaxずecxレゞスタの間で000000 ##の圢匏で実行されたす00000034ずしたす。 その結果、eaxは00001234のようになりたす。
  3. 文字列の最埌の4バむト目は「無料」のexxに曞き蟌たれたす。
  4. exの内容は再びバむト単䜍でシフトされ、次のORコマンドのために䞋䜍バむトのスペヌスを解攟したす。 eaxは00123400のようになりたす。
  5. 今回はexずedxの間でOR呜什が実行されたす。これには、たずえば00000056が含たれたす。exは00123456です。
  6. 2぀のステップSHL eax、8およびORが繰り返され、その結果、新しいecxコンテンツ00000078が「終了」eaxに远加されたす。 その結果、eaxは倀12345678を保存したす。


次に、この倀は「倉数」に栌玍されたす-メモリ領域のオフセットarg_4に。 以前にスタックに保存されおいたレゞスタの状態以前の倀は、スタックからプルされ、レゞスタに配垃されたす。 次に、オフセットarg_4の倀がレゞスタeaxに再び曞き蟌たれ、この倀がレゞスタからスタックにプッシュされたす。 その埌、sub_401100関数呌び出しが続きたす。



これらの操䜜の意味は䜕ですか 理論を䜿わずに、実際に芋぀けるこずは非垞に簡単です。 デバッガヌにブレヌクポむントを蚭定したす。たずえば、プッシュeax呜什サブ関数が呌び出される盎前にプログラムを実行したす。 Keygenが起動し、回線を芁求したす。 qwerずtyuiに入り、ブレヌクポむントで停止した埌、倀72657771を確認したす。テキストにデコヌドしたすrewq。 ぀たり、これらの操䜜の物理的な意味は行反転です。



これで、sub_401100で元の行の1぀がダブルワヌドのサむズで送信され、䞊䞋逆さたになり、すべおの暙準レゞスタに収たるこずがわかりたした。 おそらく、sub_401100の手順をご芧ください。

別の比范的長いコヌド
 sub_401100 proc near var_4= dword ptr -4 arg_0= dword ptr 8 push ebp mov ebp, esp push ecx push ebx push esi push edi pusha mov ecx, [ebp+arg_0] mov eax, ecx shl eax, 10h not eax add ecx, eax mov eax, ecx shr eax, 5 xor eax, ecx lea ecx, [eax+eax*8] mov edx, ecx shr edx, 0Dh xor ecx, edx mov eax, ecx shl eax, 9 not eax add ecx, eax mov eax, ecx shr eax, 11h xor eax, ecx mov [ebp+var_4], eax popa mov eax, [ebp+var_4] pop edi pop esi pop ebx mov esp, ebp pop ebp retn sub_401100 endp
      
      





最初は、ここでは䜕も興味深いこずはありたせん。レゞスタの状態は慎重にスタックに保存されたす。 そしお、ここに私たちが興味を持っおいる最初のチヌムがありたす-PUSHAの指瀺に埓いたす。 オフセットarg_0に保存されおいる関数匕数をexxに曞き蟌みたす。 次に、この倀がeaxに転送されたす。 そしお、半分を切り捚おたす。思い出すず、この䟋では72657771がsub_401100に枡されたす。 10h10進数で16だけ巊に論理シフトするず、レゞスタの倀が77710000に倉わりたす。

その埌、レゞスタ倀はNOT呜什によっお反転されたす。 これは、レゞスタのバむナリ衚珟では、すべおのれロが1に倉わり、ナニットがれロに倉わるこずを意味したす。 この呜什を実行した埌のレゞスタには、888EFFFFFが含たれおいたす。

ADD呜什は、結果の倀を匕数の元の倀に远加加算、プラスなどしたす。この倀は、exxレゞスタにただ含たれおいたすなぜexxで、次にexaxで蚘述されたのかは明らかです。 結果はexに保存されたす。 この操䜜が完了した埌のexhの倖芳を確認したすFAF47770。

この結果はexxからexahにコピヌされ、その埌、SHR呜什がexaxのコンテンツに適甚されたす。 この操䜜はSHLの反察です。埌者が数字を巊にシフトした堎合、最初の数字は右にシフトしたす。 論理的な巊シフト挔算が2の环乗の乗算ず同等であるように、論理的な右シフト挔算は同じ陀算ず同等です。 この操䜜の結果である7D7A3BBの倀を芋おみたしょう。

次に、exずexの内容に察しお別の暎力を犯したす。XOR呜什はモゞュロ2加算たたは「排他的OR」です。 倧たかに蚀っお、この挔算の本質は、オペランドが明確な堎合にのみ、結果が単䞀真に等しいこずです。 たずえば、0 xor 1の堎合、結果はtrueたたは1です。 0 xor 0たたは1 xor 1の堎合、結果はfalseたたはれロになりたす。 この堎合、レゞスタeax7D7A3BBおよびexxFAF47770に関しおこの呜什に埓った結果、FD23D4CBの倀がレゞスタeaxに曞き蟌たれたす。



次のLEA ecxコマンド[eax + eax * 8]は、exを9で゚レガントか぀簡単に乗算し、結果をexxに曞き蟌みたす。 次に、この倀はedxにコピヌされ、13桁右にシフトされたす。edxで73213、exxでE6427B23になりたす。 その埌-再びXorim exxずedx、exx E6454930で曞きたす。 これをeaxにコピヌし、8A926000だけ巊に9桁シフトしおから、反転しお756D9FFFを取埗したす。 この倀をexxレゞスタに远加したす-5BB2E92Fがありたす。 これをeaxにコピヌし、17桁-2DD9-で既に右にシフトし、exxでXorimをシフトしたす。 最終的に5BB2C4F6になりたす。 それから...それから...䜕がありたすか なに、みんな

したがっお、この倀をオフセットvar_4のメモリ領域に保存し、レゞスタステヌタススタックからロヌドし、再びメモリから最終倀を取埗し、最埌にスタックの先頭に残っおいるレゞスタ状態を取埗したす。 関数を終了したす。 䞇歳...しかし、喜ぶには時期尚早です。最初の関数呌び出しの終了時点では、最倧4぀の半角文字が残っおいたすが、ただ生の文字列が残っおいるため、これを神の圢にする必芁がありたす。



逆アセンブラヌから逆コンパむラヌたで、より高いレベルの分析に移りたしょう。 Cのような擬䌌コヌドの圢匏で、sub_401100呌び出しを含むDialogFunc関数党䜓を想像しおください。 実際、この逆アセンブラは「疑䌌コヌド」ず呌びたす。実際、これは実際にはCコヌドであり、芋苊しいだけです。 私たちは芋たす

もっずコヌドが必芁です。 ゞグラットを構築する必芁がありたす。
  SendDlgItemMessageA(hDlg, 1000, 0xDu, 0xAu, (LPARAM)&lParam); SendDlgItemMessageA(hDlg, 1001, 0xDu, 0xAu, (LPARAM)&v15); v5 = sub_401100((char)lParam | ((SBYTE1(lParam) | ((SBYTE2(lParam) | (SBYTE3(lParam) << 8)) << 8)) << 8)); v6 = 0; do { v21[v6] = v5 % 0x24; v7 = v21[v6]; v5 /= 0x24u; if ( v7 >= 10 ) v8 = v7 + 55; else v8 = v7 + 48; v21[v6++] = v8; } while ( v6 < 4 ); v22 = 0; v9 = sub_401100(v15 | ((v16 | ((v17 | (v18 << 8)) << 8)) << 8)); v10 = 0; do { v19[v10] = v9 % 0x24; v11 = v19[v10]; v9 /= 0x24u; if ( v11 >= 10 ) v12 = v11 + 55; else v12 = v11 + 48; v19[v10++] = v12; } while ( v10 < 4 ); v20 = 0; wsprintfA(&v13, "%s-%s-%s-%s", &lParam, &v15, v21, v19); SendDlgItemMessageA(hDlg, 1002, 0xCu, 0, (LPARAM)&v13);
      
      







これは、アセンブリのリストよりも読みやすくなっおいたす。 ただし、すべおの堎合においお、デコンパむラヌに頌るこずができるわけではありたせん。アセンブラヌロゞックのスレッド、デバッガヌのレゞスタヌずスタックのステヌタスを数時間監芖し、FSBたたはFBIに説明を曞く準備が必芁です。 倕方には、特に面癜いゞョヌクがありたす。

私が蚀ったように、読曞は簡単ですが、それでも完璧にはほど遠いです。 コヌドを分析しお、倉数にわかりやすい名前を付けたしょう。 キヌ倉数には明確で論理的な名前を付け、カりンタヌにはたすたすシンプルにしたす。

同じ、䞭囜語からヒンドゥヌ語ぞの翻蚳のみ。
 SendDlgItemMessageA(hDlg, 1000, 0xDu, 0xAu, (LPARAM)&first_given_string); SendDlgItemMessageA(hDlg, 1001, 0xDu, 0xAu, (LPARAM)&second_given_string); first_given_string_encoded = sub_401100((char)first_given_string | ((SBYTE1(first_given_string) | ((SBYTE2(first_given_string) | (SBYTE3(first_given_string) << 8)) << 8)) << 8)); i = 0; do { first_result_string[i] = first_string_encoded % 0x24; temp_char = first_result_string[i]; first_string_encoded /= 0x24u; if ( temp_char >= 10 ) next_char = temp_char + 55; else next_char = temp_char + 48; first_result_string[i++] = next_char; } while ( i < 4 ); some_kind_of_data = 0; second_string_encoded = sub_401100(byte1 | ((byte2 | ((byte3 | (byte4 << 8)) << 8)) << 8)); j = 0; do { second_result_string[j] = second_string_encoded % 0x24; temp_char2 = second_result_string[j]; second_string_encoded /= 0x24u; if ( temp_char2 >= 10 ) next_char2 = temp_char2 + 55; else next_char2 = temp_char2 + 48; second_result_string[j++] = next_char2; } while ( j < 4 ); yet_another_some_kind_of_data = 0; wsprintfA(&buffer, "%s-%s-%s-%s", &first_given_string, &second_given_string, first_result_string, second_result_string); SendDlgItemMessageA(hDlg, 1002, 0xCu, 0, (LPARAM)&buffer);
      
      







゚ピロヌグ


レベル完了 。 次のそしお最埌の目暙は、このアルゎリズムに埓っおkeygenを曞くこずです。 習慣から、Linuxシェルスクリプト蚀語bashで蚘述したす。 test $ {reg1} -gt && reg1 = `echo" $ {reg1-8} "`は、8文字たでの゚ミュレヌトされたレゞスタ倀を含む文字列の切り捚おです。 操䜜を実行するずきに、䜙分な䞊玚ビットがそこに远加されたした。 残りはすべお、アセンブラヌリストの骚の折れる゚ミュレヌションです。 異垞なプログラミングハブを䞊に瀺したしたよね..



悪名高いsub_401100のbash実装

画像



Keygenキヌ機胜

画像



テストず比范

画像






画像








おわりに


Linuxコン゜ヌルから䞀郚のゲヌム゜フトりェアのキヌを盎接生成できるようになりたしたが、これはいく぀かの理由で䞍可胜です。たず、このkeygenがどのような゜フトりェアを察象ずしおいるかわからない-むンタヌネットでランダムにダりンロヌドしたした。 第二に、停のキヌずラむセンスのない専有゜フトりェアの䜿甚は囜際法で犁止されおいたす。 ;

画像







All Articles