GCCを使用してWindows NTのカーネルDLLを作成

8906 ワード

原文リンク:GCCを使用してWindows NTのカーネルDLLを作成
 
階層型ドライバの章では、I/Oマネージャの直列接続に依存せず、カーネルルーチンを直接呼び出すことで、ドライバの実行効率を大幅に向上させることができます.
このような機能を実現するためには、ユーザモードでのDLLと同様のメカニズムを提供する必要があるが、この「DLL」はカーネルにロードされる.実はWindows NTカーネル自体はとっくにこのようなメカニズムを利用しています.例えばHal.dll、ntoskrnl.Exceや、サードパーティ製ドライバに対してHAL層、カーネル層、実行体層の機能関数をそれぞれ導出したドライバなどがあります.
Tim Robertsの「カーネルモードのDLL」では、カーネルDLLの主な特徴が示されています.
 
カーネルDLLは、ユーザー・モードDLLと同じです.リンクは、DLLの構築時にインポート・ライブラリを生成し、このDLLを使用するドライバのターゲット・ライブラリのリストに含めます.レジストリテクニックもDLLを停止する特別な動作も必要ありません.カーネルDLLは、参照された他のドライバとともに自動的にロードされ、最後に参照されたドライバとともに自動的にアンインストールされます(注1).
 
このようなDLLを実現するために、RobertsはDDKを使用してTARGETYPEをEXPORT_として生成する方法を示した.DRIVERのプロジェクト.私は試して、望み通りに、確かにxxxを創立しました.Sysファイル、私はまたこのsysのPEタイプを観察して、それが標準のカーネルsysと変わらないことを発見して、それではgccで1つのカーネルモードのDLLを生成することができますか?答えは肯定的だ!Windows NTの下にあるCore Dllをgcc(MinGW)で書いている場合は、DDKのEXPORT_DRIVERタイプのモジュールを書くこともできますが、具体的なやり方は省略します...
 
はい、上は冗談です.ほほほ.MinGWでCoreDllを書く方法について詳しく説明します.
  • まずあなたのシステムにMinGWをインストールするべきで、私は今使っています(MinGW 5.1.4).
  • あなたのシステムにはMasm 32 V 9があります.0+の環境(これは必須ではなく、Gccも自分でドライバファイルを生成する能力があり、私はMasm方式を採用しています)では、WINDDKをインストールし、その環境で最終的なドライバファイルを生成することもできます.
  • 用gccNTDrvFrame(注2)CoreDllの動的ロードとアンインストール機能を実現するにはsys.cで次の2つのインスタンスを提供する必要があります.構築と分析に関する内容をそれらの中に入れることができます.同様にDriverには標準的なDriverEntryエントリポイントが含まれている必要がありますが、実際にはシステムは呼び出されません.この要件はシステムを作成することです.カーネルドライバごとに/ENTRY:DriverEntryをリンクオプションに追加するため、人為的に制限されます.従って,導出したDLLのみに対しても擬似入口点を提供しなければならない. 
  • 1 __declspec(dllexport) DDKAPI NTSTATUS DllInitialize(/
    
    2  IN PUNICODE_STRING RegistryPath); 3 __declspec(dllexport) DDKAPI NTSTATUS DllUnload(void);

         4.エクスポートする必要がある関数を作成します.ここでは例を示しただけなので、簡単なエクスポート関数を書きました.
     1 __declspec(dllexport) DDKAPI NTSTATUS GetMagicNum(IN int *pVal)  2 {  3     if(!pVal)  4  {  5         DbgPrint("err : pVal == NULL!/n");  6         return STATUS_DEVICE_CONFIGURATION_ERROR;  7  }  8     DbgPrint("*pVal is %d/n",*pVal);  9     *pVal *= 11 * 11; 10     DbgPrint("After OP --- *pVal is %d/n",*pVal); 11     return STATUS_SUCCESS

        5. コネクタのdefファイルを作成します.内容は次のとおりです.
    NAME CoreDll.sys
    
    EXPORTS
    
        DllInitialize PRIVATE
    
        DllUnload PRIVATE
    
        GetMagicNum

         6. gccNTDrvFrameのbuilderを実行し、CoreDllのコンパイルと接続を完了し、エラーがなければいくつかのファイルが生成され、そのうち2つしか使用されません.1つはxxxです.Sys、これは言うまでもなく他の駆動呼び出しのCoreDllであり、もう一つはxxxである.lib、xxxを呼び出す必要があるすべてのものです.Sysの他のドライバの作成に必要なファイル、hal.lib、ntoskrnl.libはまったく同じです.
     
        7. 別のDriverプロジェクトを新規作成し、b.batのlink接続オプションにxxxを追加します.lib.外部関数を宣言して呼び出す方法は次のとおりです.
    __declspec(dllimport) DDKAPI NTSTATUS GetMagicNum(IN int *pVal); DDKAPI NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,/ PUNICODE_STRING pRegistryPath) { PDEVICE_OBJECT pDevObj; NTSTATUS status = STATUS_DEVICE_CONFIGURATION_ERROR; PRINT("[%s]enter DriverEntry.../n",__func__); RtlInitUnicodeString(&DevName,DEVNAMEW); RtlInitUnicodeString(&SymlnkName,SYMLNKNAMEW); if(IoCreateDevice(pDriverObject,0,&DevName,FILE_DEVICE_UNKNOWN,/
    
            0,false,&pDevObj) != STATUS_SUCCESS) { PRINT("[%s]IoCreateDevice Failed!/n",__func__); goto QUIT; } if(IoCreateSymbolicLink(&SymlnkName,&DevName) != STATUS_SUCCESS) { IoDeleteDevice(pDevObj); PRINT("[%s]IoCreateSymbolicLink Failed!/n",/ __func__); goto QUIT; } pDevObj->Flags |= DO_BUFFERED_IO; pDriverObject->DriverUnload = DriverUnload; pDriverObject->MajorFunction[IRP_MJ_CREATE] = / DrvDispatchCreateClose; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = / DrvDispatchCreateClose; pDriverObject->MajorFunction[IRP_MJ_READ] = / DispatchRead; pDriverObject->MajorFunction[IRP_MJ_WRITE] = / DispatchWrite; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = / DrvDispatchControl; pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = / DrvShutdown; if(!NT_SUCCESS(IoRegisterShutdownNotification(/ pDriverObject->DeviceObject))) { PRINT("[%s]err : Register Shutdown Failed!/n",/ __func__); } int i = 11; GetMagicNum(&i); PRINT("[%s]Addr of KeServiceDescriptorTable : %p/n",/ __func__,KeServiceDescriptorTable); PRINT("[%s]leave DriverEntry.../n",__func__); status = STATUS_SUCCESS; QUIT: return status; }

    もちろんDriverEntryで呼び出す必要はありません.xxxですから.Sysはシステムによってsysを呼び出す前に自動的に動的にロードされる.
     
             8. このsysをbuilderで確立し、プロセス全体が終了します.
     
    终わりの言叶:ここはただ1つの最も简単な例で、もしこのような“小さい”事だけをしてCoreDllを使うならば、鶏を杀して牛刀を使う意味を免れません.CoreDllの用途は大きく広がることができて、どのようにあなたの情熱と才能を発揮するかについては、私の力の及ぶ限りではありません.(^o^)
     
    注1:ただし、Windows 98の第2版またはWindows MeではカーネルDLLはアンインストールされません.
    注2:gccNTDrvFrameは私が書いたgccがwindows NT駆動を確立するフレームワークパッケージで、後で新しい文章で紹介します.
     
    (PS:記事参照http://sluttery.spaces.live.com/blog/cns!3569FEA80C717FD4!519.entry)