LInk到ntdll.lib并在ntdll.dll中调用函数

时间:2016-02-19 15:53:11

标签: c visual-studio dll window

我最近正在对私有API进行一些研究。我试图在运行时使用NtOpenFileLoadLibrary在ntdll.dll中调用GetProcAddress等函数。幸运的是,它成功了。今天早上我在计算机上执行了文件搜索,并在我的C盘中找到ntdll.lib。据我所知,这样的.lib文件应该包含可用于链接的dll导出的存根。所以,我试图将我的应用程序链接到该lib,但我经常遇到unresolved external symbol错误。但是,dumpbin /EXPORTS表明ntdll.lib显然已导出NtOpenFile。我怎么能解决这个错误?

2 个答案:

答案 0 :(得分:2)

问题是库中记录的函数名称以及编译器生成的函数名称 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
);

编译器将为32位以下的__stdcall函数生成符号_NtOpenFile@24,如果我没有错误计算调用参数的字节大小,那么显然不在库中。 这是因为ntdll.lib旨在在DDK下用于驱动程序开发,其中编译器生成未修饰的符号。
为了阐明概念,使用二进制编辑器打开ntdll.lib文件并查找NtOpenFile,您将只看到它和导入版本__imp_NtOpenFile。现在以gdi32.lib打开一个标准库,只需命名一个,然后搜索CreateDIBSection您会找到_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

答案 1 :(得分:0)

不再如此,我在2019年编写此文件时,便可以找到ntdll.lib导入库和NT标头。

使用 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”中,但是不幸的是,缺少了很多部分和/或仅是结构的简化版本等。 为了解决这个问题,您可以使用“ Process Hacker”项目中出色的NT标头集: https://github.com/processhacker/processhacker 标头位于“ phnt”中。

您将使用:

来代替典型的“ windows.h”和“ winternl.h”组合。
#include <phnt_windows.h>
#include <phnt.h>

然后以Windows 10作为目标(例如,默认为Windows 7)作为目标,您可以按照以下步骤操作:

#undef PHNT_VERSION
#define PHNT_VERSION PHNT_THRESHOLD 

请注意,“ 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