65.9K
CodeProject 正在变化。 阅读更多。
Home

拦截 WinAPI 调用

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (28投票s)

2006年3月6日

3分钟阅读

viewsIcon

155299

downloadIcon

3757

一篇关于截取 WinAPI 调用的文章。

引言

API 调用截取是一项允许访问其他程序某些部分的任务。许多程序员花费时间开发和描述各种允许访问的方法。这种方法被用于许多反病毒和反间谍软件中。此外,有时,截取可以帮助您找到应用程序中的错误。然而,一些病毒也在使用它,这已不是什么秘密。我花了很多时间来寻找和理解截取技术。我想在这里描述我的研究结果。

方法描述

首先,您需要阅读以下文章以了解截取机制的基础知识:HookSys(由 Ivo Ivanov 撰写)。它对我有很大的帮助,并且我使用了其中的示例代码。但是,它并没有解决我的所有问题,因为 Ivo 的示例有时会遗漏非常重要的 API 调用。当应用程序启动太快并且截取服务没有时间注入 DLL 时,就会发生这种情况。经过一些研究,我发现了实际问题,它与使用内核模式函数 SetCreateProcessNotificationRoutine 相关。此函数用于接收有关任何新进程创建的通知事件。当进程已经启动时,通常会触发此类通知。因此,我需要找到一种方法来改进 Ivo 的代码。

据我所知,所有 Windows 进程的执行都包含以下步骤

  • 初始进程加载;
  • 以暂停状态为进程创建主线程;
  • NT.DLL 映射到进程的地址空间中;
  • 映射所有需要的 DLL,并使用 DLL_PROCESS_ATTACH 原因调用它们的 DllMain
  • 恢复主进程的线程。

在恢复主线程之前的步骤看起来最适合注入,因为进程处于暂停状态并且尚未执行任何指令。

进程创建的大部分工作都在内核模式下完成,因此要更改此算法,您需要截取内核模式函数 NtCreateProcess()NtCreateThread()。传递给函数 NtCreateThread()CONTEXT 结构包含一个名为 EAX 的成员。我发现它等于用户模式下进程的起始地址,因此如果您可以更改它,那么您可以在进程创建之后和启动之前获得控制权。为了解决这个任务,我编写了一个内核模式驱动程序。它在系统启动时启动。

有一些初始化步骤

  1. 启动;
  2. 从用户模式接收配置;
  3. 截取内核模式函数,例如:NtCreateProcess()NtCreateThread()NtTerminateProcess()NewNtCreateProcessEx() - 适用于 Windows 2003 Server。

NtCreateThread() 函数的处理程序包含将完成大部分有趣工作的代码。这是其算法的简要描述

  1. 通过调用 ObReferenceObjectByHandle() 允许访问正在创建的进程;
  2. 记住主线程的起始地址 (ThreadContext->EAX);
  3. 通过调用 KeAttachProcess() "跳转"到正在创建的进程的上下文中;
  4. 通过调用 ZwAllocateVirtualMemory() 为我的代码分配内存,类似于用户模式下 CreateRemoteThread() 的众所周知的技术;
  5. 将小代码复制到将加载我的 DLL 的已分配内存中。这段代码看起来像
    push pszDllName
    mov  ebx, LoadLibraryAddr
    call [ebx]
    mov  eax, Win32StartAddr
    push eax
    ret
    pszDllName: db 'example.dll';
  6. "跳转"到初始进程;
  7. 更改线程起始地址 (ThreadContext->EAX) 以使其指向已分配的内存。

就是这样。您可以下载并编译本文的完整源代码。注意:该示例功能齐全,并且足以进行基本理解,但对于实际使用,可能需要重写它。

编译代码

您需要在计算机上安装 NTDDK。我使用 MSVS 6.0 来编译 NtProcDrv,并使用 MSVS 7.1 来编译其余项目。

历史

  • 2006-03-06 - 提交。
  • 2006-05-31 - 源代码和二进制文件已更新。
© . All rights reserved.