现在的位置: 首页 > 综合 > 正文

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

2013年09月19日 ⁄ 综合 ⁄ 共 5181字 ⁄ 字号 评论关闭

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;
}   

 

抱歉!评论已关闭.