要開始寫 NT Native Application 需要有 Microsoft DDK。
因為是用 DDK build system 去編譯,
所以需要寫一個 Sources 檔案,如下:
TARGETNAME=native
TARGETPATH=obj
TARGETTYPE=PROGRAM
SOURCES=native.c
在這裡的 TARGETNAME 指的是你最後編譯出來的檔案名稱會是 native.exe ,
而 TARGETPATH 是指所編譯出來的目錄位置,
至於 TAGETTYPE 則一定要是 PROGRAM ,
這樣編譯出來的執行檔的型態才會正確。
最後的 SOURCES 放的是你所有要編譯的 source codes。
如果不知道怎麼寫 SOURCES 檔,
你可以參考微軟網站 Windows Driver Kit: Driver Development Tools: Build
再來則是來寫 native.c ,
因為是 NT Native Application,
所以也就沒有所謂的 main() 當作程式進入點 (Entry Point),
而是由 NtProcessStartup 進入,
如果你有看從網路上抓下的程式碼,
會發現大家所寫的 prototype 如下:
void NtProcessStartup( PSTARTUP_ARGUMENT Argument )
會附一個叫做 PSTARTUP_ARGUMENT 的參數。
之後有些資料是要從這個參術來取得,
像程式名稱、程式命令列參數等等。
但是事實上這個 Pointer 並非什麼特別的資料結構,
也並沒有真的有個叫做 STARTUP_ARGUMENT 的資料結構,
而應該是 PEB Structure 。
這算是微軟半公開的資料結構,
你可在微軟網站這個連結取得這個資料結構。
如果你對 windbg 熟悉的話,
就可以取得更詳細的 PEB Structure 。
但因為這個 PEB structure 有可能在不同平台上會有些不同,
所以請自行小心使用,
或是多測其他平台 (Windows 2000, Windows XP, Windows Vista... )。
像其他的範例程式一樣,
總是要來顯示一下 "Hello World!" 這字串。
在這邊也沒有 printf 可以使用,
但是你可以用 NtDisplayString 。
NTSTATUS NTAPI NtDisplayString(PUNICODE_STRING String);
這個用法很簡單,
就是給個 UNICODE_STRING 的 structure 去輸出到藍色畫面。
UNICODE_STRING helloWorld;
RtlInitUnicodeString(&helloWorld,L"Hello World!\n");
NtDisplayString(&helloWorld);
只需要這樣寫,你就可以在藍色的畫面上看到"Hello World!"。
之後要離開程式,
也並不像是一般程式 return 就可以了,
而是你需要呼叫 NtProcessTerminate 來結束這個程式。
NTSTATUS NTAPI NtTerminateProcess(HANDLE ProcessHandle, LONG ExitStatus);
原始碼如下:
#include "ntddk.h"
NTSTATUS NTAPI NtDisplayString(PUNICODE_STRING String); NTSTATUS NTAPI NtTerminateProcess(HANDLE ProcessHandle, LONG ExitStatus); void NtProcessStartup(PPEB pPEB) { UNICODE_STRING helloWorld; RtlInitUnicodeString(&helloWorld,L"Hello World!\n"); NtDisplayString(&helloWorld); NtTerminateProcess( NtCurrentProcess(), 0 ); }
現在只需要到目錄下,
輸入 build ,
之後只需要由 ddk 把 native.exe 編譯好之後,
拷貝到 c:\windows\system32 下,
執行 reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager" /v BootExecute /t REG_MULTI_SZ /d "autocheck autochk *\0native\0" /f
重開機後,就可以在藍色的畫面裡,
看到"Hello, world"。
一個簡單的 NT Native Application 就完成了。
原始碼在此下載。 請用 firefox 下載或是支援 data uri 的瀏覽器。
附註:
今天(2015/10/29)發現用 WinDDK 7600.16385.1 會build failed.
需要自己手動把library link進去.
因此需要手動更改SOURCES檔如下:
======================================
TARGETNAME=native
TARGETPATH=obj
TARGETTYPE=PROGRAM
UMTYPE=nt
INCLUDES=\
$(DDK_INC_PATH); \
$(NDK_INC_PATH);
MINWIN_SDK_LIB_PATH=$(SDK_LIB_PATH)
TARGETLIBS= \
$(DDK_LIB_PATH)\ntdll.lib \
$(DDK_LIB_PATH)\nt.lib
USE_NTDLL=1
SOURCES=native.c
======================================
