豊富な署名、またはMSコンパイラが隠すもの

エントリー
おそらく多くのプログラマーと好奇心people盛な人たちは、exe / dll / sysなどのファイルにMZとPEヘッダーの間に不可解なデータが含まれているという事実に直面しました。

多くは彼らに注意を払わなかったが、彼らの何人かはこのファイルがマイクロソフトのコンパイラを使用して作成されたと言うことができた。 プログラムが機能するために必要なデータがそこに隠されていると考える人もいました。 そして、これはこの事実の一面にすぎません。

反対側は、多くの人々が、Microsoftがコンパイラ(C \ C ++ \ MASM)を使用して作成された実行可能ファイルを特別にマークし、これが悪意のあるプログラムの作成者を計算するために行われることを知っていることです。
多くの人は、リンクするときにコンピューターまたはユーザーに関する情報が入力されると考えています。

これら両方の事実を組み合わせることで、リッチデータが可能であり、悪意のあるプログラムが作成された人/コンピューターを特定できる識別子であると自信を持って言えます。 この事実の妥当性が検証されます。

詳細が豊富
目視検査で発見される可能性のあるこのデータの主な特徴のうち、次のものを区別できます。

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操作(単なる暗号化)のマスクです

デコード:

その結果、次のような結果が得られます。
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は重要な機密情報を保存しないと言えるので、それらがプログラムに存在するという事実を心配する必要はありません。

実際には、次の重要なポイントを特定できます。


参照:
1)Daniel Pistelli(http://ntcore.com/files/richsign.htm)-リッチデータの詳細な説明、キー生成方法、リッチデータの作成を無効にするコンパイラパッチ。
2)Vovane(http://www.wasm.ru/forum/viewtopic.php?id=8572)-プログラムの偽造とリッチデータの検証。

Source: https://habr.com/ru/post/J98174/


All Articles