Kernel下检测还原正确的SSDT
首先声明这个是菜鸟—我的学习日记,不是什么高深文章,高手们慎看.
都好久没写自己的博客了,玩游戏玩到好闷,突然想写一些东西.以前我见到www.rootkit.com上面有人写了怎么在ntkrnlpa.exe或ntoskrnl.exe搜索出正确的SSDT,不过他写的是在User Mode下进行的,那么我就想做到怎么在驱动中也能直接实现搜索正确SSDT.(已经有非常多人写出来了,不过我之前不会,现在逐渐明白,写出来是为了分享,我在网上找不到,可能我笨).
u 还原会造成卡巴等杀软主动防御失效,慎用!病毒除外!哈哈!
步骤说明:
1) 用NtQuerySystemInformation取得内核模块ntkrnlpa.exe或ntoskrnl.exe的基址KernelBase,获取内核模块的文件名称,到底是ntkrnlpa.exe还是ntoskrnl.exe.
2) 读取ntkrnlpa.exe或ntoskrnl.exe的映象基址ImageBase,和.Text节中虚拟偏移Virtual Offset,实际偏移Real Offset.
3) 从ntkrnlpa.exe或ntoskrnl.exe读出正确的SSDT: 正确SSDT在ntkrnlpa.exe或ntoskrnl.exe文件中偏移 = *(PULONG)KeServiceDescriptorTable - KernelBase – Virtual Offset + Real Offset.读取长度 = KeServiceDescriptorTable->NumberOfService * 4.
4) 这里读出的内容每4字节就是一个调用的地址,但这样读出的内容还不是SSDT. 计算出正确的SSDT: 每4个字节 - ImageBase + KernelBase.
5) 禁用中断 -> memcpy写SSDT -> 启用中断.
以下是代码了,需要用到我前篇文章写的IrpFile.h,去复制就OK啦.
//RestoreSSDT_Kernel.c/
#include "IrpFile.h"
#define SystemModuleInformation 11
typedef struct _SYSTEM_MODULE_INFORMATION
{
ULONG Reserved[2];
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
typedef struct
{
ULONG NumberOfModules;
SYSTEM_MODULE_INFORMATION smi;
} MODULES, *PMODULES;
NTSYSAPI
NTSTATUS
NTAPI
NtQuerySystemInformation(
IN ULONG SysInfoClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG RetLen
);
typedef struct _NEED_INFO
{
ULONG ImageBase;
UCHAR UseLess1[204];
ULONG VOffset;
ULONG UseLess2;
ULONG ROffset;
} NEED_INFO, *PNEED_INFO;
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
} SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
VOID InterruptEnable()
{
__asm
{
MOV EAX, CR0
OR EAX, 10000H
MOV CR0, EAX
STI
}
}
VOID InterruptDisable()
{
__asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H
MOV CR0, EAX
}
}
NTSTATUS RestoreServiceDescriptorTable()
{
NTSTATUS rc;
ULONG NeededSize;
PMODULES pModules;
ULONG KernelBase;
ULONG ActualLength;
HANDLE LinkHandle;
WCHAR NameBuffer[128];
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING LinkString, NameString;
PFILE_OBJECT FileObject;
ANSI_STRING AnsiImageName;
UNICODE_STRING UniImageName, UniModuleName;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER CurrentOffset;
ULONG Elfnew, Index, *Address;
NEED_INFO NeedInfo;
PVOID Buffer;
pModules = (PMODULES)&pModules;
rc = NtQuerySystemInformation(SystemModuleInformation, pModules, 4, &NeededSize);
if(rc == STATUS_INFO_LENGTH_MISMATCH)
{
pModules = (PMODULES)ExAllocatePool(PagedPool, NeededSize);
if(!pModules)
return STATUS_INSUFFICIENT_RESOURCES;
rc = NtQuerySystemInformation(SystemModuleInformation, pModules, NeededSize, NULL);
if(!NT_SUCCESS(rc))
{
ExFreePool(pModules);
return rc;
}
}
if(!NT_SUCCESS(rc))
{
return rc;
}
KernelBase = (ULONG)pModules->smi.Base;
LinkString.Buffer = NameBuffer;
LinkString.MaximumLength = sizeof(NameBuffer);
RtlZeroMemory(NameBuffer, sizeof(NameBuffer));
RtlInitUnicodeString(&NameString, L"//KnownDlls//KnownDllPath");
InitializeObjectAttributes(&ObjectAttributes, &NameString, OBJ_KERNEL_HANDLE, NULL, NULL);
ZwOpenSymbolicLinkObject(&LinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes);
ZwQuerySymbolicLinkObject(LinkHandle, &LinkString, &ActualLength);
ZwClose(LinkHandle);
RtlInitAnsiString(&AnsiImageName, pModules->smi.ImageName + pModules->smi.ModuleNameOffset - 1);
RtlAnsiStringToUnicodeString(&UniModuleName, &AnsiImageName, TRUE);
wcscat(NameBuffer, UniModuleName.Buffer);
RtlInitUnicodeString(&UniImageName, NameBuffer);
RtlFreeUnicodeString(&UniModuleName);
ExFreePool(pModules);
rc = IrpCreateFile(&FileObject, FILE_READ_ATTRIBUTES|SYNCHRONIZE, &UniImageName,
&IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if(NT_SUCCESS(rc))
{
CurrentOffset.QuadPart = 60;
rc = IrpReadFile(FileObject, &IoStatusBlock, &Elfnew, sizeof(ULONG), &CurrentOffset);
if(NT_SUCCESS(rc))
{
CurrentOffset.QuadPart = Elfnew + 52;
rc = IrpReadFile(FileObject, &IoStatusBlock, &NeedInfo, sizeof(NEED_INFO), &CurrentOffset);
if(NT_SUCCESS(rc))
{
Buffer = ExAllocatePoolWithTag(NonPagedPool, KeServiceDescriptorTable->NumberOfService * 4, 'TDSS');
if (!Buffer)
rc = STATUS_INSUFFICIENT_RESOURCES;
else
{
CurrentOffset.QuadPart = *(PULONG)KeServiceDescriptorTable - KernelBase - (NeedInfo.VOffset - NeedInfo.ROffset);
rc = IrpReadFile(FileObject, &IoStatusBlock, Buffer, KeServiceDescriptorTable->NumberOfService * 4, &CurrentOffset);
if(NT_SUCCESS(rc))
{
for(Index = 0;Index < KeServiceDescriptorTable->NumberOfService;Index++)
{
Address = (PULONG)Buffer + Index;
*Address = *Address - NeedInfo.ImageBase + KernelBase;
}
InterruptDisable();
memcpy((unsigned char *)KeServiceDescriptorTable->ServiceTableBase, Buffer, KeServiceDescriptorTable->NumberOfService * 4);
InterruptEnable();
}
ExFreePoolWithTag(Buffer, 'TDSS');
}
}
}
IrpClose(FileObject);
}
return rc;
}
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
RestoreServiceDescriptorTable();
return STATUS_UNSUCCESSFUL;
}