私はすぐに言います:私はバイラルアナリストではなく、この活動に専門的に関与していません。 私は、3文字の企業グループのいずれかの企業でネットワークエンジニアとして働いています。 ですから、理解をもって厳しく判断し、扱わないようお願いします。
この記事の目的は、マルウェアの動作の高レベルのロジックに関するレポートを作成するためのマルウェアの明示的な分析ではなく、知識と経験を高めるために頭でリバースエンジニアリングに没頭することです。 したがって、アンパックアルゴリズム全体を詳しく説明します。
すぐに、逆アセンブルされたコードの多くの写真とリストがあることを警告します。
建設的な批判の準備ができており、私の考えを最適化するためのアドバイスを喜んでいます。
最近、高く評価されたCTB-Lockerが当社に侵入し、情報セキュリティサービスに興味を持ちました。なぜウイルス対策やWebトラフィックフィルタリングが機能しなかったのですか? このマルウェアが正確に行うことは、 securelistで詳しく説明されています 。 これにより、すべてが明確になり、すでに十分に説明されていることを再分析する意味がありません。
インシデントの原因を理解するために、このマルウェアの配布ベクトルを検討します。
ユーザーの観点からこれがどのように見えるか:
- .cabアーカイブが添付された手紙が届きました。
- ユーザーはアーカイブを開き、そこから.scrを実行します。
- .rtfファイルは、あいまいで興味深いデータで開きます。
- ユーザーはこのファイルを落ち着いて閉じ、作業を続けます。
- しばらくすると、デスクトップにCTB-Lockerウィンドウがポップアップし、ユーザーにとって悲しい情報が表示されます。
解読する
そのため、.cabアーカイブから怒りと噛み付きの.scrを取得します。 これをImmunity Debuggerで開き、F9で数回押すと、途中でアンチデバッグのトリックに出会うことなく、エントリポイント0x4021C6に到達します。これはすでに良好です。
![](https://habrastorage.org/files/feb/371/033/feb371033bef4bc994749278c3060cf8.png)
リストを少し調べてインポートを調べたところ、わかりやすく「有用」なものは見つかりませんでした。 ネットワークアクティビティに関連するものはありません-何かがより深く隠されていることを示唆しています。 パッカー?
PEiDが私たちに伝えること:
![](https://habrastorage.org/files/2c1/dfe/a35/2c1dfea355ab46cba0be6048eca78f04.png)
既知のパッカーが見つかりませんでした。 さらに、エントロピー分析により、ファイルがパックされていない可能性が高いことがわかります。 しかし、さらに見てみましょう...
コードが少しあると、最初のメモリ操作に出くわします。 HeapCreateに渡される変数はあまり巧妙に隠されていません。
![](https://habrastorage.org/files/e9b/43b/dda/e9b43bdda47249d390043e3f353a3303.png)
割り当てられたメモリのサイズは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
デバッガーにターゲットメモリ領域を逆アセンブルし、予想される結果を取得するように指示します。これは非常に実行可能なコードです
![](https://habrastorage.org/files/b33/595/52e/b3359552e6ee493aa5ae33f7d61b08a4.png)
復号化されたコードへの移行は間もなく開始されました。
![](https://habrastorage.org/files/45e/6bc/0e4/45e6bc0e4a6d4e698e9529a108a75af8.png)
最初に、プロシージャにパラメータを渡す興味深い方法に出会います。 最初のそのような関数の例を考えてみましょう。 ご覧のとおり、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」の呼び出しが発生し、次の命令のアドレスがプッシュされてスタックに戻ります。 ダンプを見ると、ライブラリの名前がわかります。
![](https://habrastorage.org/files/1ac/ad2/c79/1acad2c797854d0aa1081cf125ff6e0e.png)
さらに、複数回リストする場合、そのような方法があります。
次に興味深い点は、接続されたライブラリから必要な関数を見つける手順です。 プロシージャに渡されるパラメータの中には、上記の方法で取得した不可解なバイトセットへのポインタがあります。次に、その理由と内容を把握します。 したがって、手順自体:
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のアドレスを受け取ることが明らかになりました。 次に、ロジックは順番に:
- PEヘッダーは、ターゲットDLLエクスポートテーブルのアドレスを計算します。
- 各関数の名前はエクスポートテーブルから取得され、特定のハッシュの合計が計算されます。
- 計算されたハッシュ和がパラメーターで取得されたものと一致するかどうかを確認します。
- ハッシュ値が一致する場合、見つかった関数のアドレスが返されて返されます。
必要な機能を検索すると、元のハッシュの合計が実際のアドレスに書き換えられます。
![](https://habrastorage.org/files/c24/811/ee0/c24811ee01964569ba3d679cf566e31d.png)
次に、「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が使用する既に生成されたアドレスの配列の最後に追加されます。
![](https://habrastorage.org/files/b2e/155/9f3/b2e1559f3e63469f9c69af72914c75b0.png)
使用される関数の配列が形成され、その後、その使用は、前回と同じサイズの新しいメモリ領域の割り当てで直ちに開始されます-0x6D0:
![](https://habrastorage.org/files/16d/a64/fb7/16da64fb7024432492b09826136eb570.png)
flProtect = 0x40。これも割り当てられたメモリでコードが実行される可能性を示しています。
「VirtualAlloc」の後、スタックのリターンアドレスを「RETN」のオフセット0x81で保存しながら、現在のメモリを新しいメモリにコピーするサイクルがすぐに発生します。
![](https://habrastorage.org/files/747/4ea/6f9/7474ea6f9aba41689db0f7ed32f9aba2.png)
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エディターでは、このオフセットでいくつかのデータが実際に保存され、ほとんどの場合暗号化されていることがわかります。
![](https://habrastorage.org/files/7ba/5ff/059/7ba5ff05904346438277cd65afe056e0.png)
指定されたオフセットでサイズ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
次に、コピーされたデータを復号化する手順が呼び出されます。
![](https://habrastorage.org/files/942/272/c89/942272c8946d49cd8710e00dbf545b2a.png)
手順のリスト全体を表示するわけではありません。復号サイクルは次のとおりです。
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
ダンプで復号化した後、次の図を確認できます。
![](https://habrastorage.org/files/309/dc9/0be/309dc90bea624ea080551a50f5dba7b4.png)
署名「MZ」および「PE」は、目標に近いことを示しています。
現在のプロセスの新しいヘッダーとセクションの形成。
復号化後、現在のプロセスのImageBaseの512バイトは、復号化されたデータで上書きされます(もちろん、ターゲットメモリ領域の権限をRWに変更した後)。
![](https://habrastorage.org/files/b7c/7de/2cd/b7c7de2cd02248acb79409d820d447d2.png)
一番下の行-古いヘッダーとセクションのテーブルが新しく書き換えられました。 新しいセクションの表からわかるように、2つのセクション「.text」と「.rsrc」があります。
![](https://habrastorage.org/files/5ab/b92/d09/5abb92d09f0d462f9706224ed1240241.png)
次に、次のコードに移動します。
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(インポートアドレステーブル)を復元します。 手順の結果:
![](https://habrastorage.org/files/373/f34/619/373f346193f248a69e4430f4209ccb66.png)
次に、データが以前に保存されていたメモリが解放され、新しいプロセス環境(0x00230000)が形成されます。
002201BD FF55 14 CALL DWORD PTR SS:[EBP + 14]; kernel32.VirtualFree
エピローグに来てください-OEPを抽出してください:
![](https://habrastorage.org/files/322/d99/d6e/322d99d6ec10422d803f4dfc9b828692.png)
OEPに移動します。
![](https://habrastorage.org/files/eab/3ed/b37/eab3edb3712e42e5a45af139a57ffe2e.png)
デバッガーにコードを分析し、既に解凍されたダウンローダーの美しく読みやすいリストを取得するように指示します。メインの汎用モジュールをロードするために使用される行はすでに区別できます。
![](https://habrastorage.org/files/37c/604/900/37c6049005574b8e80c690451899d28f.png)
一般的な復号化ロジック
![](https://habrastorage.org/files/9e5/ad2/673/9e5ad26732bd43cca9f66a024467d308.png)
- HeapCreateを使用して0x6D0(1744バイト)RWEメモリ領域を割り当てます。 .dataセクション(0x00408E63-0x00409532)から割り当てられたメモリへのデータの復号化とコピー。
- 割り当てられたメモリのゼロオフセットへのコード実行の転送。
- 必要なAPI関数を検索し、現在のメモリ領域のオフセット0x654にアドレスを持つ配列を作成します。
- VirtualAllocを使用して、同じサイズの0x6D0(1744バイト)のRWE権限を持つ新しいメモリを作成します。 現在のメモリの内容を新しいものにコピーします。
- 「PUSH-RETN」メソッドを使用して、オフセット0x81のメモリの新しいセクションにコード実行を転送します。
- RW権限を持つサイズ0x2C00(11,264バイト)の新しいメモリ領域の割り当て。
- ソースファイルを読み取り用に開きます。 データを(ファイルオフセット0x6263-0x8E62で)ファイルからメモリの新しいセクションにコピーします。
- コピーされたデータの復号化。
- 新しいプロセス環境の形成。
- OEP(0x004019BA)への移行。
プロセスダンプ
実行可能なアンパックウイルスファイルを取得するプロセスをダンプするために残ります。 ダンプ後の手動固定を回避するために、Immunity Debugger用のOllyDumpExプラグインを使用しました。
![](https://habrastorage.org/files/d05/659/0f7/d056590f7a454583871096b8b7a3495a.png)
起動時に生成される実行可能ファイルの構造は次のとおりです。
![](https://habrastorage.org/files/9ae/9f6/ffa/9ae9f6ffa5e140eca0d0573274835d3c.png)
おわりに
行われた作業の過程で、彼らは解凍されたダウンローダー実行可能ファイルを受け取りました。 はい。データのコピーと復号化、およびOEPへの移行という重要なポイントを経ることで、説明を短縮できます。 戦闘条件では、マルウェアを分析する際に、解読者のロジックを詳細に解析することはほとんどありません。 ただし、この記事の目的は、逆転に没頭し、おまけとして、マルウェアプロテクターの仕組みを理解することです。
この記事で達成できなかった目標は、ウイルス対策エミュレーターの「詐欺」の原因となるトレッドの主要ポイントをローカライズすることです。 これらの構成要素は、おそらく復号化プログラムに存在します。 誰かがそれらを識別する方法を教えてくれたら、感謝します。
記事の第2部では、Downloaderの機能負荷とCTB-Locker暗号化ツールの起動方法について検討します。 私は彼女が先日現れることを約束しません、なぜなら 時間に限りがあり、この分野での私の小さな経験を否定しません-記事の執筆中にいくつかの問題を理解しますが、これには時間がかかります。