Windows XP教程
  • Windows 2000教程
  • Windows 2003教程 Windows vista教程 Win 7教程 Win 8教程 linux教程 unix教程 windows 2008教程
    当前位置:教程网 > 操作系统 > Windows 2000教程 > 正文

    《Undocumented Windows 2000 Secrets》翻译 --- 第五章(2)

    编辑:教程网 来源:网络 时间:2011年11月07日 16:45

    第五章 监控 Native API 调用

    翻译: Kendiv( fcczj@263.net )

    更新: Thursday, February 24, 2005

    声明:转载请注明出处,并保证文章的完整性,本人保留译文的所有权利。

    汇编语言的救援行动

    通用解决方案的主要障碍是 C 语言的典型参数传递机制。就像你知道的, C 通常在调用函数的入口点之前会将函数参数传递到 CPU 堆栈中。根据函数需要的参数数量,参数堆栈的大小将有很大的差别。 Windows 2000 的 248 个 Native API 函数需要的参数堆栈的大小位于 0 到 68 字节。这使得编写一个唯一的 hook 函数变得非常困难。微软的 Visual C/C++ 提供了一个完整的汇编( ASM )编译器,该编译器可处理复杂度适中的代码。具有讽刺意味的是,在我的解决方案中所使用的汇编语言的优点正是通常被认为是其最大缺点的特性:汇编语言不提供严格的类型检查机制。只要字节数正确就一切 OK 了,你可以在任何寄存器中存储几乎所有的东西,而且你可以调用任何地址,而不需要关心当前堆栈的内容是什么。尽管这在应用程序开发中是一种很危险的特性,但这确实最容易获取的:在汇编语言中,很容易以不同的参数堆栈调用同一个普通的入口点,稍后将介绍的 API hook Dispatcher 将采用这一特性。

    通过将汇编代码放入以关键字 __asm 标记的分隔块中就可调用 Microsoft Visual C/C++ 嵌入式汇编程序。嵌入式汇编缺少宏定义以及 Microsoft's big Macro Assembler ( MASM )的评估能力,但这些并没有严重的限制它的可用性。嵌入式汇编的最佳特性是:它可以访问所有的 C 变量和类型定义,因此很容易混合 C 和 ASM 代码。不过,当在 C 函数中包含有 ASM 代码时,就必须遵守 C 编译器的某些重要的基本约定,以避免和 C 代码的冲突:

    l C 函数调用者假定 CPU 寄存器 EBP 、 EBX 、 ESI 和 EDI 已经被保存了。

    l 如果在单一函数中,将 ASM 代码和 C 代码混合在一起,则需要小心的保存 C 代码可能保存在寄存器中的中间值。总是保存和恢复在 __asm 语句中使用的所有寄存器。

    l 8 位的函数结果( CHAR , BYTE 等)由寄存器 AL 返回。

    l 16 位的函数结果( SHORT , Word 等)由寄存器 AX 返回。

    l 32 位的函数结果( INT , LONG , DWORD 等)由寄存器 EAX 返回。

    l 64 位的函数结果( __int64 , LONGLONG , DWORDLONG 等)由寄存器对 EDX : EAX 返回。寄存器 EAX 包含 0 到 31 位, EDX 保存 32 到 63 位。

    l 有确定参数的函数通常按照 __stdcall 约定进行参数的传递。从调用者的角度来看,这意味着在函数调用之前参数必须以相反的顺序压入堆栈中,被调用的函数负责在返回前从堆栈中移除它们。从被调用的函数的角度来看,这意味着堆栈指针 ESP 指向调用者的返回地址,该地址紧随最后一个参数(按照原始顺序)。( 译注 :这意味着,最先被压入堆栈的是函数的返回地址 )参数的原始顺序被保留下来,因为堆栈是向下增长的,从高位线性地址到低位线性地址。因此,调用者压入堆栈的最后一个参数(即,参数 #1 )将是由 ESP 指向的数组中的第一个参数。

    l 某些有确定参数的 API 函数,如著名的 C 运行时库函数(由 ntdll.dll 和 ntoskrnl.exe 导出),通常使用 __cdecl 调用约定,该约定采用与 __stdcall 相同的参数顺序,但强制调用者清理参数堆栈。

    l 由 __fastcall 修饰的函数声明,则希望前两个参数位于 CPU 寄存器 ECX 和 EDX 中。如果还需要更多的参数,它们将按照相反的顺序传入堆栈,最后由被调用者清理堆栈,这和 __stdcall 相同。

    ; this is the function's prologue

    push ebp ; save current value ebp

    mov ebp, esp ; set stack frame base address

    sub esp, SizeOfLocalStorage ; create local storage area

  • 原文来自 教程网-免费ps教程,cad教程,ppt教程,ppt教程,java教程,vb教程,php教程技术在线学习课程网 转载请注明:http://www.websmill.com/xitong/Windows2000/31868.html

  • 上一篇:实现对共享文件的监控
  • 下一篇:蓝色警报――解决Win 2000/XP的蓝屏陷阱