編譯器的一些參數

    繼續昨天的話題,用WDK6001編譯驅動用了這麼一些關鍵選項:

(CL.exe)

/Zl:省略 .obj 文件中的默認 C 運行時庫名稱。默認情況下,編譯器將庫名放入 .obj 文件中,以便使鏈接器指向正確的庫。

/Oi:生成內部函數,前一篇文章已經講過了,(Cheack模式有,Free模式卻沒有)

 

(Link.exe)

/NODEFAULTLIB  在解析外部引用時忽略所有(或指定的)默認庫

/RELEASE 選項在 .exe 文件頭中設置校驗和。

操作系統要求設備驅動程序的校驗和。爲設備驅動程序的發佈版本設置校驗和,以確保與未來的操作系統兼容。

當指定 /SUBSYSTEM:NATIVE 選項時,默認情況下設置 /RELEASE 選項。

/entry:GsDriverEntry@8 指定入口點

/subsystem:native,6.00

 

從上面看出C運行時庫是肯定無法連接了,甚至用#pragma comment( lib, "" )也不行了,因爲會被/NODEFAULTLIB忽略,可以看一下啊MSDN上的說明:

lib Places a library-search record in the object file. This comment type must be accompanied by a commentstring parameter containing the name (and possibly the path) of the library that you want the linker to search. The library name follows the default library-search records in the object file; the linker searches for this library just as if you had named it on the command line provided that the library is not specified with /nodefaultlib. You can place multiple library-search records in the same source file; each record appears in the object file in the same order in which it is encountered in the source file.

 

解決的辦法是有的,可以在source裏改:TARGETLIBS= $(DDK_LIB_PATH)/your.lib

linker

Places a linker option in the object file. You can use this comment-type to specify a linker option instead of passing it to the command line or specifying it in the development environment. For example, you can specify the /include option to force the inclusion of a symbol:

#pragma comment(linker, "/include:__mySymbol")
Only the following (comment-type ) linker options are available to be passed to the linker identifier:
  • /DEFAULTLIB

  • /EXPORT

  • /INCLUDE

  • /MANIFESTDEPENDENCY

  • /MERGE

  • /SECTION

/DEFAULTLIB 選項將一個 library 添加到 LINK 在解析引用時搜索的庫列表。用 /DEFAULTLIB 指定的庫在命令行上指定的庫之後和 .obj 文件中指定的默認庫之前被搜索。

忽略所有默認庫 (/NODEFAULTLIB) 選項重寫 /DEFAULTLIB:library 。如果在兩者中指定了相同的 library 名稱,忽略庫 (/NODEFAULTLIB:library ) 選項將重寫 /DEFAULTLIB:library

 

現在的編譯器似乎跟vc的有很多區別了,,有些是還很智能,如果它發現某些函數是顯而易見的結果甚至不編譯函數了(直接給結果),真是神奇啊…………

 

再說說程序入口點:

/ENTRY 選項指定一個入口點函數作爲 .exe 文件或 DLL 的起始地址。

必須用 __stdcall 調用約定來定義函數。必須按 WinMain (對於 .exe 文件)或 DllEntryPoint (對於 DLL)的 Win32 API 中記錄的內容定義參數和返回值。建議讓鏈接器設置入口點,以便 C 運行時庫正確初始化,並執行靜態對象的 C++ 構造函數。

默認情況下,起始地址爲 C 運行時庫中的函數名。鏈接器根據程序的屬性來選擇該函數,如下表所示。

函數名

...的默認值

mainCRTStartup (或 wmainCRTStartup

使用 /SUBSYSTEM:CONSOLE 的應用程序;調用 main (或 wmain

WinMainCRTStartup (或 wWinMainCRTStartup

使用 /SUBSYSTEM:WINDOWS 的應用程序;調用 WinMain (或 wWinMain ),它必須用 __stdcall 來定義

_DllMainCRTStartup

DLL;調用 DllMain (如果存在),DllMain 必須用 __stdcall 來定義

如果未指定 /DLL 或 /SUBSYSTEM 選項,則鏈接器將根據是否定義了 mainWinMain 來選擇子系統和入口點。

函數 mainWinMainDllMain 是三種用戶定義的入口點形式。

 

上面說的非常清楚了,但是驅動程序並不連接C庫函數,沒有什麼main。但/entry:GsDriverEntry@8我知道,關鍵是GsDriverEntry在哪裏?哈哈,在這裏WINDDK/6001~1.180/lib/wlh/i386/BufferOverflowK.lib,這個函數非常簡單:

NTSTATUS GsDriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegPath)
{
    LARGE_INTEGER tickCount;
    KeQueryTickCount(&tickCount);
    if(!___security_cookie || ___security_cookie == 0xbb40)
    {
        ULONG temp = (ULONG)&___security_cookie;
        temp = ((temp >> 8) ^ tickCount.u.LowPart) & 0xffff;
        if(temp)
          ___security_cookie = temp;
        else
          ___security_cookie = tickCount.u.LowPart & 0xffff;
    }

    ___security_cookie_complement = ~___security_cookie;
    return DriverEntry(DriverObject,RegPath);
}

 

哦!這裏還有一個很大的問題:

"/Oi:生成內部函數(Cheack模式有,Free模式卻沒有)"那Free模式怎麼辦!!!!!!!!

我看到Free模式時有 /Oxs(完全優化)

看看/Oxs的說明:

/Ox 可與 /Os (/Oxs ) 結合使用以利於生成較小的代碼大小(優化大小)。

通常,/O2 應該優先於 /Ox ,而 /O1 優先於 /Oxs

使用 /Ox 的作用與使用下列選項的作用相同:

暈!又有/Oi,,用IDA看看它們的代碼,有驚人的差別……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章