能力值:
( LV3,RANK:20 )
|
-
-
2 楼
在32位内核中,可以使用KeServiceDescriptorTable 这个公开的变量得到SSDT 地址
|
能力值:
(RANK:50 )
|
-
-
3 楼
SSDT中并不直接带有函数名,如果SSDT中的函数未导出的话,并不能直接得到函数名。
需要根据服务号预先准备一张SSDT函数名表或者使用调试符号
|
能力值:
( LV5,RANK:70 )
|
-
-
4 楼
是的,SSDT中并不包含函数名。
|
能力值:
( LV7,RANK:110 )
|
-
-
5 楼
这个是可以的,我已经做出来了,提供一个思路给你,就是分析Ntdll.dll的Nt和Zw系列导出函数,它们上面的第二个指令就是mov eax,SSDT序列号,由这个指令可以得到序列号,再由Ntdll.dll的导出表得到对应函数的名字,这样就可以了
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
这样的话,该如何去分析呢
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
这样的话,该如何去加载NTDLL.DLL呢
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
ULONG GetSSDTName()
{
KdBreakPoint();
if (KeGetCurrentIrql() > PASSIVE_LEVEL)
{
return STATUS_UNSUCCESSFUL;
}
//设置NTDLL路径
UNICODE_STRING uniFileName;
RtlInitUnicodeString(&uniFileName, L"[URL="file://\\SystemRoot\\system32\\ntdll.dll"]\\SystemRoot\\system32\\ntdll.dll[/URL]");
//初始化打开文件的属性
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;
}
|
能力值:
( LV2,RANK:10 )
|
-
-
9 楼
楼上威武!感谢以上所有人!
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
好人多,呵呵呵
|