我如何在我的代码中修复系统调用 Ntcreateprocess 原型的未定义符号?
How can i fix an undefined symbol for the system call Ntcreateprocess prototype in my code?
我想在 Windows 7 x86 VM 上实现 ssdt 挂钩,我遵循了本指南 link to guide。在我的代码中,我得到了 "undefined symbol" 的链接错误,它引用了我想要挂钩的系统调用函数。在这种情况下 "NtCreateProcess".
错误:LNK2019 未解析的外部符号 __imp__NtCreateProcess@32 在函数 _DriverEntry@8
中引用
LNK2001 未解析的外部符号 _NtCreateProcess@32
我认为 __declspec(dllimport)
告诉链接器忽略没有定义的事实,因为它在导入函数中
#include <ntddk.h>
/* The structure representing the System Service Table. */
typedef struct SystemServiceTable {
UINT32* ServiceTable;
UINT32* CounterTable;
UINT32 ServiceLimit;
UINT32* ArgumentTable;
} SST;
/* Declaration of KeServiceDescriptorTable, which is exported by ntoskrnl.exe. */
__declspec(dllimport) SST KeServiceDescriptorTable;
//Required information for hooking NtCreateProcess.
__declspec(dllimport) NTSTATUS NTAPI NtCreateProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL);
typedef NTSTATUS(*NtCreateProcessPrototype)(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL);
NtCreateProcessPrototype oldNtCreateProcess = NULL;
/*
* Disable the WP bit in CR0 register.
*/
void DisableWP() {
__asm {
push edx;
mov edx, cr0;
and edx, 0xFFFEFFFF;
mov cr0, edx;
pop edx;
}
}
/*
* Enable the WP bit in CR0 register.
*/
void EnableWP() {
__asm {
push edx;
mov edx, cr0;
or edx, 0x00010000;
mov cr0, edx;
pop edx;
}
}
/*
* A function that hooks the 'syscall' function in SSDT.
*/
PULONG HookSSDT(PUCHAR syscall, PUCHAR hookaddr) {
/* local variables */
UINT32 index;
PLONG ssdt;
PLONG target;
/* disable WP bit in CR0 to enable writing to SSDT */
DisableWP();
DbgPrint("The WP flag in CR0 has been disabled.\r\n");
/* identify the address of SSDT table */
ssdt = (PLONG)KeServiceDescriptorTable.ServiceTable;
DbgPrint("The system call address is %x.\r\n", syscall);
DbgPrint("The hook function address is %x.\r\n", hookaddr);
DbgPrint("The address of the SSDT is: %x.\r\n", ssdt);
/* identify 'syscall' index into the SSDT table */
index = *((PULONG)(syscall + 0x1));
DbgPrint("The index into the SSDT table is: %d.\r\n", index);
/* get the address of the service routine in SSDT */
target = (PLONG)&(ssdt[index]);
DbgPrint("The address of the SSDT routine to be hooked is: %x.\r\n", target);
/* hook the service routine in SSDT */
return (PULONG)InterlockedExchange(target, (LONG)hookaddr);
}
/*
* Hook Function.
*/
NTSTATUS Hook_NtCreateProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ParentProcess, IN BOOLEAN InheritObjectTable, IN HANDLE SectionHandle OPTIONAL, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL) {
/* local variables */
NTSTATUS status;
/* calling new instructions */
DbgPrint("NtCreateProcess hook called.\r\n");
/* calling old function */
status = oldNtCreateProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ParentProcess, InheritObjectTable, SectionHandle, DebugPort, ExceptionPort);
if (!NT_SUCCESS(status)) {
DbgPrint("The call to original ZwQuerySystemInformation did not succeed.\r\n");
}
return status;
}
/*
* DriverEntry: entry point for drivers.
*/
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
unsigned int uiIndex = 0;
PDEVICE_OBJECT pDeviceObject = NULL;
UNICODE_STRING usDriverName, usDosDeviceName;
DbgPrint("DriverEntry Called \r\n");
RtlInitUnicodeString(&usDriverName, L"\Device\MyDriver");
RtlInitUnicodeString(&usDosDeviceName, L"\DosDevices\MyDriver");
NtStatus = IoCreateDevice(pDriverObject, 0, &usDriverName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);
if (NtStatus == STATUS_SUCCESS) {
/* DriverUnload is required to be able to dynamically unload the driver. */
pDriverObject->DriverUnload = MyDriver_Unload;
pDeviceObject->Flags |= 0;
pDeviceObject->Flags &= (~DO_DEVICE_INITIALIZING);
/* Create a Symbolic Link to the device. MyDriver -> \Device\MyDriver */
IoCreateSymbolicLink(&usDosDeviceName, &usDriverName);
/* hook SSDT */
oldNtCreateProcess = (NtCreateProcessPrototype)HookSSDT((PUCHAR)NtCreateProcess, (PUCHAR)Hook_NtCreateProcess);//linking problem is here
}
return NtStatus;
}
I thought that __declspec(dllimport) tells the linker to ignore the fact that there is no definition because it's in an imported function
使用 __declspec(dllimport)
声明的函数仍然需要用于导入它们的 DLL 的 .lib 文件,如前所述 here:
Note that the users of your DLL still need to link with an import library.
换句话说,如果没有 ntdll.lib
,你就完蛋了,这意味着你无法构建调用 NtCreateProcess
或 [=13= 公开的任何其他函数的内核模式驱动程序].
我想在 Windows 7 x86 VM 上实现 ssdt 挂钩,我遵循了本指南 link to guide。在我的代码中,我得到了 "undefined symbol" 的链接错误,它引用了我想要挂钩的系统调用函数。在这种情况下 "NtCreateProcess".
错误:LNK2019 未解析的外部符号 __imp__NtCreateProcess@32 在函数 _DriverEntry@8
中引用LNK2001 未解析的外部符号 _NtCreateProcess@32
我认为 __declspec(dllimport)
告诉链接器忽略没有定义的事实,因为它在导入函数中
#include <ntddk.h>
/* The structure representing the System Service Table. */
typedef struct SystemServiceTable {
UINT32* ServiceTable;
UINT32* CounterTable;
UINT32 ServiceLimit;
UINT32* ArgumentTable;
} SST;
/* Declaration of KeServiceDescriptorTable, which is exported by ntoskrnl.exe. */
__declspec(dllimport) SST KeServiceDescriptorTable;
//Required information for hooking NtCreateProcess.
__declspec(dllimport) NTSTATUS NTAPI NtCreateProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL);
typedef NTSTATUS(*NtCreateProcessPrototype)(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL);
NtCreateProcessPrototype oldNtCreateProcess = NULL;
/*
* Disable the WP bit in CR0 register.
*/
void DisableWP() {
__asm {
push edx;
mov edx, cr0;
and edx, 0xFFFEFFFF;
mov cr0, edx;
pop edx;
}
}
/*
* Enable the WP bit in CR0 register.
*/
void EnableWP() {
__asm {
push edx;
mov edx, cr0;
or edx, 0x00010000;
mov cr0, edx;
pop edx;
}
}
/*
* A function that hooks the 'syscall' function in SSDT.
*/
PULONG HookSSDT(PUCHAR syscall, PUCHAR hookaddr) {
/* local variables */
UINT32 index;
PLONG ssdt;
PLONG target;
/* disable WP bit in CR0 to enable writing to SSDT */
DisableWP();
DbgPrint("The WP flag in CR0 has been disabled.\r\n");
/* identify the address of SSDT table */
ssdt = (PLONG)KeServiceDescriptorTable.ServiceTable;
DbgPrint("The system call address is %x.\r\n", syscall);
DbgPrint("The hook function address is %x.\r\n", hookaddr);
DbgPrint("The address of the SSDT is: %x.\r\n", ssdt);
/* identify 'syscall' index into the SSDT table */
index = *((PULONG)(syscall + 0x1));
DbgPrint("The index into the SSDT table is: %d.\r\n", index);
/* get the address of the service routine in SSDT */
target = (PLONG)&(ssdt[index]);
DbgPrint("The address of the SSDT routine to be hooked is: %x.\r\n", target);
/* hook the service routine in SSDT */
return (PULONG)InterlockedExchange(target, (LONG)hookaddr);
}
/*
* Hook Function.
*/
NTSTATUS Hook_NtCreateProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ParentProcess, IN BOOLEAN InheritObjectTable, IN HANDLE SectionHandle OPTIONAL, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL) {
/* local variables */
NTSTATUS status;
/* calling new instructions */
DbgPrint("NtCreateProcess hook called.\r\n");
/* calling old function */
status = oldNtCreateProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ParentProcess, InheritObjectTable, SectionHandle, DebugPort, ExceptionPort);
if (!NT_SUCCESS(status)) {
DbgPrint("The call to original ZwQuerySystemInformation did not succeed.\r\n");
}
return status;
}
/*
* DriverEntry: entry point for drivers.
*/
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
unsigned int uiIndex = 0;
PDEVICE_OBJECT pDeviceObject = NULL;
UNICODE_STRING usDriverName, usDosDeviceName;
DbgPrint("DriverEntry Called \r\n");
RtlInitUnicodeString(&usDriverName, L"\Device\MyDriver");
RtlInitUnicodeString(&usDosDeviceName, L"\DosDevices\MyDriver");
NtStatus = IoCreateDevice(pDriverObject, 0, &usDriverName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);
if (NtStatus == STATUS_SUCCESS) {
/* DriverUnload is required to be able to dynamically unload the driver. */
pDriverObject->DriverUnload = MyDriver_Unload;
pDeviceObject->Flags |= 0;
pDeviceObject->Flags &= (~DO_DEVICE_INITIALIZING);
/* Create a Symbolic Link to the device. MyDriver -> \Device\MyDriver */
IoCreateSymbolicLink(&usDosDeviceName, &usDriverName);
/* hook SSDT */
oldNtCreateProcess = (NtCreateProcessPrototype)HookSSDT((PUCHAR)NtCreateProcess, (PUCHAR)Hook_NtCreateProcess);//linking problem is here
}
return NtStatus;
}
I thought that __declspec(dllimport) tells the linker to ignore the fact that there is no definition because it's in an imported function
使用 __declspec(dllimport)
声明的函数仍然需要用于导入它们的 DLL 的 .lib 文件,如前所述 here:
Note that the users of your DLL still need to link with an import library.
换句话说,如果没有 ntdll.lib
,你就完蛋了,这意味着你无法构建调用 NtCreateProcess
或 [=13= 公开的任何其他函数的内核模式驱动程序].