文書化されていないWindows関数の使用例

ほとんどのSysinternalsプログラムは、文書化されていない機能を使用しています。 私はこの事実に十分興味を持ってこのトピックに興味を持ちました。 かっこいい人が、同じくらいかっこいいプログラムで、説明されていない関数をどのように使用するかは興味深いです。



私たちは、必要な範囲で怠areなプログラマーであり、WinAPIおよび最新のWindows OSのアーキテクチャと調和するCを知っていると仮定します。 私たちは、ホイールを再発明することなく(そして腕と頭に負担をかけすぎないように)美しく、迅速かつ効率的にタスクを完了したいと考えています。



実験関数を探しましょう。 ntdll.dllには多くの利点があります。 私自身はWin7 64の下で書いていますが、素晴らしいライブラリの32ビット版を取りました。 念のため:%SystemDisk%\ Windows \ System32 \ ntdll.dll。



簡単にするために、Idaでntdllを開き、エクスポートされる関数を確認します。 Idaがない場合は、PEファイルで動作するプログラム(PEToolsなど)を使用できます。 Rtl(ランタイムライブラリ)プレフィックスを持つ関数に興味があります。 つまり、コードの実行中に、このシステム関数にサービスについて問い合わせることができます。



単純な関数を少し検索したところ、RtlComputeCrc32が見つかりました。







関数名をダブルクリックすると、逆アセンブルされたコードが表示されます。 HDasmやW32Dasmのような他の逆アセンブラーで関数を学習できます。 スペースを無駄にしないために、Idaデコンパイラーによって親切に提供された擬似コードRtlComputeCrc32を引用します(Hex-RaysデコンパイラーがEdit-> Pluginsプラグインで利用可能な場合、関数本体でF5を押します)。







すぐに多くの情報を取得します! 私たちが実際に探しているものを考えなければなりません。 必要なもの:

1)ntdllでアドレスを取得する関数の名前。

2)関数への正しいポインターを作成する関数のプロトタイプ。

3)正しい引数をそれに渡し、結果を正しく処理するための、おおよその作業原理。



擬似コードからすでに取得しているアイテム1-2。 ここでのタスクは、関数を理解し、それに基づいて何かからCRC32を計算するプログラムを作成することです。



関数がサイズがa3で、 a1がアルゴリズムの初期化値である配列a2のバイトを反復処理することは、擬似コードから簡単に理解できます。 バイトで計算を行った後、RtlCrc32Tableテーブルからインデックスを取得します(ダブルクリックすると、巨大なテーブルが表示されます)。 Google CRC32と実装例。すべてが正しいことを理解しています。



小さなことは、獲物を利用することです。 Visual Studioで空のコンソールアプリケーションを作成しましたが、もちろん他の環境でも実行できます。



GetModuleHandle()はntdllハンドルを返し、GetProcAddress()は関数のアドレスです。 UndocFoo型の関数へのポインターを使用して、RtlComputeCRC32()を呼び出します。



#include <stdio.h> #include <windows.h> typedef INT (WINAPI *UndocFoo)(INT accumCRC32, const BYTE* buffer, UINT buflen); int main() { HMODULE hDLL = GetModuleHandle(TEXT("ntdll.dll")); if (hDLL == NULL) { puts("[-] Failed to find ntdll.dll\n"); return EXIT_FAILURE; } puts("[+] Got ntdll.dll handle\n"); UndocFoo ComputeCrc32 = (UndocFoo)GetProcAddress(hDLL, "RtlComputeCrc32"); if (ComputeCrc32 == NULL) { puts("[-] Failed to find RtlComputeCrc32\n"); return EXIT_FAILURE; } puts("[+] Found RtlComputeCrc32 address\n"); puts("[*] Calling RtlComputeCrc32...\n"); BYTE buffer[] = {0x01, 'a', 7}; INT iCRC32 = ComputeCrc32(INT(0), (BYTE*)buffer, 3); printf("[+] Computed CRC32 --> 0x%x\n\n", iCRC32); puts("Press any key to quit\n"); getchar(); return EXIT_SUCCESS; }
      
      











成功。 任意のオンライン計算機を使用して確認できます。

バイト016107からCRC32 = 0x1c017c60が得られました。







オンライン計算機でも同じことがわかりました。







そのため、独自の機能を実装したり、他人の大きなコードを使用したりする時間を無駄にすることなく、このような素晴らしいプログラムを作成しました。 簡単で楽しかったです。



All Articles