看流星社区

 找回密码
 注册账号
查看: 2254|回复: 0

SSDT HOOK NtWriteVirtualMemory阻止内存修改

[复制链接]

该用户从未签到

发表于 2013-5-6 08:48:48 | 显示全部楼层 |阅读模式
依据10年的进程保护修改的,也是一个经典的SSDT HOOK. 模仿商业保护阻止其他软件修改内存。
在内核中HOOK  NtWriteVirtualMemory函数,这样用户层的那些内存修改器就无法修改内存了。
以下以保护进程 Form1.exe为例 在 win7 32 位系统下测试通过。
注意 我这里获取函数地址用的是函数序号来获取的,函数序号 在win7和xp 系统里面是不同的。
NtWriteVirtualMemory函数 在win7 32 位系统里面的序号为399,用xuetr点击驱动层钩子 SSDT 即可发现。
在xp 系统里面不是 399.所以大家如果要使用以下源码,必须注意修改小这个 函数序号。
#include <ntddk.h>
typedef struct _SystemServiceDescriptorTable
{
    PVOID    ServiceTableBase; //SSDT表的基地址
    PULONG    ServiceCounterTableBase; //指向另一个索引表,该表包含了每个服务表项被调用的次数
    ULONG    NumberOfService; //当前系统所支持的服务个数
    ULONG    ParamTableBase; //包含了每个服务所需的参数字节数
}SystemServiceDescriptorTable,*PSystemServiceDescriptorTable;
extern PSystemServiceDescriptorTable KeServiceDescriptorTable; //导出函数,DDK的头文件中并未声明
//内核函数声明
typedef NTSTATUS  (*NtWRITEVIRTUALMEMORY)(
                                                                             IN HANDLE ProcessHandle,
                                   IN PVOID BaseAddress,
                                   IN PVOID Buffer,
                                   IN ULONG BufferLength,
                                   OUT PULONG ReturnLength OPTIONAL);
//定义一个内核函数的数据类型
NtWRITEVIRTUALMEMORY pRealAddr;//用 NtWRITEVIRTUALMEMORY 定义 一个  真的 函数类型

ULONG RealServiceAddress;          //接受被hook的函数地址
CHAR *TerminateName = "Form1.exe";  //这里就是我们的进程名。

UCHAR* PsGetProcessImageFileName( IN PEPROCESS Process );  

BOOLEAN IsProtect(CHAR *temp) //判断正在结束的进程是否是我们要保护的魔兽进程
{
  ULONG len = strcmp(TerminateName, temp);
  if(!len)
    return TRUE;
  return FALSE;
}

NTSTATUS MyNtWriteVirtualMemory(IN HANDLE ProcessHandle,IN PVOID BaseAddress,IN PVOID  Buffer,IN ULONG BufferLength,OUT PULONG ReturnLength OPTIONAL)

{
  PEPROCESS process; //接受通过ProcessHandle返回的进程
  NTSTATUS status;  
  CHAR *pName;  //接受进程的进程名

  status = ObReferenceObjectByHandle(ProcessHandle, FILE_READ_DATA,0, KernelMode,&process,NULL); //获取进程
  if(!NT_SUCCESS(status))  
       return (NTSTATUS)(NtWRITEVIRTUALMEMORY)pRealAddr(ProcessHandle, BaseAddress,Buffer,BufferLength,ReturnLength);
   pName = (CHAR*)PsGetProcessImageFileName(process); //获取进程名
  if(IsProtect(pName)) //判断是否是我们要保护的进程,是则返回权限不足,不能修改内存,否则调用原函数
       return STATUS_ACCESS_DENIED;
  return (NTSTATUS)(NtWRITEVIRTUALMEMORY)pRealAddr(ProcessHandle, BaseAddress,Buffer,BufferLength,ReturnLength);
}

NTSTATUS Hook()
{
  ULONG Address;
  Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 399 * 4;//399是函数序号,可用xuetr查看。这个399是win7 32 系统里面的。XP系统不是399,自己查
  RealServiceAddress = *(ULONG*)Address;  
  pRealAddr = (NtWRITEVIRTUALMEMORY)RealServiceAddress;
  //开启SSDT 表为可写
  _asm
  {
    cli;
    mov  eax, cr0;
    and eax, not 10000h;
    mov  cr0, eax;
  }

  *((ULONG*)Address) = (ULONG)MyNtWriteVirtualMemory;  //替换为我们自己的MyNtWriteVirtualMemory 函数
    DbgPrint("完成HOOK内核函数");
  //设置SSDT表位只读
  _asm
  {
    mov  eax, cr0;
    or  eax, 10000h;
    mov  cr0, eax;
    sti;  
  }

}
VOID UnHook()//把SSDT中的NtTerminateprocess函数还原
{
  ULONG Address;

  Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 399 * 4;//399是函数序号,可用xuetr查看。这个399是win7 32 系统里面的。XP系统不是399,自己查
  __asm
     {
       cli
       mov    eax, cr0;
       and    eax, not 10000h ;
       mov    cr0, eax ;
     }

     *((ULONG*)Address) = (ULONG)RealServiceAddress;

  __asm
     {
       mov    eax, cr0 ;
       or   eax, 10000h ;
       mov    cr0, eax ;
       sti ;
     }
}


VOID Unload(PDRIVER_OBJECT driver)
{
  UNREFERENCED_PARAMETER(driver);
  UnHook();

  DbgPrint("卸载驱动完成...");


}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING str)
{
  NTSTATUS status;
  UNREFERENCED_PARAMETER(str);
  driver->DriverUnload = Unload;
   DbgPrint("驱动加载完成");
  status = Hook();
  return STATUS_SUCCESS;
}
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-5-15 06:03

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表