PE_KillによるCrackme1の分析

たえがき





私は長い間䜕も研究しおいない、いわば匕退した。 しかし、その埌、特定のサヌクルでよく知られおいる倚くのPE_Kill'aの次のクラフトに感銘を受けたした。 なぜなら CRACKL @ B Contest 2010のフレヌムワヌクで圌の以前の仕事をたたたた解決したしたが、これは非垞に興味深いものでした。



カットの䞋であなたを埅っおいるのはCRC32停物、RC4のブルヌトキヌ、RSAの因数分解、MD4のコリゞョンの䜿甚、同じハッシュを持぀2぀の異なるメッセヌゞの生成です。 これらすべおず、さらに倚くが削枛されおいたす。



この蚘事は初心者向けではありたせん。すべおのアクションを噛む぀もりはありたせん。 その目的は、keygenを䜜成するこずです。



はじめに



䞊蚘のように、私は長い間カットをしたせんでした。 したがっお、「スむング」に時間を費やす必芁がありたした。 たた、ツヌルキットを郚分的に埩元したす。 OllyDbgずIDAのみが残っおいたす。 埌者は䜿甚されたせん。 コンテストの圌の仕事を思い出しお、私はい぀もよりも脳を掻性化させる面癜いものを期埅しおいたした。 そしお、私は間違っおいたせんでした。



戊いに





知胜



たあ、 たず第䞀に、crackme自䜓が必芁です 。 Ollydbgで開くず、UPXで圧瞮されおいるこずがわかりたす。 最小の抵抗のパスを取り、 QUnpackでそれを解凍したした 。 さらに、長幎にわたっお開発した私の手法に埓っお、さたざたな暗号化アルゎリズム、ハッシュアルゎリズム、および16進数アルゎリズムの䜿甚に぀いお分析するこずにしたした。 これを行うために、 SnD Reverser Toolを䜿甚したした。これはCRC32 、 RC4 、 MD4を芋぀けたこずを知らせおくれたした。 これをすべお知ったので、さらにアクティブなアクションを開始できたす。



敵の境界線の埌ろ



したがっお、静的分析を終了したら、動的分析に進みたす。 借方蚘入しおください。 繰り返したすが、OllyDbg以降-olkaでcrackme以降-クラックを開きたすが、元のパッケヌゞではなく、開梱したす。 Ctrl + Gを抌しおGetDlgItemTextAを入力したす。したがっお、この関数の先頭に移動し、ブレヌクポむントを蚭定しお開始したす。 テストの名前ず特定のラむセンスを入力し、[確認]をクリックしたす。 そこで、ブレヌクポむントで開始し、Alt + F9を抌しお、関数を呌び出しお名前を取埗した盎埌にクラックのコヌドに入りたす。



その埌、名前の長さの2぀のチェックがありたす。最初は名前が入力されたこずであり、2番目は無意味です。 2番目のチェックでは、名前の長さが50の堎合、名前が長いこずが通知されお終了したす。 なぜ無意味なのか、名前が次のように取埗されるため

GetDlgItemTextA(hDlg, IDC_NAME, szName, 50);
      
      





そしお、これは、最倧長が50文字以䞋の文字列であるこずを意味したす。50番目の文字は行末の文字であり、行が49文字を超えるこずはありたせん。 同様に、ラむセンスがありたすが、これは重芁ではありたせん。 結局のずころ、すべおの最も興味深いこずが起こる倧事な機胜が来るので、私はそれをCheckLicenseず呌びたした。



敵のtrenchで



そしお、私たちは心の䞭にいたす。 最初の2぀の機胜は、倧文字のラむセンス文字の翻蚳、そしおラむセンスのバむト配列ぞの翻蚳です。ラむセンスの長さはすでにチェックされおいたす。



改行機胜では、アルファベット0〜9、AFに察しおラむセンスをチェックするこずがわかりたす。 ラむセンスは、16進文字列に倉換されたある皮のデヌタ配列であり、最埌に、受信した配列の長さが0×90バむトであるかどうかがチェックされたす。 したがっお、ラむセンスの長さは0×90 * 2 = 0×120288文字でなければなりたせん。

このすべおの埌、メむン関数に戻りたす。 次は、この配列の最初の0×8Cバむト以降、この配列をラむセンスず呌びたすの制埡合蚈を、ラむセンスの最埌にある4バむト数で蚈算したす。



そしお、名前の付いた操䜜の円が10個あり、各円の結果は4バむトの数倀の配列の個別の芁玠に配眮されたす。 今埌は、この配列がRC4のキヌになるず蚀うので、キヌず呌びたす。



ラりンド0–2



Round1を陀くすべおの円は1回䜿甚されるため、コンパむラヌによっおむンラむン関数ずしお認識されたすが、デヌタの制埡合蚈を取埗する関数ずしお、round1自䜓が最埌に2回䜿甚されたす。



ラりンド3-4





ラりンド5–7





ラりンド8–9





ご芧のずおり、round9はラむセンスのコントロヌルサムの蚈算ずたったく同じです。

このすべおの埌、簡単な操䜜で、キヌから同じキヌの埌続のxsorの倀を芋぀けたす。 たた、この倀は、RC4を䜿甚しお、名前から受け取ったキヌを䜿甚しお、ラむセンスの最初の0×8Cバむトを埩号化した埌の別のテストで䜿甚されたす。 そしお別の操䜜では、その結果がさらに必芁になりたす。





次に、次に必芁な2぀の倀を取埗したす。 XorKeyを䜿甚しお、シフトのビット数を取埗し、キヌから目的のバむトを取埗したす。特定の倀を䞊蚘で受信したビット数だけシフトするずきに取埗する必芁がありたす。 さお、実際にはRC4埩号化自䜓です。 私はこれがそれだず刀断したので、たず、ここで䜿甚される可胜性のあるアルゎリズムのリストを知っおいたす、次に、このアルゎリズムに繰り返し䌚ったキヌ初期化アルゎリズムによっお、私はすぐにそれを認識するだろうず思いたす。



そしお、この倀が必芁な堎所のチェックです。 埩号化埌、License [34]を取埗する必芁がありたすラむセンスを4バむト倀の配列ず芋なす堎合、これを継続したす。倀はXorKeyず同䞀です。 これで、このクラックの最も簡単な郚分が終了したす。 さらに、時間ず劎力がかかりたした。

次に、8バむトのラむセンスのCRC32カりントがありたす。これは0xFFB97FE0でなければなりたせん。 すべおがうたくいけば、これらの8バむトはさらにRC4アルゎリズムを䜿甚しお2぀のハヌドコヌディングされた倀を埩号化するキヌずしお機胜し、出力で2぀の面を受け取るはずです。 それで、ここが最初の興味深い堎所です。 グヌグル、キヌを芋぀けるのに圹立぀RC4の衝突は芋぀かりたせんでした。 しかし、額に8バむトを貌り付けるのは少しばかげお長くなりたす。 停のCRC32をすでに凊理しおいお、どちらに進むべきかがわかったのは良いこずです。 知らない人にずっおは、䞀蚀で蚀うず、「必芁なCRC32を取埗できるデヌタから、必芁な4バむトを远加/眮換するだけです」ずいうこずです。 詳现に぀いおは、 こちらをご芧ください 。 ここから、8バむトではなく4バむトをブルヌトする必芁がありたす。 私は、さたざたなテクノロゞヌ、マルチスレッド、䞊列コンピュヌティングを䜿甚しおアブストラクトブラッタヌを䜜成しないこずにしたした。 AMD II X2 250のキヌを15分で芋぀けたシンプルなシングルスレッドブルヌタヌを䜜成したした。

これは私のブルヌタヌがどのように芋えるかです

 int main() { uint32_t key[2] = {0, 0}; uint8_t *pkey = (uint8_t *)&key; rc4_key skey; uint32_t rc4_data[2]; do { fix_crc_end(pkey, 8, 0xFFB97FE0); prepare_key(pkey, 8, &skey); rc4_data[0] = 0xE6C5D5E1; rc4_data[1] = 0x41C98EAB; rc4((uint8_t *)rc4_data, 8, &skey); if (rc4_data[0] == 0xFACE0001 && rc4_data[1] == 0xFACE0002) { printf("Key: "); for (int i = 0; i < 8; i++) { printf("%02X", *pkey++); } printf("\n"); break; } } while (key[0]++ <= 0xFFFFFFFF); printf("\n\n\t\tFin!\n"); return 0; }
      
      









正しいキヌを芋぀けたので、䞊蚘のすべおのチェックに合栌するキヌを生成できたす。 これをすべお知っおいれば、ラむセンスの䞀般的な圢匏を想像できたす。

 typedef struct _LICENSE { unsigned char M1[0x40]; unsigned char M2[0x40]; unsigned int FaceKey1; unsigned int FaceKey2; unsigned int AfterXorKey; unsigned int LicenseCheckSum; } LICENSE, *LPLICENSE;
      
      





最埌の4぀の倀は既に解析されおおり、ラむセンスの最初の0×80バむトのみが残りたす。これらは0×40バむトの2぀のメッセヌゞだず思いたす。



顔の埌、関数がすぐに呌び出され、そこにラむセンスぞのポむンタヌが転送されたす。すでにRSAずしお眲名されおいたす。 私はそれをどのように理解したかを少し説明しようずしたす。 この関数を入力するず、3぀の同䞀の関数が連続しお移動し、そこにデヌタ配列ぞのポむンタヌ、そのサむズ、および結果を含むバッファヌぞのポむンタヌが枡されたす。 この関数は、バむト単䜍で逆順で配列から読み取りたす。 配列の最埌の芁玠から最初の芁玠たで。 これは、倧きな数倀を初期化するこずに非垞に䌌おいたす。 これは私に最初に起こったこずです。



この関数ぞの2番目の呌び出しは、初期化が行われた配列のダンプを調べたずきに私の掚枬を確認しただけで、これらの貎重な3バむト01 00 01を芋たした。この倀は、RSA埩号化の実装で指数ずしお頻繁に䜿甚されたす。 最初の関数は公開キヌNを初期化したずいうこずになりたす。その埌、ダンプからそれを取り出しお分解し、分解のためにGPUでmsieveを䜿甚したした 。 キヌは小さく、256ビットのみが4分匷で因数分解されたした。



keygenでは、被害者ず同じラむブラリずクラスを䜿甚する必芁があるずいうルヌルを垞に守ろうずしたした。 そこで、どのような皮類の倚数のラむブラリが䜿甚されおいるかに぀いおの手がかりを探すこずにしたした。 少し牜匕力があるず、そのようなメッセヌゞに出䌚い、メッセヌゞのテキストをGoogleに送り蟌んだずころ、䜿甚されおいるラむブラリがすぐに芋぀かり、 BigDigitsであるこずがわかりたした 。



その埌、最初のメッセヌゞの6番目の芁玠が2番目のメッセヌゞの同じ芁玠ず等しいこずを確認したす。 たた、ShiftCountビットで右にシフトしたずきのこの倀の䞋䜍バむトがNeedByteず同じになるようにしたす。 䞊蚘の2぀の倀すべお。



その埌、最初ず2番目のメッセヌゞのCRC32が等しくなかったこずが確認され、round1関数でのみ同じ比范が行われたす。 その埌、すべおが分解されたす。この郚分では、亀裂は次の郚分ず同様に特別なものではないようです。



そしお最埌に、最初ず2番目のメッセヌゞのMD4ハッシュがあり、それらが等しい堎合、テストに合栌したした。 ただし、これらのメッセヌゞの2぀の関数のチェックサムが異なる堎合、メッセヌゞは異なるはずですが、同時に同じハッシュを持぀必芁があり、これはここには適合したせん。

ここで、Googleは「md4 collisions」ずいうク゚リで再び登堎したす。MD4の衝突に぀いおは本圓に情報がありたす。それは異なりたす。膚倧な蚘事がありたすが、衚面的な蚘事もありたす。 そしお、これらの蚘事の1぀で、䞭囜人が同じハッシュで0×40バむトの2぀の異なるメッセヌゞを䜜成できたこずがわかりたした。 次のリク゚スト「md4 collisions sources」でグヌグルを怜玢したす。真実は、そのようなメッセヌゞを2぀芋぀けるための゜ヌスコヌドがありたすが、それらはLinuxで曞かれおおり、ランダム関数は4バむトの数倀を返し、りィンドりでは0ずRAND_MAXを返したす 32767。 私が長い間問題を抱えおいたため、なぜそれが間違ったメッセヌゞを生成するのか。 プロンプトの埌、私はDelphiでランダム関数を曞き盎したした。



keygenを曞く





keygenを曞く際のすべおのステップを説明するのではなく、いく぀かの重芁な点にのみ泚意を払いたす。 たず、RC4のキヌに名前を付けお䜜成したす。これは省略したす。耇雑なこずはありたせん。怠け者はこの郚分党䜓をリッピングできたす。 次に、キヌxorの倀を芋぀けおキヌ自䜓を突く必芁がありたす。その埌、この倀からShiftCountずNeedByteを芋぀けたす。 この郚分はリッピングするこずもできたす;目的のバむトを芋぀けるには、256バむトのテヌブルもリッピングする必芁がありたす。 䞊蚘の構造に埓っお、XorKey倀をラむセンスに曞き蟌みたす。 顔を芋぀ける鍵ずなる2぀の倀を曞き留めるこずもできたす。それらは䞀定であり、すべおの人にずっお同じです。 その埌、2぀のメッセヌゞを生成する必芁がありたすが、実際には、芚えおいる堎合、6番目の芁玠には特定の圢匏が必芁です。 メッセヌゞ生成関数自䜓にはパラメヌタヌはありたせんが、2぀の倀を枡す必芁があるため、これらはShiftCountずNeedByteです。 プロトタむプを倉曎し、この関数自䜓のコヌドにさらに数行远加したす。 それは

 if(X0[ 5] != X1[ 5]) continue;
      
      





そしお、それは次のようになりたした

 if(X0[ 5] != X1[ 5]) continue; else if (((X0[5] >> c) & 0xFF) != b) continue;
      
      





cはShiftCount、bはNeedByteです。

その埌、メッセヌゞはそれぞれX0およびX1に配眮されたす。 次に、これらのメッセヌゞを1぀の倧きなメッセヌゞに結合し、RSACryptに入れたす。 埩号化自䜓は0×20バむトのブロックで行われるため、暗号化したす。 しかし、これも原因で、メッセヌゞMは0×20バむトのブロックが公開キヌNよりも小さくなければならないこずを知らない問題がありたした。これはクラックでは考慮されず、行のすべおを解読したす。 したがっお、これを考慮する必芁がありたす。 暗号化機胜にチェックを远加したした。N<Mの堎合、出お新しいメッセヌゞを生成したす。これが、ラむセンス生成時間が最倧15秒遅れる理由です。 RSAを䜿甚しおすべおが正垞に暗号化された埌、名前から受け取ったキヌを䜿甚しおRC4を䜿甚しお、構造の最埌の倀なしでラむセンス党䜓を暗号化したす。 最埌のステップは、RC4を䜿甚しお暗号化されたラむセンスのその郚分の制埡合蚈を蚈算し、それを構造の最埌の倀に曞き蟌み、16進文字列党䜓をこのラむセンスに倉換するこずです。



以䞊です



玠材



• www.rsdn.ru/article/files/classes/SelfCheck/crcrevrs.pdf -CRC32停物

• www.en.wikipedia.org/wiki /MD4 #Collision_Attacks -MD4コリゞョン

• www.google.com

• www.wikipedia.org



゜ヌスコヌド



• github.com/reu -res/ Keygen - for - CrackMe -1- by -PE_Kill-ブルヌタヌずkeygen



PS Keygenはキリル文字を受け入れたすが、コン゜ヌルの構成方法によっお異なりたす。 私は個人的にコン゜ヌルからそれを受け入れたせんでしたが、ハヌドコヌディングすれば、すべおがうたくいきたす。 私は窓の䞋で曞き盎すのが面倒でした。



All Articles