zoukankan      html  css  js  c++  java
  • 37、Windows API 其它相关原理和注意点

    164位操作系统与32位操作系统最大的不同在于寻址空间的大小,32位操作系统使用32位数据来表示内存地址,因此有232 (4GB)的可用空间,而64位操作系统可以使用16TB的内存地址空间。在64位操作系统下,指针和基本数据类型(int)所引用的空间是64位的。

    Windows系统中包括的对象类型有很多种。内核对象、GDI图形对象、用户对象等。内核对象是与操作系统对系统的管理相关的对象,比如文件、进程、事件,网络通信的Socket等。而GDI对象是指在图形输出的相关对象。USER对象是指用户控件、菜单、输入设备等。

    程序进行相关的操作时,都以这些对象作为操作对象,通常以句柄作为参数。

    VSDebug版本中,很多情况下,通过跳转表调用函数。调用函数时,会使用call指令调用一个跳转表中的位置,这个位置上通常是一个jmp强制跳转指令,跳转到真实的函数程序段处。在Release版本中,不采用函数跳转表,直接调用函数代码所在的地址。

    在函数调用过程中栈的结构所示:

    wps_clip_image-11921

       

        函数每调用一次,ebp变化一次。栈中依次保存着参数、返回地址、调用者的ebp、局部变量等。

    每一次函数调用都会产生一个这样的结构,随着调用的深入在栈中依次增长,因此又称为栈帧,每一帧对应着一个函数调用。ebp在栈帧中起着关键作用,参数的寻址、局部变量的寻址和函数返回都依赖于ebp

    调用方式影响函数调用时参数的传递方式和函数返回后栈的恢复方式。如果为“_cdecl”和“_stdcall”方式则参数均为从右往左入栈,而“_fastcall”使用ECXEDX寄存器传递,余下部分的参数从右向左保存在栈中。

    在函数返回后,如果函数是“_cdecl”调用方式,则是调用者将espebp指令恢复到调用前的态;而如果是“_stdcall”方式,则由被调用函数将栈恢复到调用前,以便调用函数可以继续执行。

    使用memcpystrcpy等函数将数据复制到缓冲区(从低内存地址到高内存地址)。

    2Windows系统的可执行程序结构称作PE, EXE文件、DLL文件、SYS文件、OCX文件等都是PE格式的文件。

    具体结构可以参见[1P565]中介绍。

    3、在进行调用函数时,需要知道函数的地址,调用指令(call)以函数地址或保存函数地址的指针作为参数。在同一模块中的函数,代码的相对位置都是固定的,call语句的参数在编译时都已经计算好,并嵌入到指令中(称作静态链接)。但是位于不同模块的函数要相互调用时,被调用函数的地址并不确定。

        系统使用动态链接机制来保证不同模块中函数的正确调用。导入表和导出表是两个在动态链接中需要使用到的重要结构。

    导入表中保存了一个模块所需调用的外部模块的函数,包括函数所在的DLL函数名等。导出表保存了一个模块可被其他模块调用的函数,包括函数名。

    在进程创建、模块加载时,系统会从可执行文件的导入表中获取信息,知道需要加载哪些DLL,然后再加载这些需要调用的DLL,从加载的被调用DLL中根据函数名找到需要调用的函数地址,然后将导入表指定的各函数的地址指针数组的值全部赋值为真实的DLL导入函数地址。

    因此一个模块的导入表的位置是相对固定的,但是导入表中的函数指针的值是在动态链接时赋值的。在完成动态连接后,程序就可以通过导入表中的函数指针调用外部函数了。

    4NTDLL.DLL所导入的API函数称作本机API (NativeAPI)

    内核中处理系统调用的结构称作SSDTSSDT的全称是System Service Descriptor Table,也就是系统服务描述符表。

    wps_clip_image-10090

        ntdll.dll导出的函数接口就是NativeAPI,由ntdll.dll导出的Native API的实质是一系列的stub函数,实现了从用户态向内核态的跳转,调用系统服务实现API的最终功能。

    当从Native API进入内核态以后,系统会根据服务号在SSDT中查找对应的表项,寻找所调用系统服务函数的真正地址。之后,系统会根据这个地址调用相应的系统服务函数,并返回函数的执行结果。

    5HOOK(挂勾)是一种比较高级的应用。HOOK技术是指修改API的地址或修改API中的代码,使得程序在调用API函数时,可以监视到调用,或者可以修改参数或返回值等。

    通常有两种方法可以实现API HOOK,一是遍历进程中各个模块的导入表,如果导入表中调用了所需HOOK的目标函数,则将跳转地址修改到自定义的函数中;另一种是在目标函数的地址后,在函数的代码处写入跳转指令,一旦API被调用,则会跳转到自定义的函数中。

    因此进行API HOOK,需要进行两个步骤的工作:一是编写用于HOOK的函数,使用这些函数去“替换”正常的API函数,HOOK函数中,需要调用原API函数;二是HOOK程序,使用系统原有API的地址或代码。

    6lib文件中包括链接时所需的信息,指明了链接器应该如何处理这些外部函数等(通常是将函数调用加入导入表中)。

    如果为第三方应用程序提供程序设计接口,那么就需要有lib文件,lib文件指明了在链按时,链接器如何处理这些外部变量、外部函数等。如果需要通过导入表调用DLL中的函数,就需要在链接时将lib文件作为链接输入。

    为第三方开发人员提供头文件,lib文件,DLL文件等。

    参考

    [1] 精通Windows API 函数、接口、编程实例

    [2] http://msdn.microsoft.com/en-us/library/aa966039%28VS.85%29.aspx

  • 相关阅读:
    ADO.Net——增、删、改、查
    面向对象——类库五大原则
    面向对象——设计模式和委托
    JS 函数 内置方法和对象
    js 字符串、数组类型 及方法
    复习一下 Python三元运算
    复习一下 列表
    前端 2 CSS 选择器
    前端 1 HTML
    39
  • 原文地址:https://www.cnblogs.com/mydomain/p/1963225.html
Copyright © 2011-2022 走看看