您的位置:首页 > 编程语言

使用ZwSystemDebugControl的简易用户模式Rootkit检测器代码

2008-03-22 15:27 701 查看
NTSTATUS
ReadKernelMemory(IN PVOID BaseAddress,
OUT PVOID Buffer,
IN ULONG Length)
{
NTSTATUS Status;
SYSDBG_VIRTUAL DbgMemory;

//
// Setup the request
//
DbgMemory.Address = BaseAddress;
DbgMemory.Buffer = Buffer;
DbgMemory.Request = Length;

//
// Do the read
//
Status = NtSystemDebugControl(SysDbgReadVirtual,
&DbgMemory,
sizeof(DbgMemory),
NULL,
0,
NULL);
return Status;
}

PCHAR
FindDriverForAddress(IN PVOID Pointer)
{
NTSTATUS Status;
PRTL_PROCESS_MODULES ModuleInfo;
PRTL_PROCESS_MODULE_INFORMATION ModuleEntry;
ULONG ReturnedLength;
ULONG i;

//
// Figure out how much size we need
//
Status = NtQuerySystemInformation(SystemModuleInformation,
NULL,
0,
&ReturnedLength);
if (Status != STATUS_INFO_LENGTH_MISMATCH) return NULL;

//
// Allocate a buffer large enough
//
ModuleInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, ReturnedLength);
if (!ModuleInfo) return NULL;

//
// Now query the data again
//
Status = NtQuerySystemInformation(SystemModuleInformation,
ModuleInfo,
ReturnedLength,
&ReturnedLength);
if (!NT_SUCCESS(Status)) return NULL;

//
// Loop all the drivers
//
for (i = 0; i < ModuleInfo->NumberOfModules; i++)
{
//
// Get the current entry and check if the pointer is within it
//
ModuleEntry = &ModuleInfo->Modules[i];
if ((Pointer > ModuleEntry->ImageBase) &&
(Pointer < ((PVOID)((ULONG_PTR)ModuleEntry->ImageBase +
ModuleEntry->ImageSize))))
{
//
// Found a match, return it
//
return ModuleEntry->FullPathName;
}
}
}

PCHAR
DetectDriver(VOID)
{
BOOLEAN Old;
NTSTATUS Status;
ULONG_PTR MappedAddress;
PVOID KernelBase, TableBase;
UNICODE_STRING KernelName;
ANSI_STRING TableName = RTL_CONSTANT_STRING("KeServiceDescriptorTable");
RTL_PROCESS_MODULES ModuleInfo;
ULONG Flags;
KSERVICE_TABLE_DESCRIPTOR ServiceTable;

//
// Give our thread the debug privilege
//
Status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &Old);
if (!NT_SUCCESS(Status)) return NULL;

//
// Query the kernel's module entry
//
Status = NtQuerySystemInformation(SystemModuleInformation,
&ModuleInfo,
sizeof(ModuleInfo),
NULL);
if (Status != STATUS_INFO_LENGTH_MISMATCH) return NULL;

//
// Initialize the kernel's full path name
//
Status = RtlCreateUnicodeStringFromAsciiz(&KernelName,
ModuleInfo.Modules[0].FullPathName);
if (!Status) return NULL;

//
// Keep only the short name
//
KernelName.Buffer = KernelName.Buffer +
(KernelName.Length / sizeof(WCHAR)) -
12;

//
// Map the kernel
//
Flags = IMAGE_FILE_EXECUTABLE_IMAGE;
Status = LdrLoadDll(NULL, &Flags, &KernelName, &KernelBase);
if (!NT_SUCCESS(Status)) return NULL;

//
// Find the address of KeServiceDescriptorTable
//
Status = LdrGetProcedureAddress(KernelBase, &TableName, 0, &TableBase);
if (!NT_SUCCESS(Status)) return NULL;

//
// Unload the kernel image, we're done with it
//
Status = LdrUnloadDll(KernelBase);
if (!NT_SUCCESS(Status)) return NULL;

//
// Get the virtual address we need
//
MappedAddress = (ULONG_PTR)ModuleInfo.Modules[0].ImageBase;
MappedAddress -= (ULONG_PTR)KernelBase;
MappedAddress += (ULONG_PTR)TableBase;

//
// Now read the SSDT
//
Status = ReadKernelMemory((PVOID)MappedAddress,
&ServiceTable,
sizeof(ServiceTable));
if (!NT_SUCCESS(Status)) return NULL;

//
// Setup the argument table
//
ArgumentTable = RtlAllocateHeap(RtlGetProcessHeap(),
0,
ServiceTable.Limit * sizeof(ULONG_PTR));
if (!ArgumentTable) return NULL;

//
// Now fill it up
//
Status = ReadKernelMemory(ServiceTable.Base,
ArgumentTable,
ServiceTable.Limit * sizeof(ULONG_PTR));
if (!NT_SUCCESS(Status)) return NULL;

//
// Now scan it
//
for (i = 0; i < ServiceTable.Limit; i++)
{
//
// Make sure no pointer is outside the kernel area
//
if (ArgumentTable[i] > 0x8FFFFFFF)
{
//
// Find the driver file that this belongs to
//
return FindDriverForAddress(UlongToPtr(ArgumentTable[i]));
}
}

//
// If we got here, then you don't have any rootkit
//
return NULL;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐