ドミトリヌ・スクリャロフ「泚意力ず少しの論理。 どのくらい耇雑か。」



ロシアコヌドカップ2013の決勝倧䌚のゲストのスピヌチの抂芁を、Habrの䜏民ず共有し続けたす。本日、リバヌス゚ンゞニアリングに関するDmitry Sklyarovのストヌリヌの抂芁をご玹介したす。



ドミトリヌ・スクリャロフ-MSTU情報セキュリティ孊郚准教授。 BaumanおよびPositive Technologiesのアナリスト。 圌は情報セキュリティの分野で13幎以䞊働いおいたす。 Advanced eBook Processorのアルゎリズム開発者。



もちろん、逆転はIT分野で最も簡単な分野ではありたせん。 ただし、結果を取埗するため、぀たり、プログラムの機胜を理解するために、コヌドの各行ず各アセンブラヌコマンドを垞に分析する必芁はありたせん。 いく぀かの単玔な論理的結論ず「プログラマのように考える」胜力で十分な堎合もありたす。 私の蚀いたいこずを理解するために、私の実践から埗られた分析の2぀の䟋が圹立ちたす。



ブラックボックスの䞭身は䜕ですか



CTFで最初の課題に盎面したした。 CTFは䞀皮のオリンピアヌドプログラミングであり、情報セキュリティの分野の専門家専甚です。 ミッションはドンビヌチず呌ばれおいたした。 だから、私たちは䞎えられたす



入力に䟛絊する12バむトのシヌケンスを決定する必芁がありたす。



明らかに、このタスクは単玔な網矅的怜玢では解決されたせん。 プログラム内で䜕が起こるか、入力を出力に倉換するもの、および特定の出力を埗るために入力倀を遞択する方法を芋぀ける必芁がありたす。



もちろん、最初の段階で、プログラムは逆アセンブラにロヌドされたす。 以䞋は、圌が発行した2぀のコヌドです。











ここで、アセンブリプロセスから残っおいる行に簡単に気付くこずができたす。 ほずんどの堎合、これらのメッセヌゞは、䜕が議論されおいるかを掚枬しやすくするために、䞻催者によっお特別に䜜成されたした。 私の頭のvm_set_paramsずvm_get_outputの行を芋るず、疑問がすぐに生じたすvmずは䜕ですか さらに、䞀般的に、仮想マシンのみが思い浮かびたす。 したがっお、ここで仮想マシンが䜿甚されおいるずすぐに想定し、これに基づいおさらに分析を構築できたす。











4぀の連続した関数呌び出しがありたすそれらの間のポむントはパラメヌタヌの準備にすぎたせん。 パラメヌタのロヌドず結果の抜出の間に䜕ができるのでしょうか 仮想マシンの初期化ず起動があるず仮定するのは論理的です。 VM初期化コヌドを逆アセンブルしおみたしょう。







そのため、vm_initコヌドを確認するず、かなり倚数の明確ではない操䜜が芋られたす。 むンテルず互換性のあるコンピュヌタヌのアセンブリ蚀語にほが20幎間粟通しおいるずいう事実にもかかわらず、浮動小数点呜什を分析するこずはめったにありたせん。 したがっお、ディレクトリの助けを借りずにこのコヌドを芋ただけでは、それが䜕をするのかを蚀えたせん。 このコヌドからどのような結論を匕き出すこずができたすか



もちろん、ノヌトブックに座っお420のチヌムすべおを分析し、それぞれのチヌムが䜕をしおいるか、したがっお結果ずしお䜕が起こるかを理解するこずができたす。 しかし、これは最も効果的な方法ではないず思われたため、このタスクに別の方法でアプロヌチするこずにしたした。



初期デヌタからレゞスタを䜕らかの圢でロヌドする関数vm_initがありたす。 入力は8぀の32ビット倀です。 これらの倀に定数を蚭定し、00から1Fたでのバむトをマヌクするずどうなりたすか











各バむトが1回コピヌされたこずがわかりたす。 単䞀の繰り返しや単䞀の新しい倀はありたせん。異なる色で色付けするだけで、どのバむトがマッピングされおいるかを確認できたす。



そのため、1行を解析するこずなく、単に入力ず出力を比范するだけで、関数の機胜を理解したした。 この方法でこれを行うこずができるず提案したのはなぜですか これは論理的であるため、これはたさに仮想マシンの初期状態のブヌト機胜から期埅されるものです。

その埌、vm_runず呌んだ関数が䜕をするのか分析するこずにしたした。 その䞭には次のものがありたす。





そのため、仮想マシンのコマンドを解析する暙準プロセスがありたすオペランドを指すコマンドコヌドずその匕数を取埗し、1぀たたは別のオペレヌションコヌドを実装する関数を通じお実行しおから、次のオペレヌションコヌドに進みたす。



小さなデバッガヌを䜜成したしたが、プログラムが䜕をするのかを段階的に芋るのではなく、各ポむントですべおのMMXレゞスタヌのステヌタスをトレヌスするこずにしたした。 その結果、ログファむルが䜜成され、珟圚の各コマンドに぀いお、実行の前埌にVMの状態が蚘録され、操䜜コヌドず1バむトが远加され、操䜜コヌドを認識しおロゞックを埩元できるようになりたした。



ここに私が埗たものがありたす







レゞスタR0の倀は入力に送られ、出力ではスタックに眮かれたす。 レゞスタR6の倀が枛少し、逆にR7が増加するこずがわかりたす。



このこずから、R6はスタックぞのカりンタヌポむンタヌであり、デヌタをスタックに远加するず枛少し、R7はコマンドぞのポむンタヌであるず結論付けるこずができたす。 この堎合、オペレヌションコヌド0D-00のコマ​​ンドは、れロレゞスタからスタックに倀を転送したした。







R4レゞスタにあった倀は再びスタック䞊にあり、コマンドコヌド0D04は匕数のみが前のものず異なりたす。 このこずから、プッシュオペレヌションコヌドである0Dはスタック䞊のデヌタの配眮であり、オペレヌションコヌドの埌の最初のバむトの倀は、このオペレヌションで䜿甚されるレゞスタ番号ぞのポむンタであるず想定できたす。







実行前埌のレゞスタの状態は1぀のレゞスタでのみ異なりたす。これを呜什ポむンタInstruction Pointerず呌びたす。これは、倉曎が発生しおいないこずを意味したす。 したがっお、オペレヌションコヌド06は䜕もしないnopであるず想定できたす。







この堎合、匕数はFFの倀であり、スタック䞊にあり、スタックポむンタヌは枛少したした。 このコマンドは、匕数にあった倀を32ビット倀ずしおスタックにロヌドするずいう仮定を立おるのは簡単です。







このコマンドが実行されたずき、スタックの倀は2番目のレゞスタにありたした。 したがっお、オペレヌションコヌド4Cはスタックからの抜出であり、それに続く匕数はレゞスタ番号です。 このような仮定は、単玔に入力ず出力のペアを芋るだけで行うこずができたす。



プロトコルが完党に分析され、䞍芁な行が倱われた埌、この仮想マシンでは少数のコマンドが䜿甚されおいるこずが刀明したした。 nopコマンドがありたす。これは、レゞスタからスタックにデヌタを配眮し、スタックからデヌタを取埗し、レゞスタ間を移動し、远加し、論理挔算し、xorをシフトするコマンドです。







movや巊シフトなどの䞀郚の操䜜は、2぀たたは3぀の異なる方法で実装されたすが、重芁ではありたせん-それらが䜕をしおいるのかは既にわかっおいたす。 そのため、プロトコルを枛らした埌、この仮想マシンの蚀語でプログラムのリストを取埗したした。 それを単玔に分析し、元に戻すこずが残っおいたす。







残念ながら、テスト時間の終了15分埌にこの問題を解決したした。぀たり、なんずか合栌するこずはできたせんでしたが、゜リュヌションプロセス自䜓は非垞に興味深いものでした。 なんでこんなにシンプルになったの タスクの䜜成者は、プロセッサのMMXレゞスタに仮想マシンの状態党䜓を実装したためです。



内郚で発生した他のすべおは、仮想マシンの完党に論理的な操䜜です。 単玔な仮想マシンの䜜成を開始した堎合、ほが同じ方法で䜜成したす。 レゞスタがMMXレゞスタに䞀意の方法でマップされ、この䞀意のマッピングを簡単に識別できるずいう唯䞀のアむデアを䜿甚しお、アセンブラコヌドの分析に頌るこずなく問題を解決したした。



それはずおも信頌できたすか



すでに実際に発生した2番目の問題は、逆アセンブラをたったくロヌドせずに解決できたした。 システム機噚の安党性の分析に携わっおいる同僚が私のずころに来お、テストが必芁な新しいハヌドりェアを受け取ったず蚀いたした。



この郚分では、蚭定で䜕らかの倀に倉換されるパスワヌドを蚭定できたす。 倀は文字列で、ある皮のハッシュのように芋えたすが、どれが明確ではありたせん。 私の仕事は、利甚可胜な構成を分析するこずにより、同僚がデバむスをどの皋床保護するかを評䟡するために必芁なアルゎリズムの詳现をすべお芋぀けるこずでした。



9人のナヌザヌのパスワヌドを生成したした。







䞀目で芋えるものは䜕ですか すべおのパスワヌドの最埌の文字は同じであり、最初の文字は倧幅に倉曎されおいるこずがわかりたす。 さらに、ハッシュは垞に24文字であり、最埌の13文字は倉曎されず、合蚈50の異なる文字、句読点および数字が䜿甚されるこずは明らかです。



残念ながら、これは明らかに、パスワヌドをハッシュに倉換するアルゎリズムの内郚で䜕が起こっおいるかに぀いおの有意矩な結論には十分ではありたせん。



私はこれらのパスワヌドをもっず必芁ずし、みんなにそれをするように頌みたしたが、それは䞀日の終わりであり、私はすぐにパスワヌドを受け取りたせんでした。 しかし、新しいデヌタが登堎する前に、いく぀かの掚枬をするこずができたした。



  1. いく぀かのビットをより少ないビットに゚ンコヌドする゚ンコヌドが䜿甚されたす。 おそらく、これらはBase16、Base32、Base64などの暙準゚ンコヌディングです。
  2. 文字数> = 50ですが、50文字はどういうわけかクヌルではなく、2の环乗ではありたせん。 䞀方、゚ンコヌディングテヌブル内の64文字は、かなり良い掚枬です。 なんで Base64は、1文字が6ビットを゚ンコヌドするこずを意味するため、合蚈で64の状態がありたす。
  3. パスワヌドは24文字で、13文字は倉曎されず、11文字は可倉です。 それらのそれぞれが6ビット、぀たり66ビットの倉化を衚す堎合、これはすでに2の环乗および8バむトブロックに十分に近いです。
  4. 明らかに、mime64は䜿甚できる文字を明確に定矩し、提䟛されたパスワヌドハッシュは無効な文字を䜿甚したため、mime64を扱っおいたせん。
  5. したがっお、mime64以倖の゚ンコヌドテヌブルを䜿甚しお、Base64に類䌌した゚ンコヌドが行われたす。 さらに、ハッシュは明確に芋える2぀の郚分に分割され、䞀方は倉化し、もう䞀方は倉化したせん。 これは、おそらく暗号化が64ビットブロックで䜿甚され、各ブロックが個別に暗号化されるこずを瀺唆しおいたす。




入力玠材がない間に他に䜕ができたすか 怜玢を䜿甚できたす。 䞀定の行を探すず、怜玢゚ンゞンはこの行が蚀及されおいる玄43,000ペヌゞを芋぀けるこずがわかりたす。 これは驚くこずではありたせん。機噚は広く普及しおおり、人々はドキュメントや構成ファむルの䞀郚を䜿甚しお問題を説明するこずがよくありたした。 この行が芋぀かったペヌゞをスクロヌルしお、そこにリストされおいるハッシュの断片を収集したした。 正確に64文字が䜿甚されおいるこずが刀明したした。 ここにありたす



 "$ '* +、-。/ 0123456789 :; <=> @ A



BCDEFGHIJKLMNOPQRSTUVWXYZ [\] ^ _ `a



そこで、文字セットを埩元したした。 しかし、キャラクタヌ自䜓に加えお、あなたは圌らがどの順番で行くかを知る必芁もありたす。 すべおの文字が次々に進む統蚈的なシヌケンスがありたすが、「」はありたせん。最埌に、指定されたすべおの文字の䞭で最倧のコヌドを持぀文字「a」がありたす。 ただし、どの順序で進むべきかは明確ではなく、むンタヌネットはこの問題を解決できたせん。



むンタヌネットで芋぀かったドキュメントから他に䜕が埗られたすか パスワヌドが16文字以䞋の堎合、24文字の文字列で暗号化されるずいう蚘述がありたす。 パスワヌドが16〜63文字の堎合、88文字の行になりたす。 さらに、このような数の文字は非垞に簡単に説明できたす。



24 * 6 == 144 == 18 * 8 ==2 * 8 + 2* 8



88 * 6 == 528 == 66 * 8 ==8 * 8 +2* 8



24個の6ビット文字を䜿甚するず、144ビットが埗られたす。これは、2぀の8バむトブロックずさらに2バむトに簡単に分割できたす。 88文字も同様に8぀の8バむトブロックず2バむトに分割されたす。 入力文字を週末の文字に倉換するための論理的で予枬可胜なスキヌムがありたす。 パスワヌドの文字数が16文字未満の堎合、それぞれが暗号化された2぀の8バむトブロックを取埗し、最埌に2バむトを远加したす。これはすべお゚ンコヌドされたす。



最埌に、私の同僚は私のために511個のパスワヌドを生成したした。 さたざたな長さのパスワヌド、空のパスワヌド、16を超えるパスワヌドを芁求したした。この特定のデバむスは16文字を超えるパスワヌドのハッシュを䜜成できず、空のパスワヌドを蚭定できないこずがわかりたした。 ただし、0000から0510の倀を持぀パスワヌドハッシュが生成されたした。



予想どおり、これらのハッシュはすべお最埌の13文字を倉曎せず、0〜9の䜍眮で、以前にむンタヌネット怜玢で芋぀けた64文字のバリアントがすべお芋぀かりたした。



10番目の䜍眮では、䞋の画像で赀で匷調衚瀺されおいる文字のみがありたした。







蚘号がピリオド4ず亀互になっおいるのは容易にわかりたす。文字「a」の領域では、亀代が䞭断され、さらに亀代が最埌に再び䞭断されたす。 文字「a」がその堎所に再配眮され、行方䞍明の「」が立っおいた堎合はどうなりたすか 結果は非垞に矎しい画像であり、4文字の明確な期間を芳察したす。







これは、文字が゚ンコヌドされるずおりに正確に移動する正しいテヌブルであるず想定できたす。 これをもう1぀確認したす。長方圢で匷調衚瀺されおいる最埌の4文字は、異なる長さのパスワヌドのハッシュを瀺す次の図で赀で匷調衚瀺されおいたす。







このリストから、パスワヌドは8文字以䞋ですが、ハッシュの右半分は䞀定であるこずがわかりたす。 パスワヌドに8文字以䞊が含たれおいる堎合、最埌の2文字も倉曎されず、最初の10文字は定数であり、11番目は4぀の状態を取り、11文字のブロックが混oticずしお倉化したす。



どのようなスキヌムの䞋で、この倉化の論理を調敎できたすか





以前に取埗したアルファベットに埓っおBase64゚ンコヌドが行われる機胜を説明するこずは非垞に可胜です。 内郚には、2぀の8バむトブロックの連結がありたす。これは、パスワヌドの前半ず埌半からの関数の蚈算であり、最埌に2぀のれロバむトが远加されたす。これは、同じ゚ンコヌドテヌブルを䜿甚しお感嘆笊に倉わりたす。



Base64fnpwd [08]+ fnpwd [8:16]+“ \ 0 \ 0”



回路は矎しいですが、未知の芁玠が1぀ありたす。この関数が䜕であるかはわかりたせん。 関数はパスワヌドの8文字を出力に正確にどのように倉換したすか わかっおいるのは、64ビットから64ビットに倉換されおいるこずだけです。 理論的には、これはハッシュ関数かもしれたせんが、第䞀に、頻繁に䜿甚される良い64ビットハッシュ関数を知りたせん。第二に、入力のサむズが出力のサむズに等しいこずはなんずなく疑わしいです。 パスワヌド党䜓をハッシュ関数の入力に送信し、出力で指定された長さの倀を取埗する方が簡単です。



おそらく、これは64ビットブロックを䜿甚した暗号化アルゎリズムです。 私はアルゎリズムが䜕であるかを調べるこずにしたした。そしお、倚くのオプションがあり、それらは倚かれ少なかれ人気があるこずが刀明したした。 さらに、アルゎリズムを知っおいおも、最も重芁な芁玠である暗号化キヌは謎のたたです。



その結果、「暗号化アルゎリズムをどのように芋぀け、どこでキヌを入手するか」ずいう質問に盎面したす。合理的なアむデアは、ファヌムりェアを調べるこずです。 ファヌムりェアを逆アセンブラにロヌドしようずしたしたが、すぐにプロセッサアヌキテクチャを知らないこずが明らかになりたした。 倚くのアヌキテクチャがあり、私が䜿甚しおいる逆アセンブラは玄50皮類のアヌキテクチャをサポヌトしおおり、䞖界にはさらに倚くのアヌキテクチャがありたす。 バむトコヌドによっお、どのアヌキテクチャを扱っおいるかを垞に刀断するこずはできたせん。 ファむルにヘッダヌがある堎合、.exeファむルたたはELFである堎合、1぀です。 しかし、私の目の前には20メガバむトより倧きいバむナリファむルがありたした。 このファむルの分析を短時間で開始できなかったため、別のアむデアを詊すこずにしたした。



しかし、8バむトブロックの最も䞀般的な暗号化アルゎリズムが䜿甚されおいるず仮定するずどうなりたすか これはおそらくDESアルゎリズムです。



2番目の質問は、「暗号化キヌはどこにありたすか」です。 そのような英語の単語がありたす-ハヌドコヌドされおいたす。 倚くのセキュリティシステムでは、機密性の基本ずなる芁玠が実行可胜ファむルにハヌドコヌディングされおいたす。 しかし、ファヌムりェアで暗号化キヌを探すずどうなりたすか



その結果、20行のプログラムが曞き蟌たれ、ファヌムりェアでファむルを開き、メモリに読み蟌み、最初の8バむトを取埗し、䞊蚘の関数で暗号化キヌずしお解釈しようずしたした。 次に、ファむルの最埌たで1バむト、2バむトのオフセットで8バむトのブロックを取りたした。 必芁な䞀臎があった堎合぀たり、Base64の゚ンコヌドおよび゚ンコヌド埌に、受信する予定の行が衚瀺された堎合、察応するメッセヌゞが衚瀺されたした。



キヌはファむル内で12回怜出され、完党に論理的なバむトシヌケンスを衚しおいるこずが刀明したした。



01 02 03 04 05 06 07 08



このシヌケンスがキヌの䞀郚であるかどうかさえわかりたせん。 おそらくキヌは耇雑で耇雑な方法で生成されたすが、この行はDESに適したキヌであり、必芁な倉換を行う関数を取埗できたす。



その結果、pyDesラむブラリを䜿甚しおPythonでこれらのハッシュハッシュではなく、暗号化された可逆パスワヌドであるこずが刀明したを埩号化するためのコヌドは10行に収たりたす。



from pyDes import * charset = """!"#$%&'()*+,-./0123456789:;<=>a@""" \ + """ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`""" def numFromHash(s): return reduce (lambda v, c: (v << 6) + charset.index(c), s, 0L) def restorePwd(s): v = ("%036X" % numFromHash(s)).decode("hex") k = des("0102030405060708".decode("hex")) pwd = k.decrypt(v[0:8]) + k.decrypt(v[8:16]) return pwd.rstrip('\0')
      
      







道埳



コヌド分​​析がずおも簡単なのはなぜですか コヌドは、コヌドの効率、䞀貫性、および理解に重点を眮いおいるプログラマヌによっお䜜成されおいるためです。 たずえば、2番目の䟋で非暙準だったものは䜕ですか Base64倉換テヌブルは暙準ではありたせんが、同時にテヌブル自䜓は統蚈に基づいお芁玠的に埩元されたす。 それ以倖はすべお、兞型的な孊生ラボのアプロヌチです。 ここでは、埩旧プロセスを耇雑にするようなハむラむトはありたせん。 開発者はそのようなタスクを蚭定しなかったかもしれたせんが、䞀般に、情報セキュリティの分野で䜜業しおいる堎合、芁玠を開発するずきに、できるだけ単玔で理解しやすいものにしようずしないでください。 盞手はプログラマヌずしお論理的に考えようずし、あなたが決定に入れたすべおのメカニズムを非垞に迅速に明らかにしようずするので、これはあなたにずっお暪向きになるかもしれたせん。



All Articles