环境:VS2012+WIN8 64
类型:C++编写的WDM驱动程序
测试:VM WIN7
用途:主要用于驱动程序中得到WIN32 API地址,也可得到自定义的DLL中的函数导出地址,记录内核文件相关操作以便以后查看。
说明:此段代码来源于网络,经修改调试而成。
头文件 HelloWDM.h
- #if __cplusplus
- extern "C"
- {
- #endif
- #include <wdm.h>
- #include <windef.h>
- #ifdef __cplusplus
- }
- #endif
- //winnt.h中的定义 由于是WDM不能引用该文件 所以只有复制过来
- #define SEC_IMAGE 0x1000000
- //PE相关结构
- typedef struct _SECTION_IMAGE_INFORMATION
- {
- PVOID TransferAddress;
- ULONG ZeroBits;
- ULONG MaximumStackSize;
- ULONG CommittedStackSize;
- ULONG SubSystemType;
- union
- {
- struct
- {
- WORD SubSystemMinorVersion;
- WORD SubSystemMajorVersion;
- };
- ULONG SubSystemVersion;
- };
- ULONG GpValue;
- WORD ImageCharacteristics;
- WORD DllCharacteristics;
- WORD Machine;
- UCHAR ImageContainsCode;
- UCHAR ImageFlags;
- ULONG ComPlusNativeReady: 1;
- ULONG ComPlusILOnly: 1;
- ULONG ImageDynamicallyRelocated: 1;
- ULONG Reserved: 5;
- ULONG LoaderFlags;
- ULONG ImageFileSize;
- ULONG CheckSum;
- } SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;
- typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
- WORD e_magic; // Magic number
- WORD e_cblp; // Bytes on last page of file
- WORD e_cp; // Pages in file
- WORD e_crlc; // Relocations
- WORD e_cparhdr; // Size of header in paragraphs
- WORD e_minalloc; // Minimum extra paragraphs needed
- WORD e_maxalloc; // Maximum extra paragraphs needed
- WORD e_ss; // Initial (relative) SS value
- WORD e_sp; // Initial SP value
- WORD e_csum; // Checksum
- WORD e_ip; // Initial IP value
- WORD e_cs; // Initial (relative) CS value
- WORD e_lfarlc; // File address of relocation table
- WORD e_ovno; // Overlay number
- WORD e_res[4]; // Reserved words
- WORD e_oemid; // OEM identifier (for e_oeminfo)
- WORD e_oeminfo; // OEM information; e_oemid specific
- WORD e_res2[10]; // Reserved words
- LONG e_lfanew; // File address of new exe header
- } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
- typedef struct _IMAGE_DATA_DIRECTORY {
- DWORD VirtualAddress;
- DWORD Size;
- } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
- typedef struct _IMAGE_OPTIONAL_HEADER {
- //
- // Standard fields.
- //
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
- DWORD BaseOfData;
- //
- // NT additional fields.
- //
- DWORD ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Win32VersionValue;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- DWORD SizeOfStackReserve;
- DWORD SizeOfStackCommit;
- DWORD SizeOfHeapReserve;
- DWORD SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[16];
- } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
- typedef struct _IMAGE_EXPORT_DIRECTORY {
- DWORD Characteristics;
- DWORD TimeDateStamp;
- WORD MajorVersion;
- WORD MinorVersion;
- DWORD Name;
- DWORD Base;
- DWORD NumberOfFunctions;
- DWORD NumberOfNames;
- DWORD AddressOfFunctions; // RVA from base of image
- DWORD AddressOfNames; // RVA from base of image
- DWORD AddressOfNameOrdinals; // RVA from base of image
- } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
HelloWDM.cpp文件
- #include "HelloWDM.h"
- //得到DLL中的指定函数地址 相当于应用层的GetProcAddress函数
- DWORD GetDllFunctionAddress(PTSTR lpFunctionName, PTSTR pDllName)
- {
- HANDLE hThread, hSection, hFile, hMod;
- SIZE_T size=0;
- NTSTATUS status;
- PVOID BaseAddress = NULL;
- //转换DLL名称
- UNICODE_STRING strDllName;
- RtlInitUnicodeString(&strDllName, pDllName);
- OBJECT_ATTRIBUTES objectAttributes={0};
- IO_STATUS_BLOCK iosb={0};
- //初始化 objectAttributes
- InitializeObjectAttributes(&objectAttributes, &strDllName, OBJ_KERNEL_HANDLE, NULL, NULL);
- //打开文件
- status=ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &objectAttributes, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
- if(!NT_SUCCESS(status))
- {
- return status;
- }
- objectAttributes.ObjectName = 0;
- //创建内存块
- status=ZwCreateSection(&hSection, SECTION_ALL_ACCESS, &objectAttributes, 0, PAGE_READONLY, SEC_IMAGE, hFile); //PAGE_READONLY页面保护属性,必须结合SEC_IMAGE属性
- if(!NT_SUCCESS(status))
- {
- return status;
- }
- //内存映射文件
- status=ZwMapViewOfSection(hSection,
- ZwCurrentProcess(),
- &BaseAddress,
- 0,
- 1024,
- 0,
- &size,
- ViewUnmap,
- MEM_LARGE_PAGES, //针对DLL文件较小是可以用MEM_TOP_DOWN 文件较大比如USER32.DLL时需要用MEM_LARGE_PAGES
- PAGE_READWRITE);
- if(!NT_SUCCESS(status))
- {
- return status;
- }
- //关闭文件句柄
- ZwClose(hFile);
- //读取PE头信息
- IMAGE_DOS_HEADER* dosheader;
- IMAGE_OPTIONAL_HEADER* opthdr;
- IMAGE_EXPORT_DIRECTORY* pExportTable;
- PDWORD arrayOfFunctionAddresses, arrayOfFunctionNames;
- USHORT* arrayOfFunctionOrdinals;
- DWORD functionOrdinal, functionAddress=0;
- PSTR functionName;
- ANSI_STRING anFunName;
- UNICODE_STRING unFunctionName, unFunctionNameSearch;
- //模块句柄
- hMod = BaseAddress;
- //得到DOS头
- dosheader = (PIMAGE_DOS_HEADER)hMod;
- //得到PE选项头
- opthdr =(PIMAGE_OPTIONAL_HEADER) ((PBYTE)hMod+dosheader->e_lfanew+24);
- //得到导出表
- pExportTable =(PIMAGE_EXPORT_DIRECTORY)((PBYTE) hMod + opthdr->DataDirectory[0].VirtualAddress);
- //得到函数地址列表
- arrayOfFunctionAddresses = (PDWORD)( (PBYTE)hMod + pExportTable->AddressOfFunctions);
- //得到函数名称列表
- arrayOfFunctionNames = (PDWORD)( (PBYTE)hMod + pExportTable->AddressOfNames);
- //得到函数序号
- arrayOfFunctionOrdinals = (USHORT*)( (PBYTE)hMod + pExportTable->AddressOfNameOrdinals);
- //导出表基地址
- DWORD Base = pExportTable->Base;
- //转换函数名
- RtlInitUnicodeString(&unFunctionNameSearch, lpFunctionName);
- //循环导出表
- for(DWORD x = 0; x < pExportTable->NumberOfNames; x++) //导出函数有名称 编号之分,导出函数总数=名称导出+编号导出,这里是循环导出名称的函数
- {
- //得到函数名
- functionName = (PSTR)( (PBYTE)hMod + arrayOfFunctionNames[x]);
- //转化为ANSI_STRING
- RtlInitAnsiString(&anFunName, functionName);
- //转化为UNICODE_STRING
- RtlAnsiStringToUnicodeString(&unFunctionName, &anFunName, TRUE);
- //打印调试信息
- KdPrint(("%d/%d,FunName:%wZ\n", x+1, pExportTable->NumberOfNames, &unFunctionName));
- //比较函数名称
- if (RtlCompareUnicodeString(&unFunctionName, &unFunctionNameSearch, TRUE) == 0)
- {
- //得到该函数地址
- functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1;
- functionAddress = (DWORD)( (PBYTE)hMod + arrayOfFunctionAddresses[functionOrdinal]);
- break;
- }
- }
- ZwClose(hSection);
- return functionAddress;
- }
以上代码虽可以运行但没有考虑到 ZwMapViewOfSection的资源释放问题 修改如下:
- //HelloWDM.h
- #if __cplusplus
- extern "C"
- {
- #endif
- #include <wdm.h>
- #include <windef.h>
- #ifdef __cplusplus
- }
- #endif
- //定义设备扩展
- typedef struct _DEVICE_EXTERSION
- {
- PDEVICE_OBJECT fdo;
- PDEVICE_OBJECT NextStatckDevice;
- UNICODE_STRING ustrDeviceName; //设备名
- UNICODE_STRING ustrSymLinkName; //符号链接名
- PVOID tmpPoint; //记录临时指针
- }DEVICE_EXTENSION, *PDEVICE_EXTENSION;
- //全局变量
- PDEVICE_EXTENSION gDevExt=NULL;
- //winnt.h中的定义 由于是WDM不能引用该文件 所以只有复制过来
- #define SEC_IMAGE 0x1000000
- //PE相关结构
- typedef struct _SECTION_IMAGE_INFORMATION
- {
- PVOID TransferAddress;
- ULONG ZeroBits;
- ULONG MaximumStackSize;
- ULONG CommittedStackSize;
- ULONG SubSystemType;
- union
- {
- struct
- {
- WORD SubSystemMinorVersion;
- WORD SubSystemMajorVersion;
- };
- ULONG SubSystemVersion;
- };
- ULONG GpValue;
- WORD ImageCharacteristics;
- WORD DllCharacteristics;
- WORD Machine;
- UCHAR ImageContainsCode;
- UCHAR ImageFlags;
- ULONG ComPlusNativeReady: 1;
- ULONG ComPlusILOnly: 1;
- ULONG ImageDynamicallyRelocated: 1;
- ULONG Reserved: 5;
- ULONG LoaderFlags;
- ULONG ImageFileSize;
- ULONG CheckSum;
- } SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;
- typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
- WORD e_magic; // Magic number
- WORD e_cblp; // Bytes on last page of file
- WORD e_cp; // Pages in file
- WORD e_crlc; // Relocations
- WORD e_cparhdr; // Size of header in paragraphs
- WORD e_minalloc; // Minimum extra paragraphs needed
- WORD e_maxalloc; // Maximum extra paragraphs needed
- WORD e_ss; // Initial (relative) SS value
- WORD e_sp; // Initial SP value
- WORD e_csum; // Checksum
- WORD e_ip; // Initial IP value
- WORD e_cs; // Initial (relative) CS value
- WORD e_lfarlc; // File address of relocation table
- WORD e_ovno; // Overlay number
- WORD e_res[4]; // Reserved words
- WORD e_oemid; // OEM identifier (for e_oeminfo)
- WORD e_oeminfo; // OEM information; e_oemid specific
- WORD e_res2[10]; // Reserved words
- LONG e_lfanew; // File address of new exe header
- } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
- typedef struct _IMAGE_DATA_DIRECTORY {
- DWORD VirtualAddress;
- DWORD Size;
- } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
- typedef struct _IMAGE_OPTIONAL_HEADER {
- //
- // Standard fields.
- //
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
- DWORD BaseOfData;
- //
- // NT additional fields.
- //
- DWORD ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Win32VersionValue;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- DWORD SizeOfStackReserve;
- DWORD SizeOfStackCommit;
- DWORD SizeOfHeapReserve;
- DWORD SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[16];
- } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
- typedef struct _IMAGE_EXPORT_DIRECTORY {
- DWORD Characteristics;
- DWORD TimeDateStamp;
- WORD MajorVersion;
- WORD MinorVersion;
- DWORD Name;
- DWORD Base;
- DWORD NumberOfFunctions;
- DWORD NumberOfNames;
- DWORD AddressOfFunctions; // RVA from base of image
- DWORD AddressOfNames; // RVA from base of image
- DWORD AddressOfNameOrdinals; // RVA from base of image
- } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
- //HelloWDM.cpp
- //得到DLL中的指定函数地址 相当于应用层的GetProcAddress函数
- DWORD GetDllFunctionAddress(PTSTR lpFunctionName, PTSTR pDllName)
- {
- HANDLE hSection=NULL, hFile=NULL;
- SIZE_T size=0;
- NTSTATUS status;
- PVOID BaseAddress = NULL;
- //转换DLL名称
- UNICODE_STRING strDllName;
- RtlInitUnicodeString(&strDllName, pDllName);
- OBJECT_ATTRIBUTES objectAttributes={0};
- IO_STATUS_BLOCK iosb={0};
- //初始化 objectAttributes
- InitializeObjectAttributes(&objectAttributes, &strDllName, OBJ_KERNEL_HANDLE, NULL, NULL);
- __try
- {
- //打开文件
- status=ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &objectAttributes, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
- if(!NT_SUCCESS(status))
- {
- __leave;
- }
- objectAttributes.ObjectName = 0;
- //创建内存块
- status=ZwCreateSection(&hSection, SECTION_ALL_ACCESS, &objectAttributes, 0, PAGE_READONLY, SEC_IMAGE, hFile); //PAGE_READONLY页面保护属性,必须结合SEC_IMAGE属性
- if(!NT_SUCCESS(status))
- {
- __leave;
- }
- //内存映射文件
- status=ZwMapViewOfSection(hSection,
- ZwCurrentProcess(),
- &BaseAddress,
- 0,
- 1024,
- 0,
- &size,
- ViewUnmap,
- MEM_LARGE_PAGES, //针对DLL文件较小是可以用MEM_TOP_DOWN 文件较大比如USER32.DLL时需要用MEM_LARGE_PAGES
- PAGE_READWRITE);
- }
- __finally
- {
- if(hFile != NULL)
- {
- //关闭文件句柄
- ZwClose(hFile);
- }
- if(!NT_SUCCESS(status) && hSection != NULL)
- {
- //关闭内存块
- ZwClose(hSection);
- }
- }
- //如果失败 直接返回
- if(!NT_SUCCESS(status))
- {
- return 0;
- }
- //读取PE头信息
- IMAGE_DOS_HEADER* dosheader;
- IMAGE_OPTIONAL_HEADER* opthdr;
- IMAGE_EXPORT_DIRECTORY* pExportTable;
- PDWORD arrayOfFunctionAddresses, arrayOfFunctionNames;
- USHORT* arrayOfFunctionOrdinals;
- DWORD functionOrdinal, functionAddress=0;
- PSTR functionName;
- ANSI_STRING anFunName;
- UNICODE_STRING unFunctionName, unFunctionNameSearch;
- //模块句柄
- HANDLE hMod = BaseAddress;
- //得到DOS头
- dosheader = (PIMAGE_DOS_HEADER)hMod;
- //得到PE选项头
- opthdr =(PIMAGE_OPTIONAL_HEADER) ((PBYTE)hMod+dosheader->e_lfanew+24);
- //得到导出表
- pExportTable =(PIMAGE_EXPORT_DIRECTORY)((PBYTE) hMod + opthdr->DataDirectory[0].VirtualAddress);
- //得到函数地址列表
- arrayOfFunctionAddresses = (PDWORD)( (PBYTE)hMod + pExportTable->AddressOfFunctions);
- //得到函数名称列表
- arrayOfFunctionNames = (PDWORD)( (PBYTE)hMod + pExportTable->AddressOfNames);
- //得到函数序号
- arrayOfFunctionOrdinals = (USHORT*)( (PBYTE)hMod + pExportTable->AddressOfNameOrdinals);
- //导出表基地址
- DWORD Base = pExportTable->Base;
- //转换函数名
- RtlInitUnicodeString(&unFunctionNameSearch, lpFunctionName);
- //循环导出表
- for(DWORD x = 0; x < pExportTable->NumberOfNames; x++) //导出函数有名称 编号之分,导出函数总数=名称导出+编号导出,这里是循环导出名称的函数
- {
- //得到函数名
- functionName = (PSTR)( (PBYTE)hMod + arrayOfFunctionNames[x]);
- //转化为ANSI_STRING
- RtlInitAnsiString(&anFunName, functionName);
- //转化为UNICODE_STRING
- RtlAnsiStringToUnicodeString(&unFunctionName, &anFunName, TRUE);
- //打印调试信息
- KdPrint(("%d/%d,FunName:%wZ\n", x+1, pExportTable->NumberOfNames, &unFunctionName));
- //比较函数名称
- if (RtlCompareUnicodeString(&unFunctionName, &unFunctionNameSearch, TRUE) == 0)
- {
- //得到该函数地址
- functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1;
- functionAddress = (DWORD)( (PBYTE)hMod + arrayOfFunctionAddresses[functionOrdinal]);
- break;
- }
- }
- //这里释放资源返回的地址将无效 所以先存放起来
- //ZwUnmapViewOfSection (NtCurrentProcess(), BaseAddress);
- gDevExt->tmpPoint=BaseAddress;
- ZwClose(hSection);
- return functionAddress;
- }
调用代码如下:
- ULONG ulOriginalProcAddr=GetDllFunctionAddress(TEXT("NtOpenProcess"), TEXT("\\SystemRoot\\system32\\ntdll.dll"));
- //释放GetDllFunctionAddress的内存块
- if(gDevExt->tmpPoint!=0)
- {
- ZwUnmapViewOfSection (NtCurrentProcess(), gDevExt->tmpPoint);
- gDevExt->tmpPoint=0;
- }