Kernel下检测还原正确的SSDT

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;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值