通过遍历导出表获取函数名和编号
- win10x64,win11测试可通用
#include <windows.h>
#include <stdio.h>
#include <ImageHlp.h>
#pragma comment(lib,"ImageHlp.lib")
typedef struct {
ULONG num;
PULONG64 addr;
PCHAR name;
}SSDT;
SSDT* ssdt = 0;
PVOID PeGetExport(PVOID ImageBase)
{
ULONG size = 0;
return ImageDirectoryEntryToData(ImageBase, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size);
}
VOID PeGetServiceTable(PCHAR dllname, PCHAR dllpath)
{
PLOADED_IMAGE image = ImageLoad(dllname, dllpath);
PVOID ImageBase = image->MappedAddress;
IMAGE_EXPORT_DIRECTORY* pExport = PeGetExport(image->MappedAddress);
PIMAGE_NT_HEADERS pNtHeader = ImageNtHeader(ImageBase);
PULONG offsetFunc = ImageRvaToVa(pNtHeader, ImageBase, pExport->AddressOfFunctions, NULL);
PULONG offsetName = ImageRvaToVa(pNtHeader, ImageBase, pExport->AddressOfNames, NULL);
PSHORT offsetOrd = ImageRvaToVa(pNtHeader, ImageBase, pExport->AddressOfNameOrdinals, NULL);
for (DWORD index = 0; index < pExport->NumberOfNames; index++)
{
PCHAR name = ImageRvaToVa(pNtHeader, ImageBase, offsetName[index], NULL);
PULONG addr = ImageRvaToVa(pNtHeader, ImageBase, offsetFunc[offsetOrd[index]], NULL);
if (addr && *addr == 0xB8D18B4C)
{
ULONG num = *(addr + 1);
ssdt[num].num = num;
ssdt[num].addr = (PULONG64)addr;
ssdt[num].name = name;
}
}
}
int main()
{
ssdt = calloc(0x2000, sizeof(SSDT));
PeGetServiceTable("ntdll.dll", "C:\\Windows\\System32\\");
PeGetServiceTable("win32u.dll", "C:\\Windows\\System32\\");
for (size_t i = 0; i < 0x2000; i++)
{
if (ssdt && ssdt[i].name)
{
printf("%04X,%I64X,%s\n", ssdt[i].num, (ULONG64)ssdt[i].addr, ssdt[i].name);
}
}
free(ssdt);
return 0;
}