驱动笔记:SSDT HOOK实现进程保护

驱动笔记:SSDT HOOK实现进程保护
2009-02-19 10:30:47  www.hackbase.com  来源:7747.net
  http://nokyo.blogbus.com/logs/35320995.html  SSDT HOOK已经是很老的技术了,但对新手来说还是有一些嚼头的。根据常规的做法,我们应该挂钩ZwTerminateProcess函数,不过这个函数仅有两个参数,其中一个 ...
  http://nokyo.blogbus.com/logs/35320995.html
  SSDT HOOK已经是很老的技术了,但对新手来说还是有一些嚼头的。根据常规的做法,我们应该挂钩ZwTerminateProcess函数,不过这个函数仅有两个参数,其中一个是进程句柄,它指定了需要被结束的进程。
  由于我们不能直接从进程句柄获取有关进程的一些信息,这就使得一些“懒惰”的家伙尝试找一些捷径。由于要想获得句柄通常都需要首先调用ZwOpenProcess,而ZwOpenProcess需要传递PID作为标识,于是有些人就不管ZwTerminateProcess函数了,改为挂钩ZwOpenProcess,这样你无法打开我们关注的进程,也就无法获得句柄,自然也就没办法结束我们的进程。
  乍一看,这还是真是一种思路巧妙的做法。不过,点心毕竟是不能当正餐吃的,这样的做法作为临时救火也没什么,要是一直抱着它不愿放弃就大错特错了。
  实际上,这种做法是有副作用的,比如通常在ring3使用PSAPI枚举进程时,我们经常使用下面的代码来获取进程完整路径:
  HANDLE hProcess = OpenProcess(
  PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
  FALSE,
  ProcessId[i]);
  if(hProcess)
  {
  EnumProcessModules(hProcess,&hModule,sizeof(hModule),&cbNeeded);
  GetModuleFileNameEx(hProcess,hModule,szPath,sizeof(szPath));
  // 输出到列表框
  }
  CloseHandle(hProcess);
  如果我们挂钩了ZwOpenProcess,那么使用这种方法枚举进程的程序就可能无法获得我们的保护进程信息。有人会说这样还不好?不要忘了,我们的目的不是隐藏,而是保护。自我保护是任何人都无可非议的做法,但尝试隐藏自身却会让人怀疑你的目的。
  其实说穿了,我们挂钩ZwOpenProcess的根本原因是不会使用句柄得到进程信息。好吧,我们现在就介绍如何通过进程句柄获取信息。
  在炉子的《API HOOK实现ring3的进程保护》一文中给出了一种解决方法,即使用NTDLL导出的Zw(Nt)QueryInformationProcess函数。
  下面我们看看这个函数的声明:
  NTSYSAPI
  NTSTATUS
  NTAPI
  NtQueryInformationProcess(
  IN HANDLE        ProcessHandle,
  IN PROCESSINFOCLASS  ProcessInformationClass,
  OUT PVOID          ProcessInformation,
  IN ULONG         ProcessInformationLength,
  OUT PULONG        ReturnLength );
  这个函数的关键是第二个参数,它决定了第三个参数输出什么结构。现在我们可以将其填写为ProcessBasicInformation,这样我们会获得一个PROCESS_BASIC_INFORMATION结构的信息输出。而PROCESS_BASIC_INFORMATION结构的UniqueProcessId子域即是该句柄代表的进程ID。
  下面是通过句柄获得PID的代码:
  ULONG lRet;
  PVOID pBuffer;
  PROCESS_BASIC_INFORMATION  *pbi;
  pBuffer = ExAllocatePool(PagedPool, sizeof(PROCESS_BASIC_INFORMATION));
  ZwQueryInformationProcess(ProcessHandle,
  ProcessBasicInformation,
  pBuffer,
  sizeof(PROCESS_BASIC_INFORMATION),
  &lRet);
  pbi = (struct _PROCESS_BASIC_INFORMATION *)pBuffer;
  KdPrint(("ProcessHandle代表进程%d!", pbi.UniqueProcessId));
  有了PID剩下的就好办了,我们可以使用函数PsLookupProcessByProcessId来获取该进程的EPROCESS结构,这个结构中就有进程名的信息。
  与之类似,文件句柄可以通过Zw(Nt)QueryInformationFile函数,注册表句柄可以通过Zw(Nt)QueryKey函数来获取有关信息。
  另外还有一种较为通用的方法,即使用ObReferenceObjectByHandle函数和ObQueryNameString函数配合使用。它可以通过进程句柄、文件句柄、注册表句柄获取完整的路径信息。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值