Kel*_*ang 9 c dll window visual-studio
我最近正在对私有 API 进行一些研究。我尝试在运行时使用和调用诸如NtOpenFile
ntdll.dll 中的函数。幸运的是,它成功了。今天早上我在我的电脑上进行了文件搜索,并在我的C盘中找到了。据我所知,这样的 .lib 文件应该包含可用于链接的 dll 导出存根。因此,我尝试将我的应用程序链接到该库,但我不断收到错误。然而,a显示ntdll.lib显然导出了NtOpenFile。我该如何解决这个错误?LoadLibrary
GetProcAddress
ntdll.lib
unresolved external symbol
dumpbin /EXPORTS
Sir*_*bus 10
现在不再是这样了,你可以找到 ntdll.lib 导入库和 NT 头文件,就像我在 2019 年写这篇文章一样。
使用GetProcAddress()方式需要很多额外的代码。当然,直接导入更干净,并且是我们用于 C/C++ 桌面应用程序的模式。
我曾经通过使用 .def 文件等创建一个简单的 Windows DLL 项目来制作自己的“ntdll.lib”导入库。每次添加每个 ntdll API 函数一个,因为我需要它们作为存根和头文件。扔掉 .dll,只使用其中的 .lib。
但至少自 MSVC 2017 以来,它包含了适用于 32 位和 64 位版本的 x86 和 ARM 的用户模式(用于桌面应用程序)ntdll.lib 库。这可能需要安装 Windows 10 WDK。只需在“C:\Program Files (x86)”中搜索“ntdll.lib”即可找到它们。
然后在标头前面,很多 ntdll 原型和定义都在“winternl.h”中,但不幸的是许多部分丢失和/或只有结构的简化版本等。要解决这个问题,您可以使用神奇的 NT 标头从“Process Hacker”项目设置: https: //github.com/processhacker/processhacker 标头位于“phnt”中。
您将使用以下命令,而不是典型的“windows.h”和“winternl.h”组合:
#include <phnt_windows.h>
#include <phnt.h>
Run Code Online (Sandbox Code Playgroud)
然后,以 Windows 10 作为目标(默认为 Windows 7),您可以使用以下命令:
#undef PHNT_VERSION
#define PHNT_VERSION PHNT_THRESHOLD
Run Code Online (Sandbox Code Playgroud)
请注意“phnt_windows.h”已经为您包含了“windows.h”。所以你应该能够跟在它之后的任何其他 Windows、stdlib、stl 等标头;与典型的桌面构建环境没有太大不同。
或者使用其他一些: https:
//github.com/Fyyre/ntdll
还包括库:
https://github.com/x64dbg/ScyllaHide/tree/master/3rdparty/ntdll
还有另一个也包含 ntdll 库:
https:// /github.com/odzhan/injection/tree/master/ntlib
问题在于库中记录的函数名称以及从编译器生成的函数名称。
dumpbin
仅向您显示基本导出符号NtOpenFile
(未修饰的符号),但还有一个导入符号__imp_NtOpenFile
。现在,如果您尝试静态链接,NtOpenFile
将其声明为:
NTSTATUS NtOpenFile(
_Out_ PHANDLE FileHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_ ULONG ShareAccess,
_In_ ULONG OpenOptions
);
Run Code Online (Sandbox Code Playgroud)
对于 32 位以下的函数,编译器将为__stdcall
32 位以下的函数生成符号_NtOpenFile@24
,如果我没有错误地计算调用参数的字节大小,那么该符号显然不在库中。这是因为 ntdll.lib 旨在在 DDK 下用于驱动程序开发,其中编译器会生成未修饰的符号。
为了阐明这个概念,请使用二进制编辑器打开 ntdll.lib 文件并查找NtOpenFile
,您将只看到它和导入版本__imp_NtOpenFile
。现在打开一个标准库,例如 gdi32.lib,仅举一个例子,然后搜索CreateDIBSection
您会发现 a_CreateDIBSection@24
和__imp__CreateDIBSection@24
。
发生什么了?简单的 dumpbin 总是显示未修饰的名称,但编译器生成修饰的名称,结果:链接器失败。据说名称使用PASCAL
约定,与 相同__stdcall
,但不装饰符号(即阅读此https://msdn.microsoft.com/en-us/library/aa235591(v=vs.60).aspx)。
有办法解决问题吗?是的,您必须创建自己的导入库,为具有正确装饰的所需函数分配别名。开始阅读此https://msdn.microsoft.com/en-us/library/0b9xe492.aspx。
归档时间: |
|
查看次数: |
13581 次 |
最近记录: |