Trojan-Downloader.Win32.Cabby.cemx-パート1-開梱

こんにちは、Habr!



私はすぐに言います:私はバイラルアナリストではなく、この活動に専門的に関与していません。 私は、3文字の企業グループのいずれかの企業でネットワークエンジニアとして働いています。 ですから、理解をもって厳しく判断し、扱わないようお願いします。



この記事の目的は、マルウェアの動作の高レベルのロジックに関するレポートを作成するためのマルウェアの明示的な分析ではなく、知識と経験を高めるために頭でリバースエンジニアリングに没頭することです。 したがって、アンパックアルゴリズム全体を詳しく説明します。



すぐに、逆アセンブルされたコードの多くの写真とリストがあることを警告します。



建設的な批判の準備ができており、私の考えを最適化するためのアドバイスを喜んでいます。



最近、高く評価されたCTB-Lockerが当社に侵入し、情報セキュリティサービスに興味を持ちました。なぜウイルス対策やWebトラフィックフィルタリングが機能しなかったのですか? このマルウェアが正確に行うことは、 securelistで詳しく説明されています 。 これにより、すべてが明確になり、すでに十分に説明されていることを再分析する意味がありません。



インシデントの原因を理解するために、このマルウェアの配布ベクトルを検討します。



ユーザーの観点からこれがどのように見えるか:

  1. .cabアーカイブが添付された手紙が届きました。
  2. ユーザーはアーカイブを開き、そこから.scrを実行します。
  3. .rtfファイルは、あいまいで興味深いデータで開きます。
  4. ユーザーはこのファイルを落ち着いて閉じ、作業を続けます。
  5. しばらくすると、デスクトップにCTB-Lockerウィンドウがポップアップし、ユーザーにとって悲しい情報が表示されます。


解読する



そのため、.cabアーカイブから怒りと噛み付きの.scrを取得します。 これをImmunity Debuggerで開き、F9で数回押すと、途中でアンチデバッグのトリックに出会うことなく、エントリポイント0x4021C6に到達します。これはすでに良好です。







リストを少し調べてインポートを調べたところ、わかりやすく「有用」なものは見つかりませんでした。 ネットワークアクティビティに関連するものはありません-何かがより深く隠されていることを示唆しています。 パッカー?



PEiDが私たちに伝えること:







既知のパッカーが見つかりませんでした。 さらに、エントロピー分析により、ファイルがパックされていない可能性が高いことがわかります。 しかし、さらに見てみましょう...



コードが少しあると、最初のメモリ操作に出くわします。 HeapCreateに渡される変数はあまり巧妙に隠されていません。







割り当てられたメモリのサイズは0x6D0です。 flOptions = 0x40000。これは、メモリ領域が実行可能であることを意味します。 OK、メモリBPを記録用に設定することで割り当てられたメモリ領域を観察し、データを復号化して.dataセクションから割り当てられたメモリにコピーするサイクルを見つけます(ちなみに、HeapCreateのほぼ直後にあります):

00401F4A。 85DBテストEBX、EBX

00401F4C。 0F84 670,000,000 JE g_r_pice.004020B9

00401F52。 01C0 EAXを追加、EAX

00401F54。 811D C8404000> SBB DWORD PTR DS:[4040C8]、0CE

00401F5E。 82C4 40 ADD AH、40

00401F61。 83C8 4AまたはEAX、4A

00401F64。 31F6 XOR ESI、ESI

00401F66。 0B37 OR ESI、DWORD PTR DS:[EDI] <-ウイルス本体から復号化するためのデータをダウンロードする

00401F68。 18E4 SBB AH、AH

00401F6A。 8315 28414000> ADC DWORD PTR DS:[404128]、33

00401F71。 8115 E6404000> ADC DWORD PTR DS:[4040E6]、0A3

00401F7B。 8315 95404000> ADC DWORD PTR DS:[404095]、25

00401F82。 F8 CLC

00401F83。 83D7 04 ADC EDI、4

00401F86。 34 F0 XOR AL、0F0

00401F88。 1305 E9404000 ADC EAX、DWORD PTR DS:[4040E9]

00401F8E。 1905 48414000 SBB DWORD PTR DS:[404148]、EAX

00401F94。 8335 A2414000> XOR DWORD PTR DS:[4041A2]、2B

00401F9B。 3105 41414000 XOR DWORD PTR DS:[404141]、EAX

00401FA1。 F8 CLC

00401FA2。 83DE 07 SBB ESI、7

00401FA5。 8325 E0404000>およびDWORD PTR DS:[4040E0]、6A

00401FAC。 82CC E9 OR AH、FFFFFFE9

00401FAF。 2105 68404000およびDWORD PTR DS:[404068]、EAX

00401FB5。 83C8 EEまたはEAX、FFFFFFEE

00401FB8。 83F0 FF XOR EAX、FFFFFFFF

00401FBB。 F7DE NEG ESI

00401FBD。 810D 07414000>またはDWORD PTR DS:[404107]、0C2

00401FC7。 C705 0D404000> MOV DWORD PTR DS:[40400D]、0B8

00401FD1。 3105 C0404000 XOR DWORD PTR DS:[4040C0]、EAX

00401FD7。 83C0 05 EAXを追加、5

00401FDA。 29D6 SUB ESI、EDX

00401FDC。 11C0 ADC EAX、EAX

00401FDE。 1305 2D414000 ADC EAX、DWORD PTR DS:[40412D]

00401FE4。 83E8 2BサブEAX、2B

00401FE7。 1305 29404000 ADC EAX、DWORD PTR DS:[404029]

00401FED。 83D8 3E SBB EAX、3E

00401FF0。 822D BA404000> SUB BYTE PTR DS:[4040BA]、-79

00401FF7。 F8 CLC

00401FF8。 83D6 01 ADC ESI、1

00401FFB。 83F0 B7 XOR EAX、FFFFFFB7

00401FFE。 3105 4E414000 XOR DWORD PTR DS:[40414E]、EAX

00402004。810DED404000>またはDWORD PTR DS:[4040ED]、0A5

0040200E。 31C0 XOR EAX、EAX

00402010. 31C0 XOR EAX、EAX

00402012。29D2SUB EDX、EDX

00402014。29F2SUB EDX、ESI

00402016. F7DA NEG EDX

00402018. 31C0 XOR EAX、EAX

0040201A。 8335 DE414000> XOR DWORD PTR DS:[4041DE]、64

00402021。310566404000 XOR DWORD PTR DS:[404066]、EAX

00402027。31C0XOR EAX、EAX

00402029. 83D0 CC ADC EAX、-34

0040202C。 2B05 33414000 SUB EAX、DWORD PTR DS:[404133]

00402032. C1C2 03 ROL EDX、3

00402035. 1305 4D404000 ADC EAX、DWORD PTR DS:[40404D]

0040203B。 11C0 ADC EAX、EAX

0040203D。 83C8 B4またはEAX、FFFFFFB4

00402040. 19C0 SBB EAX、EAX

00402042. C1C2 05 ROL EDX、5

00402045. 0105 4B404000 DWORD PTR DSを追加:[40404B]、EAX

0040204B。 2B05 3C404000 SUB EAX、DWORD PTR DS:[40403C]

00402051. 1305 B0404000 ADC EAX、DWORD PTR DS:[4040B0]

00402057. C705 C4404000> MOV DWORD PTR DS:[4040C4]、0B9

00402061. 56 PUSH ESI

00402062. 8F01 POP DWORD PTR DS:[ECX] <-専用メモリロケーションへの保存

00402064. 83E0 0EおよびEAX、0E

00402067。1905F8414000 SBB DWORD PTR DS:[4041F8]、EAX

0040206D。 2905 45404000 SUB DWORD PTR DS:[404045]、EAX

00402073. A3 8F404000 MOV DWORD PTR DS:[40408F]、EAX

00402078. A3 AF404000 MOV DWORD PTR DS:[4040AF]、EAX

0040207D。 83C1 04 ECXを追加、4

00402080. 2905 18414000 SUB DWORD PTR DS:[404118]、EAX

00402086。19C0SBB EAX、EAX

00402088。83D0D9 ADC EAX、-27

0040208B。 0905 3C404000またはDWORD PTR DS:[40403C]、EAX

00402091。19C0SBB EAX、EAX

00402093. 8D5B FC LEA EBX、DWORD PTR DS:[EBX-4]

00402096。83D812 SBB EAX、12

00402099。210515414000およびDWORD PTR DS:[404115]、EAX

0040209F。 C705 AE414000> MOV DWORD PTR DS:[4041AE]、33

004020A9。 C705 18404000> MOV DWORD PTR DS:[404018]、0DA

004020B3。 68 4A1F4000 PUSH g_r_pice.00401F4A

004020B8。 C3 RETN





デバッガーにターゲットメモリ領域を逆アセンブルし、予想される結果を取得するように指示します。これは非常に実行可能なコードです







復号化されたコードへの移行は間もなく開始されました。







最初に、プロシージャにパラメータを渡す興味深い方法に出会います。 最初のそのような関数の例を考えてみましょう。 ご覧のとおり、LoadLibrary関数が呼び出されます。この関数には、ロードするライブラリの名前に文字列変数を渡す必要があります。

02120000 8B7424 04 MOV ESI、DWORD PTR SS:[ESP + 4]

02120004 55 PUSH EBP

02120005 E8 DF010000 CALL 021201E9

0212000A 58 POP EAX

0212000B 50プッシュEAX

0212000C FFD6 CALL ESI; kernel32.LoadLibraryA



指定した関数の前に、プロシージャ「CALL 021001E9」の呼び出しが発生します。 ここにそれがあります:

021201E9 58 POP EAX; 0210000A

021201EA FFD0 CALL EAX



この瞬間に何が起こっていますか? CALL 021001E9が呼び出されると、この呼び出しからプロシージャから戻るための次の命令のアドレスがスタックにプッシュされます。 呼び出しの後、スタックから戻りアドレスが取得され、EAXに配置されます。 次に、「CALL EAX」の呼び出しが発生し、次の命令のアドレスがプッシュされてスタックに戻ります。 ダンプを見ると、ライブラリの名前がわかります。







さらに、複数回リストする場合、そのような方法があります。



次に興味深い点は、接続されたライブラリから必要な関数を見つける手順です。 プロシージャに渡されるパラメータの中には、上記の方法で取得した不可解なバイトセットへのポインタがあります。次に、その理由と内容を把握します。 したがって、手順自体:

0212034B 60 PUSHAD

0212034C EB 07 JMPショート02120355

0212034E AD LODS DWORD PTR DS:[ESI] <-エクスポートテーブルを見つけるために、接続されたDLLのヘッダーを通過するためのアルゴリズム

0212034F ^ E2 FDループショート0212034E

02120351 8D3403 LEA ESI、DWORD PTR DS:[EBX + EAX]

02120354 C3 RETN

02120355 8BE8 MOV EBP、EAX

02120357 8BF3 MOV ESI、EBX

02120359 B9 10,000,000 MOV ECX、10

0212035E E8 EBFFFFFF CALL 0212034E

02120363 B9 1F000000 MOV ECX、1F

02120368 E8 E1FFFFFF CALL 0212034E

0212036D 56 PUSH ESI

0212036E B9 07000000 MOV ECX、7

02120373 E8 D6FFFFFFコール0212034E

02120378 8BD0 MOV EDX、EAX

0212037A 8B3424 MOV ESI、DWORD PTR SS:[ESP]

0212037D B9 09000000 MOV ECX、9

02120382 E8 C7FFFFFF CALL 0212034E

02120387 8BFE MOV EDI、ESI

02120389 8BCA MOV ECX、EDX

0212038B E8 BEFFFFFF CALL 0212034E

02120390 33C0 XOR EAX、EAX

02120392 50プッシュEAX

02120393 C1C8 07 ROR EAX、7 < -DLL エクスポートテーブルから関数に代わってハッシュ合計を計算

02120396 C10424 0D ROL DWORD PTR SS:[ESP]、0D

0212039A 010424 DWORD PTR SSを追加:[ESP]、EAX

0212039D AC LODS BYTE PTR DS:[ESI]

0212039E 84C0テストAL、AL

021203A0 ^ 75 F1 JNZショート02120393

021203A2 58 POP EAX

021203A3 8BF7 MOV ESI、EDI

021203A5 3BC5 CMP EAX、EBP <-受信したハッシュ合計とメモリ内の値との比較

021203A7 74 03 JE SHORT 021203AC

021203A9 4A DEC EDX

021203AA ^ 75 DD JNZショート02120389

021203AC 8B3424 MOV ESI、DWORD PTR SS:[ESP] <-ハッシュが一致する場合、目的の関数のアドレスが検索されて返されます

021203AF B9 0A000000 MOV ECX、0A

021203B4 E8 95FFFFFF CALL 0212034E

021203B9 0FB70C56 MOVZX ECX、WORD PTR DS:[ESI + EDX * 2]

021203BD 5E POP ESI

021203BE 51 PUSH ECX

021203BF B9 08000000 MOV ECX、8

021203C4 E8 85FFFFFF CALL 0212034E

021203C9 59 POP ECX

021203CA E8 7FFFFFFF CALL 0212034E

021203CF 897424 1C MOV DWORD PTR SS:[ESP + 1C]、ESI

021203D3 61 POPAD

021203D4 C3 RETN



これで、このプロシージャが特定のハッシュサムへのポインタと、関数を検索するDLLのアドレスを受け取ることが明らかになりました。 次に、ロジックは順番に:

  1. PEヘッダーは、ターゲットDLLエクスポートテーブルのアドレスを計算します。
  2. 各関数の名前はエクスポートテーブルから取得され、特定のハッシュの合計が計算されます。
  3. 計算されたハッシュ和がパラメーターで取得されたものと一致するかどうかを確認します。
  4. ハッシュ値が一致する場合、見つかった関数のアドレスが返されて返されます。


必要な機能を検索すると、元のハッシュの合計が実際のアドレスに書き換えられます。







次に、「GetProcAddress」の助けを借りて、HeapAlloc、HeapFree、GetTickCountの3つの関数のアドレスがあります。

02120039 5F POP EDI

0212003A 83C7 0D ADD EDI、0D

0212003D 57 PUSH EDI

0212003E 53 PUSH EBX

0212003F FF55 08 CALL DWORD PTR SS:[EBP + 8]

02120042 8906 MOV DWORD PTR DS:[ESI]、EAX

02120044 83C7 0A EDIを追加、0A

02120047 57 PUSH EDI

02120048 53 PUSH EBX

02120049 FF55 08 CALL DWORD PTR SS:[EBP + 8]

0212004C 8946 04 MOV DWORD PTR DS:[ESI + 4]、EAX

0212004F 83C7 09 EDIを追加、9

02120052 57 PUSH EDI

02120053 53 PUSH EBX

02120054 FF55 08 CALL DWORD PTR SS:[EBP + 8]; kernel32.GetProcAddress

02120057 8946 08 MOV DWORD PTR DS:[ESI + 8]、EAX



見つかったアドレスは、APIが使用する既に生成されたアドレスの配列の最後に追加されます。







使用される関数の配列が形成され、その後、その使用は、前回と同じサイズの新しいメモリ領域の割り当てで直ちに開始されます-0x6D0:







flProtect = 0x40。これも割り当てられたメモリでコードが実行される可能性を示しています。

「VirtualAlloc」の後、スタックのリターンアドレスを「RETN」のオフセット0x81で保存しながら、現在のメモリを新しいメモリにコピーするサイクルがすぐに発生します。







RETNは、コード実行を次のようなメモリの新しいセクションに転送します。

00220 081 E8 CB050000 CALL 00220651

00220 086 5D POP EBP

00220087 5E POP ESI

00220088 873424 XCHG DWORD PTR SS:[ESP]、ESI

0022 008B 56 PUSH ESI

0022008C E8 2E050000 CALL 002205BF

00220091 E8 6C050000 CALL 00220602



「CALL 00220651」はすでに知られている手順であり、restoredな方法で、復元された関数のアドレスとともに配列のアドレスを返します。

「CALL 002205BF」-署名「MZ」および「PE」によってメモリにロードされたプロセスの有効性をチェックします。

002205BF 66:33F6 XOR SI、SI

002205C2 66:BA 4D5A MOV DX、5A4D

002205C6 66:AD LODS WORD PTR DS:[ESI]

002205C8 66:33D0 XOR DX、AX

002205CB 74 08 JE SHORT 002205D5

002205CD 81EE 02100000 SUB ESI、1002

002205D3 ^ EB ED JMPショート002205C2

002205D5 8D5E FE LEA EBX、DWORD PTR DS:[ESI-2]

002205D8 84FFテストBH、BH

002205DA ^ 75 F1 JNZショート002205CD

002205DC 8B76 3A MOV ESI、DWORD PTR DS:[ESI + 3A]

002205DF 66:BA 5045 MOV DX、4550

002205E3 8D341E LEA ESI、DWORD PTR DS:[ESI + EBX]

002205E6 66:AD LODS WORD PTR DS:[ESI]

002205E8 66:33D0 XOR DX、AX

002205EB ^ 75 E0 JNZ SHORT 002205CD

002205ED C3 RETN



「CALL 00220602」-新しい0x2C00メモリを割り当て(現在は読み取り/書き込みのみ)、現在のプロセスを起動したファイルのフルネームを見つけ、読み取り用にファイルを開きます

00220602 8B7D 70 MOV EDI、DWORD PTR SS:[EBP + 70]; SS:[002206C4] = 00002C00

00220 605 6A 04プッシュ4

00220 607 68 00 100 000 PUSH 1000

0022060C 57 PUSH EDI

0022060D 6A 00プッシュ0

0022060F FF55 10 CALL DWORD PTR SS:[EBP + 10]; kernel32.VirtualAlloc

00220 612 8BF0 MOV ESI、EAX

00220614 81EC 04010000 SUB ESP、104

0022061A 8BFC MOV EDI、ESP

0022061C 68 04010000 PUSH 104

00220 621 57 PUSH EDI

00220 622 53 PUSH EBX; 00400000

00220623 FF55 20 CALL DWORD PTR SS:[EBP + 20]; kernel32.GetModuleFileNameA

00220 626 6A 00プッシュ0

00220 628 68 80,000,000プッシュ80

0022062D 6A 03プッシュ3

0022062F 6A 00プッシュ0

00220 631 6A 01プッシュ1

00220 633 68 00000080プッシュ80,000,000

00220 638 57 PUSH EDI

00220639 FF55 24 CALL DWORD PTR SS:[EBP + 24]; kernel32.CreateFileA

0022063C 81C4 04010000 ESPを追加、104

00220642 C3 RETN





ハンドルが開いているファイルに戻ると、ポインターがオフセット0x6263に設定されます。

00220 096 8BF8 MOV EDI、EAX

00220 098 6A 00プッシュ0

0022 009A 6A 00プッシュ0

0022009C FF75 6C PUSH DWORD PTR SS:[EBP + 6C]; SS:[002206C0] = 00006263

0022 009F 57 PUSH EDI

002200A0 FF55 28 CALL DWORD PTR SS:[EBP + 28]; kernel32.SetFilePointer



HEXエディターでは、このオフセットでいくつかのデータが実際に保存され、ほとんどの場合暗号化されていることがわかります。





指定されたオフセットでサイズ0x2C00のファイルから以前に作成されたメモリセグメントにデータを読み込みます。

002200A3 8B4D 70 MOV ECX、DWORD PTR SS:[EBP + 70]; SS:[002206C4] = 00002C00

002200A6 6A 00プッシュ0

002200A8 54 PUSH ESP

002200A9 58 POP EAX

002200AA FF3424 PUSH DWORD PTR SS:[ESP];スタックSS:[0018FF28] = 0000005C

002200AD 50プッシュEAX

002200AE 51 PUSH ECX

002200AF 56 PUSH ESI; 00230,000

002200B0 57 PUSH EDI

002200B1 FF55 2C CALL DWORD PTR SS:[EBP + 2C]; kernel32.ReadFile





次に、コピーされたデータを復号化する手順が呼び出されます。







手順のリスト全体を表示するわけではありません。復号サイクルは次のとおりです。

00220505 3B75 60 CMP ESI、DWORD PTR SS:[EBP + 60]

00220 508 75 0D JNZショート00220517

0022050A 0375 64 ESIを追加、DWORD PTR SS:[EBP + 64]

0022050D 037D 64 EDIの追加、DWORD PTR SS:[EBP + 64]

00220510 2B4D 64 SUB ECX、DWORD PTR SS:[EBP + 64]

00220513 85C9テストECX、ECX

00220515 74 12 JE SHORT 00220529

00220517 AD LODS DWORD PTR DS:[ESI] <-読み取り、復号化、書き込み

00220518 50プッシュEAX

00220519 05 224AFE8D EAXの追加、8DFE4A22

0022051E 0FC8 BSWAP EAX

00220520 33C2 XOR EAX、EDX

00220522 5A POP EDX

00220523 AB STOS DWORD PTR ES:[EDI]

00220524 83E9 03 SUB ECX、3

00220527 ^ E2 DCループショート00220505





ダンプで復号化した後、次の図を確認できます。







署名「MZ」および「PE」は、目標に近いことを示しています。



現在のプロセスの新しいヘッダーとセクションの形成。

復号化後、現在のプロセスのImageBaseの512バイトは、復号化されたデータで上書きされます(もちろん、ターゲットメモリ領域の権限をRWに変更した後)。







一番下の行-古いヘッダーとセクションのテーブルが新しく書き換えられました。 新しいセクションの表からわかるように、2つのセクション「.text」と「.rsrc」があります。







次に、次のコードに移動します。

00220 010 0349 3C ECXを追加、DWORD PTR DS:[ECX + 3C]

00220104 8D79 18 LEA EDI、DWORD PTR DS:[ECX + 18]

00220107 8B57 20 MOV EDX、DWORD PTR DS:[EDI + 20]

0022010A 0FB741 14 MOVZX EAX、WORD PTR DS:[ECX + 14]

0022010E 03F8 EDI、EAXを追加

00220 110 0FB749 06 MOVZX ECX、WORD PTR DS:[ECX + 6]

00220 0114 60 PUSHAD <-新しいセクションの形成サイクルの開始

00220 158 8B47 08 MOV EAX、DWORD PTR DS:[EDI + 8]

00220118 85C0テストEAX、EAX

0022011A 74 42 JE SHORT 0022015E

0022011C E8 CD040000 CALL 002205EE

00220121 8BC8 MOV ECX、EAX

00220123 8B47 24 MOV EAX、DWORD PTR DS:[EDI + 24]

00220 266 E8 AA020000 CALL 002203D5

0022012B 0377 14 ESI、DWORD PTR DSの追加:[EDI + 14]

0022012E FF77 10 PUSH DWORD PTR DS:[EDI + 10]

00220131 8B7F 0C MOV EDI、DWORD PTR DS:[EDI + C]

00220134 03FB EDI、EBXを追加

00220136 5B POP EBX

00220 137 37 PUSH EAX

00220 018 8BD4 MOV EDX、ESP

0022013A 52 PUSH EDX

0022013B 50 PUSH EAX

00220 013C 51 PUSH ECX

0022013D 57 PUSH EDI

0022013E 51 PUSH ECX

0022013F 52 PUSH EDX

00220 140 6A 04プッシュ4

00220,142 51 PUSH ECX

00220,143 57 PUSH EDI

00220 014 FF55 0C CALL DWORD PTR SS:[EBP + C]

00220,147 59 POP ECX

00220 048 33C0 XOR EAX、EAX

0022014A 57 PUSH EDI

0022014B F3:AA REP STOS BYTE PTR ES:[EDI] <-メインプロセスメモリ領域のリセット

0022014D 5F POP EDI

0022014E 85F6テストESI、ESI

00220 150 74 08 JE SHORT 0022015A

00220 052 85DBテストEBX、EBX

00220 054 74 04 JE SHORT 0022015A

00220156 8BCB MOV ECX、EBX

00220158 F3:A4 REP MOVS BYTE PTR ES:[EDI]、BYTE PTR DS:[ESI] <-新しいセクションの記録

0022015A FF55 0C CALL DWORD PTR SS:[EBP + C]

0022 015D 58 POP EAX

0022015E 61 POPAD

00220 015F 83C7 28 EDIを追加、28

00220162 ^ E2 B0ループショート00220114



最初に、セクションテーブルが検索されます。 サイクルの次は、各セクションのRawDataとVirtualSizeで、メモリのメインセクションをゼロにし、新しいセクションを記録します。 したがって、現在のプロセスの新しい「ボディ」が形成されます。



次に、プロシージャコールに対応します。

00220,169 E8 AE000000 CALL 0022021C



「.text」セクションの先頭にあるIAT(インポートアドレステーブル)を復元します。 手順の結果:





次に、データが以前に保存されていたメモリが解放され、新しいプロセス環境(0x00230000)が形成されます。

002201BD FF55 14 CALL DWORD PTR SS:[EBP + 14]; kernel32.VirtualFree





エピローグに来てください-OEPを抽出してください:







OEPに移動します。







デバッガーにコードを分析し、既に解凍されたダウンローダーの美しく読みやすいリストを取得するように指示します。メインの汎用モジュールをロードするために使用される行はすでに区別できます。







一般的な復号化ロジック







  1. HeapCreateを使用して0x6D0(1744バイト)RWEメモリ領域を割り当てます。 .dataセクション(0x00408E63-0x00409532)から割り当てられたメモリへのデータの復号化とコピー。
  2. 割り当てられたメモリのゼロオフセットへのコード実行の転送。
  3. 必要なAPI関数を検索し、現在のメモリ領域のオフセット0x654にアドレスを持つ配列を作成します。
  4. VirtualAllocを使用して、同じサイズの0x6D0(1744バイト)のRWE権限を持つ新しいメモリを作成します。 現在のメモリの内容を新しいものにコピーします。
  5. 「PUSH-RETN」メソッドを使用して、オフセット0x81のメモリの新しいセクションにコード実行を転送します。
  6. RW権限を持つサイズ0x2C00(11,264バイト)の新しいメモリ領域の割り当て。
  7. ソースファイルを読み取り用に開きます。 データを(ファイルオフセット0x6263-0x8E62で)ファイルからメモリの新しいセクションにコピーします。
  8. コピーされたデータの復号化。
  9. 新しいプロセス環境の形成。
  10. OEP(0x004019BA)への移行。




プロセスダンプ



実行可能なアンパックウイルスファイルを取得するプロセスをダンプするために残ります。 ダンプ後の手動固定を回避するために、Immunity Debugger用のOllyDumpExプラグインを使用しました。







起動時に生成される実行可能ファイルの構造は次のとおりです。







おわりに



行われた作業の過程で、彼らは解凍されたダウンローダー実行可能ファイルを受け取りました。 はい。データのコピーと復号化、およびOEPへの移行という重要なポイントを経ることで、説明を短縮できます。 戦闘条件では、マルウェアを分析する際に、解読者のロジックを詳細に解析することはほとんどありません。 ただし、この記事の目的は、逆転に没頭し、おまけとして、マルウェアプロテクターの仕組みを理解することです。



この記事で達成できなかった目標は、ウイルス対策エミュレーターの「詐欺」の原因となるトレッドの主要ポイントをローカライズすることです。 これらの構成要素は、おそらく復号化プログラムに存在します。 誰かがそれらを識別する方法を教えてくれたら、感謝します。



記事の第2部では、Downloaderの機能負荷とCTB-Locker暗号化ツールの起動方法について検討します。 私は彼女が先日現れることを約束しません、なぜなら 時間に限りがあり、この分野での私の小さな経験を否定しません-記事の執筆中にいくつかの問題を理解しますが、これには時間がかかります。



All Articles