[学习记录] 32位程序调用64位API NtQuerySystemInformation 遍历内核模块
“main.cpp”
调用API
#include <iostream>
#include <Windows.h>
#include <Psapi.h>
#define EMIT(a) __asm __emit (a)
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
typedef struct _RTL_PROCESS_MODULE_INFORMATION
{
HANDLE Section;
uint64_t MappedBase;
uint64_t ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;
typedef struct _RTL_PROCESS_MODULES
{
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;
constexpr auto STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
NTSTATUS NtQuerySystemInformation_x64(DWORD SystemInformationClass, __int64 SystemInformation, DWORD Length,PULONG ReturnLength)
{
DWORD Savefs = 0;
DWORD ssdt = 0x36;
__asm {
// 保存fs
EMIT(0x8C) EMIT(0x65) EMIT(0xFC)
EMIT(0xB8) EMIT(0x2B) EMIT(0x00) EMIT(0x00) EMIT(0x00)
EMIT(0x66) EMIT(0x8E) EMIT(0xE0)
EMIT(0x83) EMIT(0xE4) EMIT(0xF0)
}
__asm {
// 进入X64环境
push 0x33
call Label1
Label1 :
add dword ptr[esp], 5
EMIT(0xCB)
}
__asm {
// Call函数
EMIT(0x67) EMIT(0x8B) EMIT(0x4D) EMIT(0x08)
EMIT(0x67) EMIT(0x48) EMIT(0x8B) EMIT(0x55) EMIT(0x0C)
EMIT(0x67) EMIT(0x44) EMIT(0x8B) EMIT(0x45) EMIT(0x14)
EMIT(0x67) EMIT(0x44) EMIT(0x8B) EMIT(0x4D) EMIT(0x18)
EMIT(0x49) EMIT(0x89) EMIT(0xCA)
EMIT(0x67) EMIT(0x8B) EMIT(0x45) EMIT(0xF8)
EMIT(0x0F) EMIT(0x05)
}
__asm {
// 退出X64环境
Call Label2
Label2 :
mov dword ptr[esp + 0x4], 0x23
add dword ptr[esp], 0xD
EMIT(0xCB)
}
__asm {
//还原FS
EMIT(0x66) EMIT(0x8C) EMIT(0xD9)
EMIT(0x66) EMIT(0x8E) EMIT(0xD1)
EMIT(0x8B) EMIT(0x4D) EMIT(0xFC)
EMIT(0x66) EMIT(0x8E) EMIT(0xE1)
}
__asm {
EMIT(0x89) EMIT(0xEC)
EMIT(0x5D)
EMIT(0xC2) EMIT(0x14) EMIT(0x00)
}
return 0;
}
遍历模块
int main()
{
ULONG buffer_size;
uint64_t buffer = 0;
NTSTATUS status = NtQuerySystemInformation_x64(11, 0, 0, &buffer_size);
while (status == STATUS_INFO_LENGTH_MISMATCH) {
if (buffer != 0)
VirtualFree((void*)buffer, 0, MEM_RELEASE);
buffer = (uint64_t)VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
status = NtQuerySystemInformation_x64(11, buffer, buffer_size, &buffer_size);
}
if (!NT_SUCCESS(status)) {
if (buffer != 0)
VirtualFree((void*)buffer, 0, MEM_RELEASE);
return 0;
}
const auto modules = static_cast<PRTL_PROCESS_MODULES>((void*)buffer);
if (!modules)
return 0;
for (auto i = 0; i < modules->NumberOfModules; ++i) {
const std::string current_module_name = std::string(reinterpret_cast<char*>(modules->Modules[i].FullPathName) + modules->Modules[i].OffsetToFileName);
printf("ModuleName %s ImageBase %llX size %X \n", current_module_name.c_str(), modules->Modules[i].ImageBase, modules->Modules[i].ImageSize);
}
VirtualFree((void*)buffer, 0, MEM_RELEASE);
}
下面是运行结果
纯粹记录一下,免得日后记不住。