Kernel下检测还原正确的SSDT

来源:互联网 发布:mysql my.ini文件下载 编辑:程序博客网 时间:2024/05/16 08:08
 
步骤说明:
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;
}
 
原创粉丝点击