首页
社区
课程
招聘
未解决 [求助]hook 主线程调用A.dll 32位正常64位崩溃
发表于: 2020-9-2 23:14 2848

未解决 [求助]hook 主线程调用A.dll 32位正常64位崩溃

2020-9-2 23:14
2848

在主线程中将对A中函数进行hook,在32位正常,64位崩溃
如果加载B.dll,在b中hook A函数 32位、64位正常
整个程序只有1个线程

 

主进程

//头文件
extern int HXLocalHookProc(int x);
class CMainDlg
{
    HMODULE m_hDll;// , strFuncName.GetBuffer());
    //调用B.dll进行hook
    LRESULT OnDllHookOn(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    {
        CString strDll;
        strDll = L"HXHookDll.dll";
        CString szFuncName = "HXAddFunc";
        m_hDll = ::LoadLibrary(strDll);// , strFuncName.GetBuffer());
        return 0;
    }
    LRESULT OnDllHookOff(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    {
        if (m_hDll)
        {
            ::FreeLibrary(m_hDll);
        }
        return 0;
    }
    DWORD oldProtect;
    BYTE  JmpBtye[5];
    BYTE  OldByte[5];
        //主线程进行hook
    LRESULT OnLocalHookOn(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    {
        CString strDll;
        strDll = L"HXAdd.dll";
        CString szFuncName = "HXAddFunc";
        HMODULE hDll = ::LoadLibrary(strDll);// , strFuncName.GetBuffer());
        if (!hDll)
        {
            return S_FALSE;
        }

        typedef int(*pHXAdd)(int);
        pHXAdd addr = (pHXAdd)::GetProcAddress(hDll, "HXAddFunc");
        if (!addr)
        {
            return S_FALSE;
        }

        VirtualProtect((void*)addr, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
        JmpBtye[0] = 0xE9;
        *(DWORD*)&JmpBtye[1] = (DWORD)((long long)HXLocalHookProc - (long long)addr - 5);
        //保存原先字节
        memcpy(OldByte, (void*)addr, 5);
        //替换原先字节
        memcpy((void*)addr, JmpBtye, 5);
        return 0;
    }

    LRESULT OnLocalHookOff(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    {
        CString strDll;
        strDll = L"HXAdd.dll";
        CString szFuncName = "HXAddFunc";
        HMODULE hDll = ::LoadLibrary(strDll);// , strFuncName.GetBuffer());
        if (!hDll)
        {
            return S_FALSE;
        }

        typedef int(*pHXAdd)(int);
        pHXAdd addr = (pHXAdd)::GetProcAddress(hDll, "HXAddFunc");
        if (!addr)
        {
            return S_FALSE;
        }
        //恢复原先字节
        memcpy((void*)addr, OldByte, 5);
        //恢复属性
        DWORD p;
        VirtualProtect((void*)addr, 5, oldProtect, &p);

        return 0;
    }
    LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    {
        // TODO: Add validation code 
        int n = GetDlgItemInt(IDC_EDIT1);
        CString strText, strCaption;
        CString strDll;
        strDll = L"HXAdd.dll";
        CString szFuncName = "HXAddFunc";
        HMODULE hDll = ::LoadLibrary(strDll);// , strFuncName.GetBuffer());
        if (!hDll)
        {
            return S_FALSE;
        }

        typedef int(*pHXAdd)(int);
        pHXAdd pFunc = (pHXAdd)::GetProcAddress(hDll, "HXAddFunc");
        if (!pFunc)
        {
            return S_FALSE;
        }
                //32位先OnLocalHookOn再OnOK正常  64位崩溃
        n = pFunc(n);
        FreeLibrary(hDll);
        strText.Format(L"结果:%d", n);
        strCaption = L"结果";

        MessageBox(strText.GetBuffer(), strCaption.GetBuffer());
        return 0;
    }
}
//cpp
int HXLocalHookProc(int x)
{
    return x * x;
}

A.dll

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

int HXAddFunc(int x)
{
    return x + x;
}

B.dll

DWORD oldProtect;
BYTE  JmpBtye[5];
BYTE  OldByte[5];
void* OpenProcessaddr;
bool H1_OpenProcess();
void UnHook();
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_THREAD_ATTACH:
    case DLL_PROCESS_ATTACH:
        H1_OpenProcess();
        break;
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        UnHook();
        break;
    }
    return TRUE;
}

int MyOpenProcess(int x)
{
    return  x * 10;
}

void* F1_OpenProcess()
{
    //寻找到OpenProcess的地址
    void* addr = 0;
    //加载kernel32.dll
    HMODULE hModule = LoadLibrary(TEXT("HXAdd.dll"));
    if (!hModule)
    {
        return nullptr;
    }
    //获取OpenProcess的地址
    addr = (void*)GetProcAddress(hModule, "HXAddFunc");
    return addr;
}


void* F2_OpenProcess()
{
    return (void*)OpenProcess;
}

bool H1_OpenProcess()
{
    //1.开始寻找地址
    void* addr = F1_OpenProcess();
    OpenProcessaddr = addr;
    //判断是否寻找成功
    if (addr == 0)
    {
        MessageBox(NULL, TEXT("寻找地址失败"), NULL, 0);
        return false;
    }
    //2.进行Hook

    /*
    一般代码段是不可写的,我们需要把其改为可读可写.
    */
    VirtualProtect((void*)addr, 5, PAGE_EXECUTE_READWRITE, &oldProtect);

    //修改前面的5个字节为jmp 跳转到我们的代码.
    //内联Hook 跳转偏移计算方式:跳转偏移=目标地址-指令地址-5
    //jmp 的OpCode 为:0xE9

    JmpBtye[0] = 0xE9;
    *(DWORD*)&JmpBtye[1] = (DWORD)((long long)MyOpenProcess - (long long)addr - 5);
    //保存原先字节
    memcpy(OldByte, (void*)addr, 5);
    //替换原先字节
    memcpy((void*)addr, JmpBtye, 5);
    return true;
}

void UnHook()
{
    //恢复原先字节
    memcpy((void*)OpenProcessaddr, OldByte, 5);
    //恢复属性
    DWORD p;
    VirtualProtect((void*)OpenProcessaddr, 5, oldProtect, &p);
}

ps:代码来自:https://www.kanxue.com/chm.htm?id=13104&pid=node1000838


[课程]FART 脱壳王!加量不加价!FART作者讲授!

最后于 2020-9-2 23:19 被乄羽落编辑 ,原因:
上传的附件:
收藏
免费 1
支持
分享
最新回复 (3)
雪    币: 6124
活跃值: (4466)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
2
你的代码我没有细看,大概看了一下,问题又几点:
1.x64下的hook最好使用一个跳板(7字节hook),而不是5字节。
2.x64下的调用约定统一为__fastcall
3.如果你不了解32位和64位的差异请使用框架,如:Detours、EasyHook、PloyHook等,这样就不必关心技术细节也能够在x64下hook
2020-9-3 00:28
0
雪    币: 288
活跃值: (247)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3

谢谢  

找到一个参照例子  能正常使用

https://www.dllhook.com/post/13.html

    HOOK原理如下:
     
    // HOOK指令长度
    #define HOOK_LEN 0xC
    // 保存原始指令
    BYTE Ori_Code[HOOK_LEN] = {0x00}; 
     
    // Hook代码
    /*   方式一
    MOV RAX, 0x9090909090909090
    PUSH RAX
    RET
    */
    BYTE HookCode[HOOK_LEN] = 
    {
        0x48, 0xB8, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x50, 0xC3
    };
     
    /*   方式二
    MOV RAX, 0x9090909090909090
    JMP RAX
    */
    /*
    BYTE HookCode[HOOK_LEN] = 
    {
        0x48, 0xB8, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xFF, 0xE0
    };
    */
     
     
    VOID HookAPI();
    VOID UnHookAPI();
     
    static int (WINAPI *kernel_MessageBoxW)(
        HWND hWnd,
        LPCTSTR lpText,
        LPCTSTR lpCaption,
        UINT uType
        ) = MessageBoxW;
     
    int WINAPI MyMessageBoxW(
        HWND hWnd,
        LPCTSTR lpText,
        LPCTSTR lpCaption,
        UINT uType
        )
    {
        UnHookAPI();
        int ret = kernel_MessageBoxW(hWnd, TEXT("Hooked!!"), TEXT("hi"), MB_OK);
        HookAPI();
        return ret;
    }
     
    VOID HookAPI()
    {
        DWORD OldProtect;
        ::VirtualProtect(kernel_MessageBoxW, HOOK_LEN, PAGE_EXECUTE_READWRITE, &OldProtect);
        // 得到原始指令
        memcpy(Ori_Code, kernel_MessageBoxW, HOOK_LEN);  
        // 填充跳转地址
        *(PINT64)(HookCode+2) = (INT64)&MyMessageBoxW;
        memcpy(kernel_MessageBoxW, &HookCode, sizeof(HookCode));
    }
     
    VOID UnHookAPI()
    {
        memcpy(kernel_MessageBoxW, &Ori_Code, sizeof(HookCode));    
    }
     
    VOID main()
    {
        MessageBoxW(NULL, TEXT("hello"), TEXT("P.Y.G"), MB_OK);
        HookAPI();
        MessageBoxW(NULL, TEXT("hello"), TEXT("P.Y.G"), MB_OK);
        system("pause");
    }


2020-9-3 11:06
0
雪    币: 11974
活跃值: (5554)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
你原先加载B这个dll能64位正常使用,完全是因为B中代理函数的基址凑巧处于这个区间罢了[A函数基址-2GB, A函数基址+2GB),要是系统给B申请的基址和A相差过多,0xE9这个指令是跳不过去的
2020-9-3 14:28
0
游客
登录 | 注册 方可回帖
返回
//