Kernel下检测还原正确的SSDT

来源:互联网 发布:聊天记录查询软件 编辑:程序博客网 时间:2024/05/16 05:11

Kernel下检测还原正确的SSDT 

首先声明这个是菜鸟我的学习日记,不是什么高深文章,高手们慎看.

都好久没写自己的博客了,玩游戏玩到好闷,突然想写一些东西.以前我见到www.rootkit.com上面有人写了怎么在ntkrnlpa.exentoskrnl.exe搜索出正确的SSDT,不过他写的是在User Mode下进行的,那么我就想做到怎么在驱动中也能直接实现搜索正确SSDT.(已经有非常多人写出来了,不过我之前不会,现在逐渐明白,写出来是为了分享,我在网上找不到,可能我笨).

u       还原会造成卡巴等杀软主动防御失效,慎用!病毒除外!哈哈!

 

步骤说明:

1)        NtQuerySystemInformation取得内核模块ntkrnlpa.exentoskrnl.exe的基址KernelBase,获取内核模块的文件名称,到底是ntkrnlpa.exe还是ntoskrnl.exe.

2)        读取ntkrnlpa.exentoskrnl.exe的映象基址ImageBase,.Text节中虚拟偏移Virtual Offset,实际偏移Real Offset.

3)        ntkrnlpa.exentoskrnl.exe读出正确的SSDT: 正确SSDTntkrnlpa.exentoskrnl.exe文件中偏移 = *(PULONG)KeServiceDescriptorTable - KernelBase Virtual Offset + Real Offset.读取长度 = KeServiceDescriptorTable->NumberOfService * 4.

4)        这里读出的内容每4字节就是一个调用的地址,但这样读出的内容还不是SSDT. 计算出正确的SSDT: 4个字节 - ImageBase + KernelBase.

5)        禁用中断 -> memcpySSDT -> 启用中断.

以下是代码了,需要用到我前篇文章写的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;

}

 

原创粉丝点击