给分的内容在后面,高手可以跳过第一段,直接看第2段的代码!能提供帮助的绝对不会吝啬分数的!不完美逆向320块的apihook教程
    好把,他的是教程,俺这不是,只是写着玩的简单的逆向烂文。希望各位客官不要拍砖。
    要说起来逆向这个程序的原因呢,其实也很简单,前段时间在天空下载软件,无意中发现了一个软件。自称是API拦截技术教程,还开价320元。apihook的技术在windows核心技术里讲了很多,居然还有人卖这么贵,我就对他来了点兴趣。程序的简介是这样的。
    对于程序员来讲,API拦截技术是一种重要的基础技术。这项技能为编写某些工具软件提供了可能,并可以大大提高我们对第三方应用程序的控制能力。不过,目前 API 拦截的技术资料往往局限于原理方面的论述,对于如何具体地编译一个 API 拦截程序却守口如瓶。毕竟,对于程序员来讲,当初学习这项技能花费了不少心血,如果让他们无偿地奉献出来,恐怕不太现实;另外的一个因素就是竞争,多一个人学会这项技能,就多一份竞争。我在掌握这项技能的时候,就走了不少弯路,如果当初有一份详细的资料,这些不必要的弯路是完全可以避免。而这正是我编写这份技术资料的目的。
   本程序是一个示例程序,用以演示如何拦截 API 调用。开始拦截 CreateProcess之后,当用户通过资源管理器运行程序时,就会弹出一个对话框提示用户运行了什么程序。停止拦截之后,用户运行程序时则不会弹出对话框。
    随本程序附带的教程是未注册版本,如果您需要详细的资料,请通过网上商城进行注册。注册费用为 320 元人民币。最终价格请以网上商城的价格为准。
    这就引起了我的好奇,难道这个软件用了什么牛x的新技术?居然这么值钱!那得看看,于是就把该软件下载下来研究了研究。谁知道,他所用的技术不但一点创新都没有,还有着很大的局限性。于是就有了这篇文章,还希望高手不要见笑。
    这个程序的原版大家自己找,名字就叫做API拦截教程。启动该程序后,按下拦截createprocess的按钮后,运行任何程序都会弹出运行程序的路径。稍微了解apihook的都了解,通常ring3下hookapi的办法有三种,一是修改程序的iat表,使api调用跳向自己的函数而不是转向api入口。二是修改api入口的机器码。三是用创建远线程CreateRemoteThread的办法来完成。那么这个教程究竟用了什么先进手法呢?
    先运行一次,按下按钮后,果然explorer弹出了程序的路径。此时,你如果使用icesword类的可以查看程序模块的程序查看explorer的模块,你就会发现explorer里面多了个InterceptDll.dll的模块,当我们卸载了这个dll后,这个拦截的效果就没有了。看来这个程序的核心不是那个启动的程序,而是这个dll。现在让我们看看这个InterceptDll.dll到底做了什么。
    先使用VC++的工具DUMPBIN将DLL中的导出函数表导出到一定义(.DEF)文件
DUMPBIN InterceptDll.dll /EXPROTS /OUT:InterceptDll.def
    ordinal hint RVA      name          1    0 00001230 InstallHook
          2    1 00001270 UninstallHook
只有两个导出函数,看名字就知道,一个是安装钩子,一个卸载钩子。我们调用看看 ,结果连参数都不用,只要调用InstallHook就可以把InterceptDll.dll插入explorer,用UninstallHook就可以卸载钩子。看来我们不用分析他的exe文件了,因为有用的东西就在这个dll里。那么如何分析这个dll这么工作的呢?直接用ida看静态代码,可以看见dll里有vivirtualalloc,setwindowshookexa等钩子函数。但是,里面乜嘢CreateRemoteThread这个函数,那么基本可以排除了第三种方法了。修改iat或者字节数的可能性比较大一些。那么具体究竟是用了什么手段,又是怎么实现的呢?光静态看源代码看出来,我可没那种本事。如果说要实时调试explorer又非常的麻烦,那么怎么办呢?其实办法很简单啦,只要自己修改一个exe文件名让他跟explorer同名就可以了。这家伙可不管你是真李逵还是假李鬼,统统都插!我先写了个很简单的exe程序,只有一个按钮直接掉用createprocess启动notepad的小程序,然后改名为explorer。运行后让程序拦截,果然再用icesword看模块,那个InterceptDll.dll偷偷的钻进了我写的这个程序。
   好,现在动手钻进InterceptDll.dll的内部,看看他到底干了什么!我用的是olldbg,其实windbg也可以,我用od习惯了。先附加到我自己写的这个小explorer程序,然后在createprocess下断点,按下启动notepad的按钮,断下以后,一步一步跟踪。当进入到原先createprocess的领空的时候,入口变了
7C802332 >- E9 B9ED7F93     jmp     100010F0
7C802337    6A 00           push    0变成了跳向100010F0,运行了这个跳转,就进入了dll的程序代码段。具体汇编代码如下。
100010F1    8BEC            mov     ebp, esp
100010F3    6A FF           push    -1
100010F5    68 50710010     push    10007150
100010FA    68 7C220010     push    1000227C
100010FF    64:A1 00000000  mov     eax, dword ptr fs:[0]
10001105    50              push    eax
10001106    64:8925 0000000>mov     dword ptr fs:[0], esp
1000110D    83EC 0C         sub     esp, 0C
10001110    53              push    ebx
10001111    56              push    esi
10001112    57              push    edi
10001113    33C0            xor     eax, eax
10001115    8945 E4         mov     dword ptr [ebp-1C], eax
10001118    8945 FC         mov     dword ptr [ebp-4], eax
1000111B    50              push    eax
1000111C    68 44710010     push    10007144                                                          ; ASCII "鎎*b"
10001121    8B75 0C         mov     esi, dword ptr [ebp+C]
10001124    56              push    esi
10001125    50              push    eax
10001126    FF15 FC700010   call    dword ptr [100070FC]                                              ; USER32.MessageBoxW
1000112C    8B45 2C         mov     eax, dword ptr [ebp+2C]
1000112F    50              push    eax
10001130    8B4D 28         mov     ecx, dword ptr [ebp+28]
10001133    51              push    ecx
10001134    8B55 24         mov     edx, dword ptr [ebp+24]
10001137    52              push    edx
10001138    8B45 20         mov     eax, dword ptr [ebp+20]
1000113B    50              push    eax
1000113C    8B4D 1C         mov     ecx, dword ptr [ebp+1C]
1000113F    51              push    ecx
10001140    8B55 18         mov     edx, dword ptr [ebp+18]
10001143    52              push    edx
10001144    8B45 14         mov     eax, dword ptr [ebp+14]
10001147    50              push    eax
10001148    8B4D 10         mov     ecx, dword ptr [ebp+10]
1000114B    51              push    ecx
1000114C    56              push    esi
1000114D    8B55 08         mov     edx, dword ptr [ebp+8]
10001150    52              push    edx
10001151    E8 7AFFFFFF     call    100010D0
当运行到 call    100010D0 时开始跳回原领空
call    100010D0里面的实际代码是这样的。
100010D0    8BFF            mov     edi, edi
100010D2    55              push    ebp
100010D3    8BEC            mov     ebp, esp
100010D5  - E9 5D12806C     jmp     kernel32.7C802337
而 kernel32.7C802337处
100010D0    8BFF            mov     edi, edi
100010D2    55              push    ebp
100010D3    8BEC            mov     ebp, esp
正是原本createprocess代码接下来的一段 
到这里,这个dll的hook功能就真相大白了,他完全没有使用什么新技术来完成hook。照样是修改api函数的头5个字节,然后跳转到自己的函数,之后再构造一个类似的头,最后跳回原来的api领空继续运行。这个完全就是windows核心编程里的代码的照抄,就这抄一下就要人320元,是在有点太黑了吧!
    更为重要的是,apihook中这样的hook有很大的缺陷,为什么这么说呢?我们可以看见他是将入口修改为 jmp     100010F0
7C802332 >- E9 B9ED7F93     jmp     100010F0
    我们知道一般的api函数头部是不会出现这样的远距离的jmp的,所以只要检测api的函数头一个字节是否e9就可以很轻松的检测出api是否被hook住了。还有一个问题就是,如果我们的目的并不停止于,只是在api函数处理之前修改某些入口函数或者做些处理,而是整个重新处理而不回到系统的api处理处,这个流程也不符合我们的要求。
    不过没有关系,既然现在我们已经知道了这个dll工作的大至流程,我们也可以自己写一个拦截createprocess的dll了,而我们把这个程序改进一下,使他成为一个全局的钩子,而且我们可以选择程序的开启,在程序开启以前弹出一个msgbox,上面有是和否的按钮,你按下是程序就不能启动,而按下否程序就照常启动,而弹出的按钮里不但有这个程序的路径,还有启动这个程序的路径。怎么样,比他的还要高级一些吧。 

解决方案 »

  1.   

     我想说一句,大家不要总说Detours,因为表面上Detours可以很容易的钩住api,但是他的自由度太低了。最重要的是,他无法完成ssdt hook,还是提高自己的水平最重要。
        我改出了两个版本一个是asm的一个是vc的,但是奇怪的是asm代码没有问题,而vc的代码却出了问题,我希望高手能帮我解决以下两个问题,第一个问题:就是在vc代码中(根据王艳萍的windows程序设计代码修改)
    在构建新的跳转字节是靠这段代码
    BYTE btNewBytes[8]={0xB8,0xE0,0x18,0x00,0x10,0xFF,0xE0,0x00};
    这个机器吗的含义是,jmp到我们自己定义的MyCreateProcessA函数处。
    这里使用是固定值,只要我们稍微修改一下代码,这里就要修改,很麻烦的是,如果使用非debug版本,你找不到jmp到这个函数的直接代码,需要你自己去调试查找非常麻烦。
    而asm中是自己动态获得的
    获得代码如下
    mov hacker.a,0B8h    ;mov eax, 
    ;mov hacker.d PMyapi  ;0x000000 
    mov hacker.d,0FFh    ;jmp 
    mov hacker.e, 0E0h    ;eax 
    中间有间隔
    mov hacker.PMyapi,offset MyAPI  ;0x000010                  ;要替代API的函数地址 
    这样的话,完全不用考虑api的地址由程序自己来定位,由于本人vc功力不够,实在不知道如何实现这个代码,希望高手能指点一二。第二个问题相对简单点,大家可以看见,我asm的代码中钩的是createprocessw而vc钩的是createprocessa,为什么呢?explorer实际上是调用createprocessw来启动程序的,用createprocessa是钩不住explorer启动的程序。而我在用vc写createprocessw钩子的时候,解决不了unicode的问题,因为MyCreateProcessA的特殊性,他要求跟原来的函数格式一样,所以只要我一使用WideCharToMultiByte这类的函数,返回值就出错了。而如果完全用unicode来写这个函数,我又不知道LPSTARTUPINFO这个的宽字符格式是什么?所以也请高手同样给与指点!
    #pragma comment(linker,"/BASE:0xBFF70000")
    #include "stdafx.h"
    #include "dllin.h"PROC m_pfnOrig;
    BYTE m_btNewBytes[8];
    BYTE m_btOldBytes[8];
    HMODULE m_hMod;BOOL WriteBack()
    {
    if(m_pfnOrig != NULL)
    {
    DWORD dwOldProtect;
    MEMORY_BASIC_INFORMATION    mbi;
    ::VirtualQuery(m_pfnOrig, &mbi, sizeof(mbi));
    ::VirtualProtect(m_pfnOrig, 8, PAGE_READWRITE, &dwOldProtect); // 写入原来的执行代码
    ::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, 
    m_btOldBytes, sizeof(DWORD)*2, NULL); 

    ::VirtualProtect(m_pfnOrig, 8, mbi.Protect, 0);
    return true;
    }
    return false;
    }BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
     )
    {    BYTE btNewBytes[8]={0xB8,0xE0,0x18,0x00,0x10,0xFF,0xE0,0x00};
         memcpy(m_btNewBytes,btNewBytes,8);
    if (ul_reason_for_call==DLL_PROCESS_ATTACH)    //当DLL加载时产生此事件 
    {
     
    m_hMod=::LoadLibrary("kernel32.dll");              //取API地址     //保存API地址 
    if (m_hMod==NULL){
    m_pfnOrig=NULL;
    return true;
    }
    m_pfnOrig=::GetProcAddress(m_hMod,"CreateProcessA");if (m_pfnOrig!=NULL){
    DWORD oldProc;
    MEMORY_BASIC_INFORMATION  mbi;
    ::VirtualQuery (m_pfnOrig,&mbi,sizeof(mbi));
    ::VirtualProtect( m_pfnOrig,8,PAGE_READWRITE,&oldProc);
    memcpy(m_btOldBytes,m_pfnOrig,8);
    ::WriteProcessMemory(::GetCurrentProcess(),(void*)m_pfnOrig,m_btNewBytes,sizeof(DWORD)*2,NULL);
    ::VirtualProtect( m_pfnOrig,8,mbi.Protect ,0);
    return true;
    }
    }
    if (ul_reason_for_call==DLL_PROCESS_DETACH)    //当DLL加载时产生此事件 
    {
    WriteBack();
    return TRUE;
    }    return TRUE;
    }
    BOOL  Rehook()
    {
    // 修改原API函数执行代码的前8个字节,使它跳向我们的函数
    if(m_pfnOrig != NULL)
    {
    DWORD dwOldProtect;
    MEMORY_BASIC_INFORMATION    mbi;
    ::VirtualQuery( m_pfnOrig, &mbi, sizeof(mbi) );
    ::VirtualProtect(m_pfnOrig, 8, PAGE_READWRITE, &dwOldProtect); // 写入新的执行代码
    ::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, 
    m_btNewBytes, sizeof(DWORD)*2, NULL); 

    ::VirtualProtect(m_pfnOrig, 8, mbi.Protect, 0);
    return true;
    }
    return FALSE;
    }
    BOOL MyCreateProcessA(
        LPCTSTR lpApplicationName, // pointer to name of executable module 
        LPTSTR lpCommandLine, // pointer to command line string
        LPSECURITY_ATTRIBUTES lpProcessAttributes, // pointer to process security attributes 
        LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to thread security attributes 
        BOOL bInheritHandles, // handle inheritance flag 
        DWORD dwCreationFlags, // creation flags 
        LPVOID lpEnvironment, // pointer to new environment block 
        LPCTSTR lpCurrentDirectory, // pointer to current directory name 
        LPSTARTUPINFO lpStartupInfo, // pointer to STARTUPINFO 
        LPPROCESS_INFORMATION lpProcessInformation  // pointer to PROCESS_INFORMATION  
       )
    {
    PROCESS_INFORMATION ProcessInfo;        WriteBack(); DWORD rets=::MessageBox(NULL,GetCommandLine(),lpApplicationName,4);if (rets!=7)
    {
    BOOL shutok=::CreateProcess(
    lpApplicationName, // pointer to name of executable module 
    lpCommandLine, // pointer to command line string
    lpProcessAttributes, // pointer to process security attributes 
      lpThreadAttributes, // pointer to thread security attributes 
      bInheritHandles, // handle inheritance flag 
        CREATE_SUSPENDED, // creation flags 
        lpEnvironment, // pointer to new environment block 
        lpCurrentDirectory, // pointer to current directory name 
        lpStartupInfo, // pointer to STARTUPINFO 
        &ProcessInfo // pointer to PROCESS_INFORMATION  
       );//HANDLE hProcess1=ProcessInfo.hProcess;
    //RemoteLoadLibrary(hProcess1,"hook.dll");
    //ResumeThread(ProcessInfo.hThread);
    }Rehook(); 
    __asm
    {
    mov eax,shutok;
    leave;
    ret 40;
    } return 0;
    }
      

  2.   

    (asm代码改自nohack的代码)    
    ASM的代码如下:
        ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 
    ;               原代码编写 by hacker0058
    ;                             aspower 稍做修改
                              汇编(MASM):最简单的HOOK API                          ; 
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 
    .486 
    .model flat,stdcall 
    option casemap:none include windows.inc 
    include kernel32.inc
    include winmm.inc
    includelib kernel32.lib 
    include user32.inc 
    includelib user32.lib
    include psapi.inc 
    includelib psapi.lib
    ;include winmm.inc
    ;includelib winmm.lib 
    HOOKAPI struct 
    a  byte ? 
    PMyapi DWORD ?  
    d BYTE ?  
    e BYTE ? 
    HOOKAPI ends 
    ;子程序声明 
    WriteApi proto :DWORD ,:DWORD,:DWORD,:DWORD 
    MyAPI proto  :DWORD ,:DWORD ,:DWORD ,:DWORD ,:DWORD ,:DWORD ,:DWORD ,:DWORD ,:DWORD ,:DWORD 
    GetApi proto  :DWORD,:DWORD 
    ;已初始化数据 
    .data 
    hInstance dd 0 
    WProcess dd 0 
    hacker HOOKAPI <> 
    CommandLine LPSTR ? 
    str1 LPSTR ?
    Papi1 DWORD ? 
    Myapi1 DWORD ? 
    ApiBak1 db 10 dup(?) DllName1  db "kernel32.dll",0 
    ApiName1  db "CreateProcessW",0 ;未初始化数据 .data? 
    hHook dd ? 
    hWnd dd ? ;程序代码段 .code 
    ;**************************************************************** ;DLL入口点 DllEntry proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD 
      
      
    .if reason==DLL_PROCESS_ATTACH    ;当DLL加载时产生此事件 
            push hInst 
            pop hInstance invoke GetCommandLine  
    mov CommandLine,eax                                        ;取程序命令行 ;初始化 mov hacker.a,0B8h    ;mov eax, 
    ;mov hacker.d PMyapi  ;0x000000 
    mov hacker.d,0FFh    ;jmp 
    mov hacker.e, 0E0h    ;eax invoke  GetCurrentProcess                                  ;取进程伪句柄 mov WProcess ,eax 
        
    invoke GetApi,addr DllName1,addr ApiName1                    ;取API地址 
      
    mov Papi1,eax                                              ;保存API地址 invoke ReadProcessMemory,WProcess,Papi1,addr ApiBak1,8,NULL  ;备份原API的前8字节 mov hacker.PMyapi,offset MyAPI  ;0x000010                  ;要替代API的函数地址 invoke WriteApi,WProcess,Papi1, addr hacker ,size HOOKAPI    ;HOOK API .endif .if  reason==DLL_PROCESS_DETACH invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8              ;还原API .endif mov  eax,TRUE 
        ret 
    DllEntry Endp ;**************************************************************** 
    GetMsgProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD 
        invoke CallNextHookEx,hHook,nCode,wParam,lParam 
        mov eax,TRUE 
        
          ret 
    GetMsgProc endp ;**************************************************************** 
    InstallHook proc 
      
        invoke SetWindowsHookEx,WH_GETMESSAGE,addr GetMsgProc,hInstance,NULL 
        mov hHook,eax 
        ret 
    InstallHook endp UninstallHook proc 
        invoke UnhookWindowsHookEx,hHook 
      invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8 
      ret 
    UninstallHook endp 
    ;***************************************************************** GetApi proc DllNameAddress:DWORD,ApiNameAddress:DWORD invoke  GetModuleHandle,DllNameAddress    ;取DLL模块句柄 
      
      .if eax==NULL 
      
      invoke LoadLibrary ,DllNameAddress    ;加载DLL 
      
      .endif 
      
    invoke GetProcAddress,eax,ApiNameAddress  ;取API地址 
      mov eax,eax ret GetApi endp 
    ;*********************************下面是核心部分***************** WriteApi proc Process:DWORD ,Papi:DWORD,Ptype:DWORD,Psize:DWORD LOCAL mbi:MEMORY_BASIC_INFORMATION 
    LOCAL msize:DWORD 
    ;返回页面虚拟信息 
    invoke VirtualQueryEx,Process, Papi,addr mbi,SIZEOF MEMORY_BASIC_INFORMATION ;修改为可读写模式 invoke VirtualProtectEx,Process, mbi.BaseAddress,8h,PAGE_EXECUTE_READWRITE,addr mbi.Protect ;开始写内存 invoke  WriteProcessMemory,Process, Papi, Ptype,Psize ,NULL PUSH eax;改回只读模式 invoke VirtualProtectEx,Process,mbi.BaseAddress,8h,PAGE_EXECUTE_READ,addr mbi.Protect 
    pop eax
     
       ret WriteApi endp ;******************************************************************* 
    ;替代的API,参数要和原来一样 MyAPI proc lp1:DWORD ,lp2:DWORD,lp3:DWORD,lp4:DWORD,lp5:DWORD,lp6:DWORD,lp7:DWORD,lp8:DWORD,lp9:DWORD,lp10:DWORD, 
          
    mov eax,CommandLine
    ;mov CommandLine,eax
    invoke WideCharToMultiByte,CP_ACP, 0, lp2, 128, addr str1, 128,NULL,NULL                                       ;如果选择否 
    invoke MessageBoxEx, NULL,addr str1, CommandLine, 4,NULL 
    .if eax==7  
    invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8              ;先还原API 
    invoke CreateProcessW,lp1,lp2,lp3,lp4,lp5,lp6,lp7,lp8,lp9,lp10
    PUSH eax
    invoke WriteApi,WProcess,Papi1, addr hacker ,sizeof HOOKAPI  ;调用完后再改回来 pop eax
    ret.endifmov eax,0 
    retMyAPI endp ;******************************************************************* End DllEntry 
      

  3.   

    源代码可以在这里下载
    http://download.csdn.net/source/1402519
      

  4.   

    嗯,可惜汇编我早就不会编了,我一般用 API hook 也是用 IAT,不是修改的 jmp 指令。
    这样虽然可能漏掉(有的函数不一定会在输入表里面),
    但是由于不需要每次都修改和恢复 jmp,所以稳定性和效率上有很大提高。我在自己测试的时候,也借用了第三方工具来辅助,比如 APIMonitor。
    我想 lz 说的这个软件这个差不多,不过这个是老外编写的。
    http://www.apimonitor.com/我是自己参照了 n 多 CodeProject 上的文章自己编写的 API hook 类,不是采用的微软的 Detours。
    没想到这样的小东东居然还有人拿出来卖 320,真是... 没天理了
    要我自己做我也能做出来,全面的 hook 阶段我之前都已经写好了,并且测试没有问题
    (可以看 http://blog.csdn.net/DavidHsing/archive/2009/05/27/4219226.aspx)
    要接着做的话,只需要弄个 dll 做成全局钩子,注入到所有进程里面去。我看你第二段写的,是采用修改 jmp 指令的办法掉到我们自己的 API 函数体。
    由于我的方案不是这个,所以我对于这种方案也就没有仔细的 coding 和调试。
    给你两篇文章,希望对你有所帮助;API hooking revealed
    http://www.codeproject.com/KB/system/hooksys.aspxHooking the native API and controlling process creation on a system-wide basis
    http://www.codeproject.com/KB/system/soviet_protector.aspx
      

  5.   

    Hook 的函数是要和原函数的参数一模一样,你说的你不了解 LPSTARTUPINFO 的宽字符格式,
    MSDN 里面都有啊,不知道你说的格式是什么意思?里面的 LPTSTR 么?
    typedef struct _STARTUPINFO {
      DWORD cb;
      LPTSTR lpReserved;
      LPTSTR lpDesktop;
      LPTSTR lpTitle;
      DWORD dwX;
      DWORD dwY;
      DWORD dwXSize;
      DWORD dwYSize;
      DWORD dwXCountChars;
      DWORD dwYCountChars;
      DWORD dwFillAttribute;
      DWORD dwFlags;
      WORD wShowWindow;
      WORD cbReserved2;
      LPBYTE lpReserved2;
      HANDLE hStdInput;
      HANDLE hStdOutput;
      HANDLE hStdError;
    } STARTUPINFO,  *LPSTARTUPINFO;
      

  6.   

    就是改函数头
    mov eax, address
    jmp eax有点问题,改改吧,
    #define UNICODE
    #include <windows.h>
    #pragma comment(lib,"kernel32.lib")
    #pragma comment(lib, "user32.lib")typedef struct {
    BYTE a;
    DWORD b;
    BYTE c;
    BYTE d;
    } HACK;
    PROC m_pfnOrig; 
    //BYTE m_btNewBytes[8]; 
    HACK hack;
    BYTE m_btOldBytes[8]; 
    HMODULE m_hMod; 
    bool shutok;
    HHOOK hHook;
    HINSTANCE hInstance;
    BOOL  Rehook() 

    // 修改原API函数执行代码的前8个字节,使它跳向我们的函数 
    if(m_pfnOrig != NULL) 

    DWORD dwOldProtect; 
    MEMORY_BASIC_INFORMATION    mbi; 
    ::VirtualQuery( m_pfnOrig, &mbi, sizeof(mbi) ); 
    ::VirtualProtect(m_pfnOrig, 8, PAGE_READWRITE, &dwOldProtect);  // 写入新的执行代码 
    ::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, 
    &hack, sizeof(HACK), NULL);  ::VirtualProtect(m_pfnOrig, 8, mbi.Protect, 0); 
    return true; 

    return FALSE; 
    } BOOL WriteBack() 

    if(m_pfnOrig != NULL) 

    DWORD dwOldProtect; 
    MEMORY_BASIC_INFORMATION    mbi; 
    ::VirtualQuery(m_pfnOrig, &mbi, sizeof(mbi)); 
    ::VirtualProtect(m_pfnOrig, 8, PAGE_READWRITE, &dwOldProtect);  // 写入原来的执行代码 
    ::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, 
    m_btOldBytes, sizeof(DWORD)*2, NULL);  ::VirtualProtect(m_pfnOrig, 8, mbi.Protect, 0); 
    return true; 

    return false; 

    BOOL _declspec(naked) MyCreateProcessW( 
      LPCWSTR lpApplicationName, // pointer to name of executable module 
      LPWSTR lpCommandLine, // pointer to command line string 
      LPSECURITY_ATTRIBUTES lpProcessAttributes, // pointer to process security attributes 
      LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to thread security attributes 
      BOOL bInheritHandles, // handle inheritance flag 
      DWORD dwCreationFlags, // creation flags 
      LPVOID lpEnvironment, // pointer to new environment block 
      LPCWSTR lpCurrentDirectory, // pointer to current directory name 
      LPSTARTUPINFO lpStartupInfo, // pointer to STARTUPINFO 
      LPPROCESS_INFORMATION lpProcessInformation // pointer to PROCESS_INFORMATION  
      ) 

    WriteBack();  if (::MessageBoxW(NULL, GetCommandLineW(), lpApplicationName, 4) != 7) 

    BOOL shutok = ::CreateProcess( 
    lpApplicationName, // pointer to name of executable module 
    lpCommandLine, // pointer to command line string 
    lpProcessAttributes, // pointer to process security attributes 
    lpThreadAttributes, // pointer to thread security attributes 
    bInheritHandles, // handle inheritance flag 
    CREATE_SUSPENDED, // creation flags 
    lpEnvironment, // pointer to new environment block 
    lpCurrentDirectory, // pointer to current directory name 
    lpStartupInfo, // pointer to STARTUPINFO 
    lpProcessInformation // pointer to PROCESS_INFORMATION  
    );  //HANDLE hProcess1=ProcessInfo.hProcess; 
    //RemoteLoadLibrary(hProcess1,"hook.dll"); 
    //ResumeThread(ProcessInfo.hThread); 
    }  Rehook();  __asm 

    push shutok
    pop  eax
    ret 4

    }
    BOOL APIENTRY DllMain( HANDLE hModule, 
      DWORD  ul_reason_for_call, 
      LPVOID lpReserved 
      ) 
    {    
    //BYTE btNewBytes[8]={0xB8,0xE0,0x18,0x00,0x10,0xFF,0xE0,0x00}; 
    //memcpy(m_btNewBytes,btNewBytes,8);  if (ul_reason_for_call == DLL_PROCESS_ATTACH)    //当DLL加载时产生此事件 
    {  hInstance = (HINSTANCE)hModule; m_hMod = ::LoadLibrary(TEXT("kernel32.dll"));      //取API地址
    if (m_hMod == NULL)  { 
    m_pfnOrig=NULL; 
    return true; 
    }  m_pfnOrig = ::GetProcAddress(m_hMod, "CreateProcessW");  if (m_pfnOrig != NULL)  { 
    ZeroMemory(&hack, sizeof(HACK)); DWORD lpNewApi = (DWORD)MyCreateProcessW; hack.a = 0xB8;
    hack.b = lpNewApi;
    hack.c = 0xFF;
    hack.d = 0xE0; DWORD oldProc; 
    MEMORY_BASIC_INFORMATION  mbi;  ::VirtualQuery (m_pfnOrig,&mbi,sizeof(mbi)); 
    ::VirtualProtect( m_pfnOrig,8,PAGE_READWRITE,&oldProc); 
    memcpy(m_btOldBytes,m_pfnOrig,8); 
    ::WriteProcessMemory(::GetCurrentProcess(), (void*)m_pfnOrig, &hack, sizeof(HACK), NULL); 
    ::VirtualProtect( m_pfnOrig,8,mbi.Protect ,0); 
    return true; 


    if (ul_reason_for_call == DLL_PROCESS_DETACH)    //当DLL加载时产生此事件 

    WriteBack(); 
    return TRUE; 
    }  return TRUE; 

    LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam,LPARAM lParam)
    {
    return (LRESULT)CallNextHookEx(hHook, nCode, wParam, lParam);
    }void __declspec(dllexport) InstallHook()
    {
    hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hInstance, NULL);
    }void __declspec(dllexport) UninstallHook()
    {
    UnhookWindowsHookEx(hHook); 
    WriteBack();
    }
      

  7.   

    是这样的,由于你钩上了createprocessw以后
    你重新回调api的时候,默认调用的是createprocessa,这样的话就会出现参数错误的问题了
    而去掉用createprocessw的时候,vc会显示 LPSTARTUPINFO 的格式错误
    我用asm不用考虑这个直接用dword就ok了,vc就不行,主要是这个方面的问题!
      

  8.   

    只学过dos汇编,windows下的只能看懂。
      

  9.   


    明白了,原来绕了个圈,就是要调原函数啊。
    这个我用 IAT 的方式很好处理,jmp 的没仔细研究过。
      

  10.   

    像你说的 A 和 W 这种情况,一般来讲,是需要 hook 两个 API,A 和 W 版本的都要处理。
    因为可能有的程序编译是多字节,有的使用 Unicode,而作为全局钩子,要考虑到这两种情况,所以都需要处理。
    虽然两个的函数体逻辑可能差不多,甚至一样。
      

  11.   

    很遗憾 这个代码不对,因为dword值是32位的这样的时候插入到代码里就全部错误了我看了看其他代码只能用byte[4]然后把eax倒序插入才可以但是我用了这个办法后还是不对,还是希望有高手帮忙看一下
      

  12.   

     主要就这里不行
              DWORD lpNewApi = (DWORD)MyCreateProcessW;
                hack.b = lpNewApi;
    因为dword值在vc下是32位的
    而mov eax,offset MyCreateProcessW
    eax里的值是16位的
    不知道vc如何转换,希望高手帮忙
      

  13.   

    DWORD在哪都是32位的吧
    EAX也是32位的啊
    干吗要转换?
      

  14.   

    对于问题1:可以使用FlushInstructionCache直接执行机器码
      

  15.   

    现在应用层API HOOK满大街都是,连SSDT HOOK,INLINE HOOK 都满地爬了。
    逆向的话去去kanxue,debugman那里牛多
      

  16.   

    自己解决了直接写4个字节跟下源代码就知道的dword直接赋值eax不行