• Windows下32位程序的Inline Hook


    话不多说,首先贴代码,代码主体参考自一本关于黑客技术的书,书名给忘了。

    当时只是敲出来跟着用,也没有深入理解,最近再看,才发现一些原理。

    Inline Hook的好处就是可以获取被Hook函数的参数,我们可以自行处理这些数据,再调用本来的Hook函数。

    #include <stdio.h>
    #include <windows.h>
    #include<iostream>
    using namespace std;
    class MyHook
    {
    public:
        MyHook()
        {
            funcAddr = NULL;
            ZeroMemory(oldBytes,5);
            ZeroMemory(newBytes,5);
        }
        ~MyHook()
        {
            UnHook();
            funcAddr = NULL;
            ZeroMemory(oldBytes,5);
            ZeroMemory(newBytes,5);
        }
        /*
         *Hook的模块名称,Hook的API函数名称,钩子函数地址
        */
        WINBOOL Hook(LPSTR ModuleName, LPSTR FuncName, PROC HookFunc)
        {
            BOOL bRet = FALSE;
            funcAddr = (PROC)GetProcAddress(GetModuleHandleA(ModuleName),FuncName);
            cout<<funcAddr<<endl;
            if(funcAddr!=NULL)
            {
                DWORD num = 0;
                ReadProcessMemory(GetCurrentProcess(),(void*)funcAddr,oldBytes,5,&num);
                newBytes[0] = 0xe9;
                *(DWORD *)(newBytes + 1) = (DWORD)HookFunc - (DWORD)funcAddr - 5;
                WriteProcessMemory(GetCurrentProcess(),(void*)funcAddr,newBytes,5,&num);
                bRet = TRUE;
            }
            return bRet;
        }
        void UnHook()
        {
            if(funcAddr!=0)
            {
                    DWORD num = 0;
                    WriteProcessMemory(GetCurrentProcess(),(void*)funcAddr,oldBytes,5,&num);
            }
        }
        WINBOOL ReHook()
        {
            BOOL ret = FALSE;
            if(funcAddr!=0)
            {
                DWORD num;
                WriteProcessMemory(GetCurrentProcess(),(void*)funcAddr,newBytes,5,&num);
                ret = TRUE;
            }
            return ret;
        }
    
    private:
        PROC funcAddr;
        BYTE oldBytes[5];
        BYTE newBytes[5];
    };
    
    MyHook hook;
    int WINAPI MyMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT type)
    {
        hook.UnHook();
        MessageBox(hWnd,"Hook流程",lpCaption,type);
        MessageBox(hWnd,lpText,lpCaption,type);
        hook.ReHook();
        return 0;
    }
    int main()
    {
        MessageBox(NULL,"正常流程1","test",MB_OK);
        hook.Hook((LPSTR)"User32.dll",(LPSTR)"MessageBoxA",(PROC)&MyMessageBoxA);
        MessageBox(NULL,"被Hook了1","test",MB_OK);
    //    MessageBox(NULL,"被Hook了2","test",MB_OK);
        hook.UnHook();
    //    MessageBox(NULL,"正常流程2","test",MB_OK); 
    }

    既不解释代码含义,也不解释Win32 API。需要注意的就是以下两点。

     首先来看图

    为什么是0xe9?
    0xe9代表jmp指令。
    但是图上不是EB吗?
    因为平时使用OD这样的调试工具,大多数情况下修改跳转,把jne之类的修改成jmp,
    都是修改成了EB,久而久之,就忘了,jmp有好几种跳转方式,这种修改应该是属于直接跳转。 Jmp
    short.(说是short,实际上是一个带符号的字节范围 -128~127)。 如图所示,地址0x00401200 和0x00401216,有着0x14个字节的指令,这就是直接跳转。
    1个字节,肯定不够我们跳转的,所以这里要用的是第2种跳转方式。再看另一副图

    从地址0x0041c3c1跳转到0x41c2ae,用的是E9 e8feffff
    因为32位下jmp远跳一共用了5字节的内存。
    E9 是jmp ,对应代码中的第一处
    剩下4字节保存的是 目的地址-起始地址-指令长度,对应代码中的第二处
    所以才有 0x41c2ae-0x41c3c1-5 = FFFFFEE8 。因为内存里面是小端,所以显示出来就是E8FEFFFF。

    一种比较好的测试方案,就是使用OD调试以上代码,ctrl+g跳转到MessageBoxA的地址处,看看随着代码的运行,该地址处的指令如何变化。

  • 相关阅读:
    《面试题 03.05. 栈排序》——惰性更新
    CTF<密码学> writeup 传统知识+古典密码
    有趣的数学(二)
    【】Dedecms友情链接去掉LI的方法介绍
    【】【】打工子弟学校学生们的中国梦何时圆?
    Discuz! 7.2 防注册机注册+发垃圾帖的解决方法
    Windows 8 常用快捷键
    Win7 64位系统下Auto CAD 2010注册激活,出现警告:Make sure you can write to current directory...
    怎么从EXCEL或WORD里提取图片?
    如何将windows xp系统下的outlook express6.0的邮件,帐号及通迅录导入Office Outlook xp/2003/2007中...
  • 原文地址:https://www.cnblogs.com/dayq/p/15808782.html
Copyright © 2020-2023  润新知