おそらく多くのプログラマーと好奇心people盛な人たちは、exe / dll / sysなどのファイルにMZとPEヘッダーの間に不可解なデータが含まれているという事実に直面しました。
多くは彼らに注意を払わなかったが、彼らの何人かはこのファイルがマイクロソフトのコンパイラを使用して作成されたと言うことができた。 プログラムが機能するために必要なデータがそこに隠されていると考える人もいました。 そして、これはこの事実の一面にすぎません。
反対側は、多くの人々が、Microsoftがコンパイラ(C \ C ++ \ MASM)を使用して作成された実行可能ファイルを特別にマークし、これが悪意のあるプログラムの作成者を計算するために行われることを知っていることです。
多くの人は、リンクするときにコンピューターまたはユーザーに関する情報が入力されると考えています。
これら両方の事実を組み合わせることで、リッチデータが可能であり、悪意のあるプログラムが作成された人/コンピューターを特定できる識別子であると自信を持って言えます。 この事実の妥当性が検証されます。
詳細が豊富
目視検査で発見される可能性のあるこのデータの主な特徴のうち、次のものを区別できます。
- それらは常にMZヘッダーの後、PEヘッダーの前に来ます。
- ほとんどの場合、ファイルの先頭からの相対的な位置= 80h = 128。
- 同じコンピューターでコンパイルされたプログラムは、同じリッチデータを持ちます。
RICHデータの例(ピンクでマーク):
つまり その構造はおよそ次のとおりです。
XXXXXXXX - YYYYYYYY - YYYYYYYY - YYYYYYYY
XXXXXXXX - XXXXXXXX - XXXXXXXX - XXXXXXXX
XXXXXXXX - XXXXXXXX - XXXXXXXX - XXXXXXXX
[Rich ] - YYYYYYYY
ここで、YYYYYYYY-32ビット値の繰り返し
XXXXXXXX-常に異なる32ビット値
[リッチ署名]-リッチという単語を形成する4バイト
リッチは何を隠しますか?
少なくともいくつかの情報とそこに保存されているデータの種類を見つけるのに多くの時間を費やし、その結果、記事が置かれている外部サイトが見つかりました(http://ntcore.com/files/richsign.htm)ダニエル・ピステリという名前の男性で、この署名を研究しただけでなく、その形成方法や多くの有用なデータも調べました。
上記の記事で見つかったように、YYYYYYYYとしてマークされている番号は暗号化/復号化キーです。 これについて詳しく説明すると、これは単なるXOR操作(単なる暗号化)のマスクです
デコード:
- 署名リッチの後にダブルワードを取ります-これが私たちの鍵です。
- リッチデータの各ダブルワードは、キーを使用してXORで復号化され、リッチシグネチャに到達するまで復号化されます(復号化する必要はありません)。
その結果、次のような結果が得られます。
DanS-00000000 - 00000000 - 00000000
XXXXXXXX - XXXXXXXX - XXXXXXXX - XXXXXXXX
XXXXXXXX - XXXXXXXX - XXXXXXXX - XXXXXXXX
Rich-YYYYYYYY
ここで、XXXXXXXX-復号化されたデータ
00000000-それ自体のXOR番号= 0。
DanS署名は、これが正確にリッチデータであり、単純な擬似乱数ジェネレーターによって偽造されていないことを確認するために入力された可能性があります。
さらに、この記事の著者は、IDAを介してコンパイラーを実行し、リッチデータで記述されている内容をより詳細に調査しました。 判明したように、それらの形式は次のとおりです。
XXXX00YY ZZZZZZZZ XXXX00YY ZZZZZZZZ
XXXX00YY ZZZZZZZZ XXXX00YY ZZZZZZZZ
ここで、xxxxは古いバージョンです
YYYY-若いバージョン
ZZZZZZZZ-ビルドのバージョンのようなもの。
このことから、リッチデータは、プログラムの作成に使用されたライブラリとコンパイラの単なるバージョンであると安全に言うことができます。
実用的な実装:
すべては問題ありませんが、どのバージョンが存在するのかを自分の目で確認する方が常に優れています。 はい、このプロセスを自動化したいです。
したがって、リッチデータで配線されたライブラリバージョンを表示する小さな関数をDelphiで作成します。
//
procedure PrintRichData(FileName : string);
var
Lib : DWORD; //
Data : DWORD; //
Key : DWORD; //
x : integer;
cnt : integer; // -
MinVer, MajVer : WORD; //
Times : DWORD;// .
Msg : string;
begin
Msg := '';
//
Lib := LoadLibrary(PAnsiChar(FileName));
if Lib <> 0 then //
begin
cnt := 0;
while true do // Rich -
begin
//
Data := DWORD(pointer(Lib + $80 + (cnt shl 2))^);
if Data = 0 then break; //
if Data = $68636952 then break; // - Rich
inc(cnt); //
end;
if cnt <> 0 then // Rich
begin
//
Key := DWORD(pointer(Lib + $80 + ((cnt+1) shl 2))^);
x := 4; // DanS 3 , 4-
while x < cnt-1 do //
begin
Data := DWORD(pointer(Lib + $80 + (x shl 2))^) xor Key; //
MinVer := Data and $FFFF; //
MajVer := (Data shr 16) and $0F; //
inc(x);
Times := DWORD(pointer(Lib + $80 + (x shl 2))^) xor Key; // . .
Msg := Msg + `Ver: ` + inttostr(MajVer) + `.0.` + inttostr(MinVer) + ` Times:` + inttostr(Times) + #13#10;
inc(x); //
end;
MessageBox(0, PAnsiChar(Msg), `INFO`, 0);
end;
FreeLibrary(Lib);
end;
end;
この機能の結果として、バージョン情報を取得できます。 私の場合、実験ファイルには次のライブラリバージョンがありました
Ver: 1.0.0 Times:44
Ver: 9.0.9210 Times:5
Ver: 0.0.9210 Times:1
Ver: 12.0.9178 Times:8
Ver: 13.0.9210 Times:1
これが私たちを脅かすものは何ですか:
上記のデータによると、Richは重要な機密情報を保存しないと言えるので、それらがプログラムに存在するという事実を心配する必要はありません。
実際には、次の重要なポイントを特定できます。
- 使用されたコンパイラのバージョンを確認できます。
- 同じプログラムに対して、異なるコンピューター上の同じバージョンのコンパイラーは、同じリッチデータを提供します。 したがって、これらのデータによると、このプログラムがこのコンピューターで作成されたことを直接証明することはできません。
- 暗号化マスクはPEヘッダーのデータに基づいて計算されるため、ウイルス対策プログラムは悪意のあるプログラムを分析するときに署名として使用できます
- この署名を削除すると、プログラムのウイルス対策に関心が集まる可能性があります。
- バージョンデータのランダムな値は、ウイルス対策の注意を引くこともあります。
- ファイル保護システムを作成するときに、完全にランダムなリッチデータを使用すると、ウイルス対策ソフトウェアはファイルが変更されたことをすぐに理解できます。 2番目の署名チェック(DanS)は失敗します。 したがって、このデータを自分で生成する方が良い場合は、最も一般的なバージョンのライブラリを用意することをお勧めします。
参照:
1)Daniel Pistelli(http://ntcore.com/files/richsign.htm)-リッチデータの詳細な説明、キー生成方法、リッチデータの作成を無効にするコンパイラパッチ。
2)Vovane(http://www.wasm.ru/forum/viewtopic.php?id=8572)-プログラムの偽造とリッチデータの検証。