首页
社区
课程
招聘
一个HOOK后遗症问题
发表于: 2022-6-16 17:05 7179

一个HOOK后遗症问题

2022-6-16 17:05
7179

菜鸟贴,请各位指教!
图片描述

 

上面是我的c++代码,我对加密与解密里面的代码进行了修改,想通过替换掉kernel32中的VirtualAlloc的内部调用的kernel32._impVirtualAllocEx,来跳转到自定义的LPVOID WINAPI DetourVirtualAllocEx中。
汇编如下:
ff 25 9413e875 jmp kernel32._imp
VirtualAllocEx
然后跳过原来的那个kernel32._imp__VirtualAllocEx(不去执行了)。就是直接替换掉。
我按照右边的代码去执行之后,产生了栈的检测错误:
图片描述
经过调试,当我正常调用VirtualAlloc的时候,在内部函数中的返回是retn10:
图片描述
而我自己写的HOOK函数中,最后的ret是14:
图片描述
多pop了4个byte,
图片描述
后来我用x32dbg进行补丁处理,把这个地方改成retn 10就没问题了。
图片描述
图片描述
图片描述
为什么会这样呢?我的理解是如果按照WINAPI的调用约定,应该是被调函数内部做栈平衡,怎么vs2010生成出来的,就多pop了4个byte呢?


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 2
支持
分享
最新回复 (19)
雪    币: 341
活跃值: (1005)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2

:)

最后于 2022-6-16 18:10 被fatcateatrat编辑 ,原因:
2022-6-16 18:08
0
雪    币: 203
活跃值: (1092)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
发样本,没看懂你的意思
2022-6-16 18:10
0
雪    币: 6124
活跃值: (4666)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
4
像这样的错误 有两个可能性,第一个是你的Detour函数 调用约定声明不对,第二个 用release编译
2022-6-16 20:48
0
雪    币: 775
活跃值: (3420)
能力值: ( LV7,RANK:140 )
在线值:
发帖
回帖
粉丝
5
你这里出现了VirtualAlloc和VirtualAllocEx,是不是哪里搞混了
2022-6-16 21:08
0
雪    币: 335
活跃值: (786)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
戒烟 发样本,没看懂你的意思
所有的代码都贴在最上面了。。
2022-6-17 08:23
0
雪    币: 335
活跃值: (786)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
yeyeshun 你这里出现了VirtualAlloc和VirtualAllocEx,是不是哪里搞混了
没有混的。。。
2022-6-17 08:24
0
雪    币: 335
活跃值: (786)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
黑洛 像这样的错误 有两个可能性,第一个是你的Detour函数 调用约定声明不对,第二个 用release编译
/////////////////////////////////////////////////////////////////
//         第13章  Hook技术 《加密与解密(第四版)》           //
//                                                             //
//         Author: achillis(黑月教主)                          //
//         Blog  : http://www.cnblogs.com/achillis/            //
//         QQ    : 344132161                                   //
//         Email : achillis@126.com                            //
//         转载请保留作者信息                                  //
//         (c)  看雪学院 www.kanxue.com 2000-2018              //
/////////////////////////////////////////////////////////////////

//本程序的功能是对VirtualAlloc函数进行call Hook

#include <windows.h>
#include <stdio.h>
#include <CONIO.H>

ULONG g_PointerToRawData = 0 ;
ULONG g_RawOffset = 0 ;

LPVOID GetAddress(char *,char *);
LPVOID WINAPI DetourVirtualAllocEx(
    HANDLE hProcess,  // process within which to allocate memory
    LPVOID lpAddress, // desired starting address of allocation
    DWORD dwSize,     // size, in bytes, of region to allocate
    DWORD flAllocationType,    // type of allocation
    DWORD flProtect   // type of access protection
    );
BOOL Inline_InstallHook(void);
BOOL Inline_UnInstallHook();
VOID TestHook();

int main(int argc, char* argv[])
{
    TestHook();
    Inline_InstallHook();
    TestHook();
    //Inline_UnInstallHook();
    printf( "yes i am ok\n" );
    getchar();
    return 0;
}

VOID TestHook()
{
    LPVOID lpAddr = VirtualAlloc(NULL,0x1000,MEM_COMMIT,PAGE_READWRITE);
}

LPVOID WINAPI DetourVirtualAllocEx(
    HANDLE hProcess,  // process within which to allocate memory
    LPVOID lpAddress, // desired starting address of allocation
    SIZE_T dwSize,     // size, in bytes, of region to allocate
    DWORD flAllocationType,                            // type of allocation
    DWORD flProtect   // type of access protection
    )
{    LPVOID lpAddr = NULL ;
    printf("[DetourVirtualAllocEx] VirtualAllocEx called.\n");
    lpAddr = VirtualAllocEx(hProcess,lpAddress,dwSize,flAllocationType,flProtect);
    printf("[DetourVirtualAllocEx] Alloced Buffer = 0x%X\n",lpAddr);
    return lpAddr;
}

DWORD G_OldAddress = 0;
DWORD G_NewAddress = 0;

/*
7C809AF1 >  8BFF                 mov edi,edi
7C809AF3    55                   push ebp
7C809AF4    8BEC                 mov ebp,esp
7C809AF6    FF75 14              push dword ptr ss:[ebp+14]
7C809AF9    FF75 10              push dword ptr ss:[ebp+10]
7C809AFC    FF75 0C              push dword ptr ss:[ebp+C]
7C809AFF    FF75 08              push dword ptr ss:[ebp+8]
7C809B02    6A FF                push -1
7C809B04    E8 09000000          call kernel32.VirtualAllocEx
7C809B09    5D                   pop ebp
7C809B0A    C2 1000              retn 10
*/
BOOL Inline_InstallHook()
{
    HMODULE hModule_ = LoadLibraryA( "kernel32.dll" ); 
    //准备Hook
    BOOL bFound = FALSE;
    BOOL bResult = FALSE ;
    ULONG addrTemp = 0 ;
    ULONG addrTargetFun = (ULONG)GetAddress("kernel32.dll","VirtualAllocEx");
    PBYTE pFun = (PBYTE)GetAddress("kernel32.dll","VirtualAlloc");
    PBYTE pBase = pFun;
    int i = 0 ;
    for (i=0;i<0x30;i++,pFun++)
    {
        // 7C809B04    E8 09000000          call kernel32.VirtualAllocEx
        // 9413e875       ff 25 9413e875        jmp  kernel32._imp__VirtualAllocEx
        // ssj 2022.6.16
        // 这里的思想是搜索kernel32.dll中的VirtualAlloc,他会jmp去调用kernel32._imp__VirtualAllocEx
        // 在这个vs2010里面,我们找到jmp指令的值是ff,25,修改里面的地址为自定义的函数。
        if (pFun[0] == 0xff && pFun[1] == 0x25)
        {
            union{
                byte bb_[4];
                DWORD address_;
            };
            bb_[0] = pFun[2];
            bb_[1] = pFun[3];
            bb_[2] = pFun[4];
            bb_[3] = pFun[5];

            G_OldAddress = address_;

            DWORD *jmpAddress_ = reinterpret_cast<DWORD*>( G_OldAddress );

            MEMORY_BASIC_INFORMATION mbInfor_;
            VirtualQuery( jmpAddress_, &mbInfor_, sizeof( mbInfor_ ) );

            SIZE_T wwww;

            addrTemp = (LONG)DetourVirtualAllocEx;
            G_NewAddress = addrTemp;

            DWORD oldProtect_;
            VirtualProtect( mbInfor_.BaseAddress, mbInfor_.RegionSize, PAGE_EXECUTE_READWRITE, &oldProtect_ );
            bResult = WriteProcessMemory( GetCurrentProcess( ), jmpAddress_, &addrTemp, sizeof(LONG), &wwww);
            VirtualProtect( mbInfor_.BaseAddress, mbInfor_.RegionSize, oldProtect_, nullptr );

            int aa = 0;
            bResult = FALSE;

            break;

            //addrTemp = (ULONG)pFun + 5 + *(LONG*)(pFun+1);
            //if (addrTemp == addrTargetFun) //判断call的目标地址是不是VirtualAllocEx
            //{
            //    bResult = TRUE;
            //    break;
            //}
        }
    }
    
    if (bResult)
    {
        //开始Hook
        g_PointerToRawData = (ULONG)pFun + 1 ;
        g_RawOffset = *(LONG*)(pFun+1) ;
        addrTemp = (LONG)DetourVirtualAllocEx - (LONG)pFun - 5 ;
        bResult = WriteProcessMemory(GetCurrentProcess(),pFun+1,&addrTemp,sizeof(LONG),NULL);
    }

    return bResult;
}


BOOL Inline_UnInstallHook()
{
    DWORD addrTemp = g_RawOffset ;
    return WriteProcessMemory(GetCurrentProcess(),(LPVOID)g_PointerToRawData,&addrTemp,sizeof(LONG),NULL);
}


//获取指定模块中指定API的地址
LPVOID GetAddress(char *dllname,char *funname)
{
    HMODULE hMod=0;
    if (hMod=GetModuleHandle(dllname))
    {
        return GetProcAddress(hMod,funname);
    } 
    else
    {
        hMod=LoadLibrary(dllname);
        return GetProcAddress(hMod,funname);
    }
    
}
2022-6-17 08:34
0
雪    币: 335
活跃值: (786)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
yeyeshun 你这里出现了VirtualAlloc和VirtualAllocEx,是不是哪里搞混了

我编译成release版本也是

2022-6-17 08:38
0
雪    币: 364
活跃值: (1736)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
VirtualAlloc   4个参数 ret 10h     VirtualAllocEx 5个参数 ret 14h
2022-6-17 09:25
0
雪    币: 335
活跃值: (786)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
LPVOID WINAPI DetourVirtualAllocEx(
    HANDLE hProcess,  // process within which to allocate memory
    LPVOID lpAddress, // desired starting address of allocation
    SIZE_T dwSize,     // size, in bytes, of region to allocate
    DWORD flAllocationType,                            // type of allocation
    DWORD flProtect   // type of access protection
    )
{    LPVOID lpAddr = NULL ;
    printf("[DetourVirtualAllocEx] VirtualAllocEx called.\n");
    lpAddr = VirtualAllocEx(hProcess,lpAddress,dwSize,flAllocationType,flProtect);
    printf("[DetourVirtualAllocEx] Alloced Buffer = 0x%X\n",lpAddr);
    return lpAddr;
}
 我这里定义的也是5个参数呢。。
2022-6-17 11:32
0
雪    币: 8715
活跃值: (8619)
能力值: ( LV13,RANK:570 )
在线值:
发帖
回帖
粉丝
12
黑月教主是那位写易语言C编译器的大佬嘛
2022-6-17 11:57
0
雪    币: 10251
活跃值: (4426)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
addrTargetFun是VirtualAllocEx,pFun却是VirtualAlloc,用VirtualAllocEx hook VirtualAlloc?
2022-6-17 13:05
0
雪    币: 335
活跃值: (786)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
superlover addrTargetFun是VirtualAllocEx,pFun却是VirtualAlloc,用VirtualAllocEx hook VirtualAlloc?
我是用DetourVirtualAllocEx来hook掉VirtualAllocEx
2022-6-17 14:40
0
雪    币: 3116
活跃值: (1269)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
15

刚看了下,新系统里面有stub存在,有可能是你get VirtualAlloc的时候,取的是VirtualAllocStub,然后在里面搜索ff 25 的时候,搜索出来的还是 VirtualAlloc。 

 你可以把你get出来的地址,u一下看下汇编代码

KERNEL32!VirtualAllocStub:
75855ed0 8bff            mov     edi,edi
75855ed2 55              push    ebp
75855ed3 8bec            mov     ebp,esp
75855ed5 5d              pop     ebp
75855ed6 ff2510138c75    jmp     dword ptr [KERNEL32!_imp__VirtualAlloc (758c1310)]
75855edc cc              int     3


2022-6-17 15:46
0
雪    币: 7379
活跃值: (4086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
hello,hook LPVOID WINAPI DetourVirtualAllocEx(    HANDLE hProcess,  // process within which to allocate memor ...

正是因为你定义的是5个参数,所以RENT 14啊,RENT 10的virtualalloc函数,这个函数只有4个参数,这不是很明白的吗。另外我WIN7系统kernel32.virtualalloc函数内部通过JMP跳转的到的是kernelbase.virtualalloc而不是kernel32.virtualallocex,所以通过替换JMP后面的数值的话替换的是kernelbase.virtualalloc,这个函数同样只有4个参数,需要RENT 10才能正常运行

最后于 2022-6-17 20:52 被htpidk编辑 ,原因:
2022-6-17 20:24
0
雪    币: 775
活跃值: (3420)
能力值: ( LV7,RANK:140 )
在线值:
发帖
回帖
粉丝
17
zhouws 刚看了下,新系统里面有stub存在,有可能是你get VirtualAlloc的时候,取的是VirtualAllocStub,然后在里面搜索ff 25 的时候,搜索出来的还是 VirtualAlloc ...
我觉得你说的靠谱
2022-6-17 22:11
0
雪    币: 335
活跃值: (786)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18

你说的是对的,这个jmp到kernelbase的VirtualAlloc了,不是我认为的VirtualAllocEx(5个参数)。而kernelbase的VirtualAlloc中的参数是4个。所以问题出现了。非常感谢大家!


2022-6-18 08:40
0
雪    币: 335
活跃值: (786)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
htpidk hello,hook LPVOID WINAPI DetourVirtualAllocEx( &nbsp; &nbsp;HAN ...
你说的是对的
2022-6-18 08:41
0
雪    币: 335
活跃值: (786)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
htpidk hello,hook LPVOID WINAPI DetourVirtualAllocEx( &nbsp; &nbsp;HAN ...

把第一个参数去掉就ok了。。。

2022-6-18 08:44
0
游客
登录 | 注册 方可回帖
返回
//