继续昨天的话题,用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
linkerPlaces 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") |
-
/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 选项,则链接器将根据是否定义了 main 或 WinMain 来选择子系统和入口点。
函数 main 、WinMain 和 DllMain 是三种用户定义的入口点形式。
上面说的非常清楚了,但是驱动程序并不连接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 的作用与使用下列选项的作用相同:
-
/Ob n ,其中 n = 2
晕!又有/Oi,,用IDA看看它们的代码,有惊人的差别……