代码:
ULONG GetSSDTName() { KdBreakPoint(); if (KeGetCurrentIrql() > PASSIVE_LEVEL) { return STATUS_UNSUCCESSFUL; } //设置NTDLL路径 UNICODE_STRING uniFileName; RtlInitUnicodeString(&uniFileName, L"\\SystemRoot\\system32\\ntdll.dll"); //初始化打开文件的属性 OBJECT_ATTRIBUTES objectAttributes; InitializeObjectAttributes(&objectAttributes, &uniFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); 创建文件 NTSTATUS Status; HANDLE FileHandle; Status = IoCreateFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &objectAttributes, &ioStatus, 0, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING); if (!NT_SUCCESS(Status)) { DbgPrint("IoCreateFile failed!status:0x%08x\n", Status); return 0; } //获取文件信息 IO_STATUS_BLOCK ioStatus; FILE_STANDARD_INFORMATION FileInformation; Status = ZwQueryInformationFile(FileHandle, &ioStatus, &FileInformation, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation); if (!NT_SUCCESS(Status)) { DbgPrint("ZwQueryInformationFile failed!status:0x%08x\n", Status); ZwClose( FileHandle ); return 0; } //判断文件大小是否过大 if (FileInformation.EndOfFile.HighPart != 0) { DbgPrint("File Size Too High"); ZwClose(FileHandle); return 0; } //取文件大小 ULONG uFileSize = FileInformation.EndOfFile.LowPart; //分配内存 PVOID pBuffer = ExAllocatePoolWithTag(PagedPool, uFileSize, (ULONG)"NTDLL"); if (pBuffer == NULL) { DbgPrint("ExAllocatePoolWithTag() == NULL"); ZwClose(FileHandle); return 0; } //从头开始读取文件 LARGE_INTEGER byteOffset; byteOffset.LowPart = 0; byteOffset.HighPart = 0; Status = ZwReadFile(FileHandle, NULL, NULL, NULL, &ioStatus, pBuffer, uFileSize, &byteOffset, NULL); if (!NT_SUCCESS(Status)) { DbgPrint("ZwReadFile failed!status:0x%08x\n", Status); ZwClose(FileHandle); return 0; } //取出导出表 PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNtHeaders; PIMAGE_SECTION_HEADER pSectionHeader; ULONG FileOffset; PIMAGE_EXPORT_DIRECTORY pExportDirectory; //DLL内存数据转成DOS头结构 pDosHeader = (PIMAGE_DOS_HEADER)pBuffer; //取出PE头结构 pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG)pBuffer + pDosHeader->e_lfanew); //判断PE头导出表表是否为空 if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0) { DbgPrint("VirtualAddress == 0"); return 0; } //取出导出表偏移 FileOffset = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; //取出节头结构 pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeaders + sizeof(IMAGE_NT_HEADERS)); PIMAGE_SECTION_HEADER pOldSectionHeader = pSectionHeader; //遍历节结构进行地址运算 for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) { if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData) { FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData; } } //导出表地址 pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONG)pBuffer + FileOffset); //取出导出表函数地址 PULONG AddressOfFunctions; FileOffset = pExportDirectory->AddressOfFunctions; //遍历节结构进行地址运算 pSectionHeader = pOldSectionHeader; for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) { if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData) { FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData; } } AddressOfFunctions = (PULONG)((ULONG)pBuffer + FileOffset); //取出导出表函数名字 PUSHORT AddressOfNameOrdinals; FileOffset = pExportDirectory->AddressOfNameOrdinals; //遍历节结构进行地址运算 pSectionHeader = pOldSectionHeader; for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) { if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData) { FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData; } } AddressOfNameOrdinals = (PUSHORT)((ULONG)pBuffer + FileOffset); //取出导出表函数序号 PULONG AddressOfNames; FileOffset = pExportDirectory->AddressOfNames; //遍历节结构进行地址运算 pSectionHeader = pOldSectionHeader; for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) { if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData) { FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData; } } AddressOfNames = (PULONG)((ULONG)pBuffer + FileOffset); //分析导出表 ULONG uNameOffset; ULONG uOffset; LPSTR FunName; PVOID pFuncAddr; ULONG uServerIndex; ULONG uAddressOfNames; for (ULONG uIndex = 0; uIndex < pExportDirectory->NumberOfNames; uIndex++, AddressOfNames++, AddressOfNameOrdinals++) { uAddressOfNames = *AddressOfNames; pSectionHeader = pOldSectionHeader; for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) { if (pSectionHeader->VirtualAddress <= uAddressOfNames && uAddressOfNames <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData) { uOffset = uAddressOfNames - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData; } } FunName = (LPSTR)((ULONG)pBuffer + uOffset); if (FunName[0] == 'Z' && FunName[1] == 'w') { pSectionHeader = pOldSectionHeader; uOffset = (ULONG)AddressOfFunctions[*AddressOfNameOrdinals]; for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) { if (pSectionHeader->VirtualAddress <= uOffset&& uOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData) { uNameOffset = uOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData; } } pFuncAddr = (PVOID)((ULONG)pBuffer + uNameOffset); uServerIndex = *(PULONG)((ULONG)pFuncAddr + 1); FunName[0] = 'N'; FunName[1] = 't'; KdPrint(("函数名为: %s 序列号为:%d\n", FunName, uServerIndex)); } } ExFreePoolWithTag(pBuffer , (ULONG)"NTDLL"); ZwClose(FileHandle); return 1; }