挂钩Windows API

===========================[ 挂钩Windows API ]==================›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                                    SoBeIt›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                      Author:  Holy_Father <holy_father@phreaker.net>›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                      Version: 1.1 english›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                      Date:    6.10.2002›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
=====[ 1. 内容 ]=============================================›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
1. 内容›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
2. 介绍›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
3. 挂钩方法›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
  3.1 运行前挂钩›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
  3.2 运行时挂钩›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    3.2.1 使用IAT挂钩本进程 ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    3.2.2 改写入口点挂钩本进程›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    3.2.3 保存原始函数›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    3.2.4 挂钩其它进程›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
      3.2.4.1 DLL注入›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
      3.2.4.2 独立的代码›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
      3.2.4.3 原始修改›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
4. 结束语›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
=====[ 2. 介绍 ]====================================================›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    这篇文章是有关在OS Windows下挂钩API函数的方法。所有例子都在基于NT技术的Windows版本NT4.0及以上有效(Windows NT 4.0, Windows 2000, Windows XP)。可能在其它Windows系统也会有效。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    你应该比较熟悉Windows下的进程、汇编器、PE文件结构和一些API函数,才能明白这篇文章里的内容。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    这里使用"Hooking API"这个术语表示对API的完全修改。当调用被挂钩的API时,我们的代码能立刻被执行。我将写下完全的挂钩过程。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
=====[ 3. 挂钩方法 ]==============================================›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    一般来说我们的目的是用我们的代码取代一些函数里的代码。这些问题有时可以在进程运行前解决。这些大多数时候可以用我们运行的用户级进程来完成,目的可以是修改程序的行为。举个例子应用程序的破解,比方说有些程序会在启动时需要原光盘,我们想要不用光盘就启动它。如果我们修改获取驱动类型的函数我们就可以让程序从硬盘启动。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    当我们挂钩系统进程时(比如说服务)这些不可能做到或者我们不打算这么做,或者在这个例子里我们不知道哪个进程才是目标。这时我们就要用到动态挂钩(在运行时挂钩)的技术。使用的例子有rootkit或者病毒里的反杀毒软件的技术。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
=====[ 3.1 运行前挂钩 ]===========================================›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    这里修改我们想要修改函数来自的物理模块(大多数时候是.exe或.dll)。在这里我们至少有3种可能的做法。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    第一种可能是找到函数的入口点然后重写它的代码。这会因为函数的大小而受限制,但我们能动态加载其它一些模块(API LoadLibrary),所以应该足够了。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    内核函数(kernel32.dll)是通用的因为Windows中每个进程都有这个模块的拷贝。另一个好处是如果我们知道哪些模块在某版本中会修改,我们可以在一些API如LoadLibraryA中使用直接的指针。这是因为kernel模块在内存中地址在相同Windows版本中是固定的。我们同样也能用动态加载的模块的作用。在这里它的初始化部分在加载进内存后立刻就运行。在新模块的初始化部分我们不受限制。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    第二种可能是在模块中被代替的函数只是原函数的扩展。然后我们选择要么修改开始的5个字节为跳转指令或者改写IAT。如果改为跳转指令,那么将会改变指令执行流程转为执行我们的代码。如果调用了IAT记录被修改的函数,我们的代码能在调用结束后被执行。但模块的扩展没那么容易,因为我们必须注意DLL首部。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    下一个是修改整个模块。这意味着我们创建自己的模块版本,它能够加载原始的模块并调用原始的函数,当然我们对这个不感兴趣,但重要的函数都是被更新的。这种方法对于有的模块过大有几百个导出函数的很不方便。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
=====[ 3.2 运行时挂钩 ]==========================================›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    在运行前挂钩通常都非常特殊,并且是在内部面向具体的应用程序(或模块)。如果我们更换了kernel32.dll或ntdll.dll里的函数(只在NT操作系统里),我们就能完美地做到在所有将要运行的进程中替换这个函数。但说来容易做起来却非常难,因为我们不但得考虑精确性和需要编写比较完善的新函数或新模块,但主要问题是只有将要运行的进程才能被挂钩(要挂钩所有进程只能重启电脑)。另一个问题是如何进入这些文件,因为NT操作系统保护了它们。比较好的解决方法在进程正在运行时挂钩。这需要更多的有关知识,但最后的结果相当不错。在运行中挂钩只对能够写入它们的内存的进程能成功。为了能写入它自己我们使用API函数WriteProcessMemory。现在我们开始运行中挂钩我们的进程。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
=====[ 3.2.1 使用IAT挂钩本进程 ]===================================›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    这里有很多种可能性。首先介绍如何用改写IAT挂钩函数的方法。接下来这张图描述了PE文件的结构:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    +-------------------------------+    - offset 0›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    | MS DOS标志("MZ") 和 DOS块    |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    +-------------------------------+    ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |      PE 标志 ("PE")          |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    +-------------------------------+›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |            .text            |    - 模块代码›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |          程序代码            |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |                              |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    +-------------------------------+›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |            .data            |    - 已初始化的(全局静态)数据›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |          已初始化的数据      |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |                              |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    +-------------------------------+›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |            .idata            |    - 导入函数的信息和数据›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |            导入表            |      ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |                              |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    +-------------------------------+›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |            .edata            |    - 导出函数的信息和数据›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |            导出表            |      ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |                              |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    +-------------------------------+›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    |          调试符号            |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    +-------------------------------+›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    这里对我们比较重要的是.idata部分的导入地址表(IAT)。这个部分包含了导入的相关信息和导入函数的地址。有一点很重要的是我们必须知道PE文件是如何创建的。当在编程语言里间接调用任意API(这意味着我们是用函数的名字来调用它,而不是用它的地址),编译器并不直接把调用连接到模块,而是用jmp指令连接调用到IAT,IAT在系统把进程调入内存时时会由进程载入器填满。这就是我们可以在两个不同版本的Windows里使用相同的二进制代码的原因,虽然模块可能会加载到不同的地址。进程载入器会在程序代码里调用所使用的IAT里填入直接跳转的jmp指令。所以我们能在IAT里找到我们想要挂钩的指定函数,我们就能很容易改变那里的jmp指令并重定向代码到我们的地址。完成之后每次调用都会执行我们的代码了。这种方法的缺点是经常有很多函数要被挂钩(比方说如果我们要在搜索文件的API中改变程序的行为我们就得修改函数FindFirstFile和FindNextFile,但我们要知道这些函数都有ANSI和WIDE版本,所以我们不得不修改FindFirstFileA、FindFirstFileW、FindNextFileA和FileNextFileW的IAT地址。但还有其它类似的函数如FindFirstFileExA和它的WIDE版本FindFirstFileExW,也都是由前面提到的函数调用的。我们知道FindFirstFileW调用FindFirstFileExW,但这是直接调用,而不是使用IAT。再比如说ShellAPI的函数SHGetDesktopFolder也会直接调用FindFirstFilwW或FindFirstFileExW)。如果我们能获得它们所有,结果就会很完美。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    我们通过使用imagehlp.dll里的ImageDirectoryEntryToData来很容易地找到IAT。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    PVOID ImageDirectoryEntryToData(›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        IN LPVOID Base,    ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        IN BOOLEAN MappedAsImage,    ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        IN USHORT DirectoryEntry,    ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        OUT PULONG Size    ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    );›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
在这里Base参数可以用我们程序的Instance(Instance通过调用GetModuleHandle获得):›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    hInstance = GetModuleHandleA(NULL);›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
DirectoryEntry我们可以使用恒量IMAGE_DIRECTORY_ENTRY_IMPORT。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    #define IMAGE_DIRECTORY_ENTRY_IMPORT 1›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    函数的结果是指向第一个IAT记录指针。IAT的所有记录是由IMAGE_IMPORT_DESCRIPTOR定义的结构。所以函数结果是指向IMAGE_IMPORT_DESCRIPTOR的指针。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    typedef struct _IMAGE_THUNK_DATA {›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        union {›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            PBYTE ForwarderString;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            PDWORD Function;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            DWORD Ordinal;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            PIMAGE_IMPORT_BY_NAME AddressOfData;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        } ;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    } IMAGE_THUNK_DATA,*PIMAGE_THUNK_DATA;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    typedef struct _IMAGE_IMPORT_DESCRIPTOR {›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        union {›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            DWORD Characteristics;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            PIMAGE_THUNK_DATA OriginalFirstThunk;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        } ;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        DWORD TimeDateStamp;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        DWORD ForwarderChain;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        DWORD Name;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        PIMAGE_THUNK_DATA FirstThunk;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    } IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    IMAGE_IMPORT_DESCRIPTOR里的Name成员变量是模块名字的指针。如果我们想要挂钩某个函数比如是来自kernel32.dll我们就在导入表里找属于名字kernel32.dll的描述符号。我们先调用ImageDirectoryEntryToData然后找到名字是"kernel32.dll"的描述符号(可能不只一个描述符号是这个名字),最后我们在这个模块的记录里所有函数的列表里找到我们想要的函数(函数地址通过GetProcAddress函数获得)。如果我们找到了就必须用VirtualProtect函数来改变内存页面的保护属性,然后就可以在内存中的这些部分写入代码了。在改写了地址之后我们要把保护属性改回来。在调用VirtualProtect之前我们还要先知道有关页面的信息,这通过VirtualQuery来实现。我们可以加入一些测试以防某些函数会失败(比方说如果第一次调用VirtualProctect就失败了,我们就没办法继续)。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    PCSTR pszHookModName = "kernel32.dll",pszSleepName = "Sleep";›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    HMODULE hKernel = GetModuleHandle(pszHookModName);›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    PROC pfnNew = (PROC)0x12345678,      //这里存放新地址›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        pfnHookAPIAddr = GetProcAddress(hKernel,pszSleepName);›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    ULONG ulSize;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            hKernel,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            TRUE,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            IMAGE_DIRECTORY_ENTRY_IMPORT,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            &ulSize›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        );›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    while (pImportDesc->Name)›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    {›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        PSTR pszModName = (PSTR)((PBYTE) hKernel + pImportDesc->Name);›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        if (stricmp(pszModName, pszHookModName) == 0) ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        break;  ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        pImportDesc++;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    }›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    PIMAGE_THUNK_DATA pThunk = ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    (PIMAGE_THUNK_DATA)((PBYTE) hKernel + pImportDesc->FirstThunk);›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    while (pThunk->u1.Function)›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    {›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        PROC* ppfn = (PROC*) &pThunk->u1.Function;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        BOOL bFound = (*ppfn == pfnHookAPIAddr);›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        if (bFound) ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        {›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            MEMORY_BASIC_INFORMATION mbi;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            VirtualQuery(›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                ppfn,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                &mbi,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                sizeof(MEMORY_BASIC_INFORMATION)›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            );›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            VirtualProtect(›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                mbi.BaseAddress,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                mbi.RegionSize,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                PAGE_READWRITE,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                &mbi.Protect)›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            )›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            *ppfn = *pfnNew;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            DWORD dwOldProtect;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            VirtualProtect(›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                mbi.BaseAddress,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                mbi.RegionSize,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                mbi.Protect,›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                &dwOldProtect›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            );›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            break;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        }›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
        pThunk++;›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    }›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
调用Sleep(1000)的结果如例子所示:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    00407BD8: 68E8030000    push 0000003E8h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    00407BDD: E812FAFFFF    call Sleep›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    Sleep:    ;这是跳转到IAT里的地址›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    004075F4: FF25BCA14000    jmp dword ptr [00040A1BCh]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    原始表:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    0040A1BC: 79 67 E8 77 00 00 00 00›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
      ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    新表:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    0040A1BC: 78 56 34 12 00 00 00 00›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
所以最后会跳转到0x12345678。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
          ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
=====[ 3.2.2 改写入口点挂钩本进程 ]==================›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    改写函数入口点开始的一些字节这种方法相当简单。就象改变IAT里的地址一样,我们也要先修改页面属性。在这里对我们想要挂钩的函数是一开始的5个字节。为了之后的使用我们用动态分配MEMORY_BASIC_INFORMATION结构。函数的起始地址也是用GetProcAddress来获得。我们在这个地址里插入指向我们代码的跳转指令。接下来程序调用Sleep(5000)(所以它会等待5秒钟),然后Sleep函数被挂钩并重定向到new_sleep,最后它再次调用Sleep(5000)。因为新的函数new_sleep什么都不做并直接返回,所以整个程序只需要5秒钟而不是10秒种。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
.386p›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
.model flat, stdcall›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
includelib lib\kernel32.lib›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
Sleep            PROTO :DWORD›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
GetModuleHandleA    PROTO :DWORD›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
GetProcAddress        PROTO :DWORD,:DWORD›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
VirtualQuery        PROTO :DWORD,:DWORD,:DWORD›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
VirtualProtect        PROTO :DWORD,:DWORD,:DWORD,:DWORD›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
VirtualAlloc        PROTO :DWORD,:DWORD,:DWORD,:DWORD›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
VirtualFree        PROTO :DWORD,:DWORD,:DWORD›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
FlushInstructionCache    PROTO :DWORD,:DWORD,:DWORD›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
GetCurrentProcess    PROTO›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
ExitProcess        PROTO :DWORD›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
.data›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
kernel_name        db "kernel32.dll",0›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
sleep_name        db "Sleep",0›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
old_protect        dd ?›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
MEMORY_BASIC_INFORMATION_SIZE    equ 28›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
PAGE_READWRITE        dd 000000004h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
PAGE_EXECUTE_READWRITE dd 000000040h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
MEM_COMMIT        dd 000001000h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
MEM_RELEASE        dd 000008000h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
.code›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
start:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    5000›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    Sleep›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
do_hook:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    offset kernel_name›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    GetModuleHandleA›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    offset sleep_name›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    eax›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    GetProcAddress›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    mov    edi,eax            ;最后获得Sleep地址›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    PAGE_READWRITE›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    MEM_COMMIT›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    MEMORY_BASIC_INFORMATION_SIZE›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    0›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    VirtualAlloc›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    test    eax,eax›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    jz    do_sleep›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    mov    esi,eax            ;为MBI结构分配内存›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    MEMORY_BASIC_INFORMATION_SIZE›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    esi›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    edi›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    VirtualQuery        ;内存页的信息›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    test    eax,eax›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    jz    free_mem›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    GetCurrentProcess›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    5›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    edi›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    eax›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    FlushInstructionCache    ;只是为了确定一下:)›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    lea    eax,[esi+014h]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    eax›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    PAGE_EXECUTE_READWRITE›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    lea    eax,[esi+00Ch]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    [eax]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    [esi]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    VirtualProtect          ;我们要修改保护属性,这样才能够写入代码›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    test    eax,eax›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    jz    free_mem        ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    mov    byte ptr [edi],0E9h    ;写入跳转指令›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    mov    eax,offset new_sleep›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    sub    eax,edi›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    sub    eax,5›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    inc    edi›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    stosd                ;这里是跳转地址›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    offset old_protect›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    lea    eax,[esi+014h]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    [eax]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    lea    eax,[esi+00Ch]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    [eax]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    [esi]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    VirtualProtect        ;恢复页保护属性›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
free_mem:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    MEM_RELEASE›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    0›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    esi›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    VirtualFree        ;释放内存›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
do_sleep:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    5000›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    Sleep›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    push    0›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    call    ExitProcess›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
new_sleep:                ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    ret    004h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
end start›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
第二次调用Sleep的结果是这样: ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    004010A4: 6888130000    push 000001388h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    004010A9: E80A000000    call Sleep›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    Sleep:    ;这里是跳转到IAT里的地址 ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    004010B8: FF2514204000    jmp dword ptr [000402014h]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    tabulka:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    00402014: 79 67 E8 77 6C 7D E8 77›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
      ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    Kernel32.Sleep:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    77E86779: E937A95788    jmp 0004010B5h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    new_sleep:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    004010B5: C20400    ret 004h    ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
=====[ 3.2.3 保存原始函数 ]=====================================›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    更多时候我们需要的不仅仅是挂钩函数。比方说也许我们并不想取代给定的函数而只是想检查一下它的结果,或者也许我们只是想在函数被使用特定的参数来调用时才取代原函数。比较好的例子有前面提过的通过取代FindXXXFile函数来完成隐藏文件。所以如果我们想要隐藏指定的文件并且不想被注意的话,就得对其它所有文件只调用没有被修改过的原始函数。这对使用修改IAT的方法时是很简单的,为调用原始函数我们可以用GetProcAddress获得它的原始地址,然后直接调用。但修改入口点的方法就会有问题,因为修改了函数入口点的5个字节,使我们破坏了原函数。所以我们必须保存开始的那些指令。这将用到以下的技术。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    我们知道我们要修改开始的5个字节但不知道里面包含多少条指令以及指令的长度。我们得为开始那些指令保留足够的内存空间。16个字节应该足够了,因为函数开始时通常没有多长的指令,很可能根本就用不到16个字节。整个被保留的内存用0x90(0x90=nop)来填满。下一个5个字节预留给将在之后填入的跳转指令。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
old_hook:        db 090h,090h,090h,090h,090h,090h,090h,090h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            db 090h,090h,090h,090h,090h,090h,090h,090h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
            db 0E9h,000h,000h,000h,000h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
    现在我们已准备好拷贝开始的指令。为获得指令长度的代码相当麻烦,这就是我们得使用已完成的引擎的原因。它是由Z0MBiE写的。传入参数是我们要获得长度的指令的地址。输出参数在eax里。›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
; LDE32, Length-Disassembler Engine, 32-bit, (x) 1999-2000 Z0MBiE›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
; special edition for REVERT tool›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
; version 1.05›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_MEM1                  equ    0001h      ; |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_MEM2                  equ    0002h      ; |may be used simultaneously›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_MEM4                  equ    0004h      ; |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_DATA1                equ    0100h      ; |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_DATA2                equ    0200h      ; |may be used simultaneously›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_DATA4                equ    0400h      ; |›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_67                    equ    0010h      ; used with C_PREFIX›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_MEM67                equ    0020h      ; C_67 ? C_MEM2 : C_MEM4›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_66                    equ    1000h      ; used with C_PREFIX›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_DATA66                equ    2000h      ; C_66 ? C_DATA2 : C_DATA4›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_PREFIX                equ    0008h      ; prefix. take opcode again›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_MODRM                equ    4000h      ; MODxxxR/M›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
C_DATAW0                equ    8000h      ; opc&1 ? C_DATA66 : C_DATA1›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        p386›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        model  flat›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        locals  @@›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        .code›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
public                  disasm_main›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
public                  _disasm_main›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
public                  @disasm_main›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
public                  DISASM_MAIN›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
disasm_main:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
_disasm_main:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@disasm_main:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
DISASM_MAIN:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
; __fastcall            EAX›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
; __cdecl              [ESP+4]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
;这是我的第一处修改,它只是这个函数的声明›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
get_instr_len:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        mov    ecx, [esp+4]    ; ECX = opcode ptr›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        xor    edx, edx        ; 标志›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        xor    eax, eax›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@prefix:              and    dl, not C_PREFIX›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        mov    al, [ecx]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        inc    ecx›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        or      edx, table_1[eax*4]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        test    dl, C_PREFIX›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jnz    @@prefix›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    al, 0F6h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        je      @@test›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    al, 0F7h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        je      @@test›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    al, 0CDh›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        je      @@int›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    al, 0Fh›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        je      @@0F›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@cont:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        test    dh, C_DATAW0 shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jnz    @@dataw0›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@dataw0done:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        test    dh, C_MODRM shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jnz    @@modrm›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@exitmodrm:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        test    dl, C_MEM67›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jnz    @@mem67›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@mem67done:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        test    dh, C_DATA66 shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jnz    @@data66›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@data66done:›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        mov    eax, ecx›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        sub    eax, [esp+4]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        and    edx,C_MEM1+C_MEM2+C_MEM4+C_DATA1+C_DATA2+C_DATA4›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        add    al, dl›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        add    al, dh›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
;这里是我的第二处修改,只有在原始版本这里是retn›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@exit:                ret    00004h  ›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@test:                or      dh, C_MODRM shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        test    byte ptr [ecx], 00111000b  ; F6/F7 -- test›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jnz    @@cont›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        or      dh, C_DATAW0 shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jmp    @@cont›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@int:                  or      dh, C_DATA1 shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    byte ptr [ecx], 20h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jne    @@cont›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        or      dh, C_DATA4 shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jmp    @@cont›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@0F:                  mov    al, [ecx]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        inc    ecx›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        or      edx, table_0F[eax*4]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    edx, -1›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jne    @@cont›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@error:                mov    eax, edx›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jmp    @@exit›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@dataw0:              xor    dh, C_DATA66 shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        test    al, 00000001b›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jnz    @@dataw0done›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        xor    dh, (C_DATA66+C_DATA1) shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jmp    @@dataw0done›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@mem67:                xor    dl, C_MEM2›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        test    dl, C_67›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jnz    @@mem67done›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        xor    dl, C_MEM4+C_MEM2›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jmp    @@mem67done›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@data66:              xor    dh, C_DATA2 shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        test    dh, C_66 shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jnz    @@data66done›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        xor    dh, (C_DATA4+C_DATA2) shr 8›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jmp    @@data66done›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@modrm:                mov    al, [ecx]›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        inc    ecx›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        mov    ah, al  ; ah=mod, al=rm›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        and    ax, 0C007h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    ah, 0C0h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        je      @@exitmodrm›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        test    dl, C_67›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jnz    @@modrm16›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@modrm32:              cmp    al, 04h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jne    @@a›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        mov    al, [ecx]      ; sib›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        inc    ecx›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        and    al, 07h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@a:                    cmp    ah, 40h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        je      @@mem1›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    ah, 80h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        je      @@mem4›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    ax, 0005h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jne    @@exitmodrm›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@mem4:                or      dl, C_MEM4›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jmp    @@exitmodrm›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@mem1:                or      dl, C_MEM1›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jmp    @@exitmodrm›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@modrm16:              cmp    ax, 0006h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        je      @@mem2›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    ah, 40h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        je      @@mem1›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        cmp    ah, 80h›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jne    @@exitmodrm›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
@@mem2:                or      dl, C_MEM2›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        jmp    @@exitmodrm›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        endp›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
                        .data›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
;0F      -- 在代码中分析,不需要标志(也就是标志(flag)必须为0)›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
;F6,F7  -- --//-- (ttt=000 -- 3 字节, 否则为2字节)›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
;CD      -- --//-- (如果为 CD 20 为6字节, 否则为2字节)›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
table_1                label  dword  ; 一般的指令›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 00›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 01›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 02›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 03›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 04›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 05›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd 0                    ; 06›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd 0                    ; 07›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 08›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 09›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 0A›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 0B›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 0C›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 0D›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd 0                    ; 0E›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd 0                    ; 0F›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 10›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 11›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 12›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 13›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 14›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 15›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd 0                    ; 16›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd 0                    ; 17›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 18›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 19›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 1A›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 1B›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 1C›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 1D›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd 0                    ; 1E›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd 0                    ; 1F›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 20›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 21›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 22›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 23›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 24›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 25›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_PREFIX            ; 26›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd 0                    ; 27›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 28›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 29›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 2A›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 2B›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 2C›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 2D›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_PREFIX            ; 2E›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd 0                    ; 2F›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 30›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 31›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 32›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_MODRM              ; 33›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 34›sÄi÷QF9_forum.entlib.net.cn2ê»íRR½Ân
dd C_DATAW0            ; 35›sÄi÷QF9_forum.entlib.n