首页
社区
课程
招聘
1
[分享]一种更激进的Hook实现方案猜想。
发表于: 4天前 1732

[分享]一种更激进的Hook实现方案猜想。

4天前
1732

昨天才发现不是原创,这种方案是VEH HOOK的一种实现方案。VEH HOOK很久很久以前都被广泛使用了。只是自己没听说过。好悲哀呀。。。。

如果VEH HOOK在内核态处理异常获取函数参数会变成什么样子呢

代码模拟:

程序输出

本人编码能力比较弱所以只能靠windbg大哥哥了去吧皮卡丘,皮卡皮卡皮卡
以下为Windows7 x64 sp1的简单逆向。

接下来就是感兴趣的童鞋开始简单粗暴的验证了。

系统提供服务接口,以dll形式提供,如创建文件CreateFile存在于kernel32.dll,访问网络WSAConnect存在于Ws2_32.dll。API是函数,所在页属性为**可读和执行**
系统提供服务接口,以dll形式提供,如创建文件CreateFile存在于kernel32.dll,访问网络WSAConnect存在于Ws2_32.dll。API是函数,所在页属性为**可读和执行**
如果把API所在页的**内存页属性改为不可以执行** ,执行API时候就会产生异常,若是能捕获该异常在异常处理程序中就可以获取异常发生的地址,通过地址可以反查询调用的API信息,在从异常中获取参数。同时将该异常所在页的属性改为**可以执行**,将调用地址所在的页设置成**不可以执行**。这样当API执行完之后返回到调用地址时又产生异常,此时在异常处理程序中获取API的返回值。重复以上操作就可以了。
```。
利用Exception 来实现Hook Api。在Exception处理程序里获得参数和返回值。
如果把API所在页的**内存页属性改为不可以执行** ,执行API时候就会产生异常,若是能捕获该异常在异常处理程序中就可以获取异常发生的地址,通过地址可以反查询调用的API信息,在从异常中获取参数。同时将该异常所在页的属性改为**可以执行**,将调用地址所在的页设置成**不可以执行**。这样当API执行完之后返回到调用地址时又产生异常,此时在异常处理程序中获取API的返回值。重复以上操作就可以了。
```。
利用Exception 来实现Hook Api。在Exception处理程序里获得参数和返回值。
PVOID HeapMemory = NULL;
PVOID MainFunctionAddress = NULL;
int RunFunction(int* a, int* b){
    *a = *a + 1;    *b = *b + 1;return *a + *b;
}
 
VOID main(int argc, char* argv[])
{
    MainFunctionAddress = GetDbgFunctionPointerAddress(main);
     
    //申请内存属性为读写权限
    HeapMemory = VirtualAlloc(NULL, PAGE_SIZE, MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
    int a=1, b=11;
    LPVOID Address = (LPVOID)RunFunction;
    Address = GetDbgFunctionPointerAddress(RunFunction);
    //将RunFunction的内容复制到HeapMemory。
    RtlCopyMemory(HeapMemory, Address, 0x3b);
    ZxDebug(("HeapMemory = %p MainFunctionAddress=%p \n", HeapMemory, MainFunctionAddress));
    __try
    {
        //执行HeapMemory,asmcall jmp r8
        //内存属性为读写,执行函数会产生异常
        for(int i =0 ; i < 3; i++)
            asmcall((PVOID)&a, (PVOID)&b, HeapMemory);
    }__except(FilterException(GetExceptionCode(), GetExceptionInformation()))
    {
        ZxDebug((__FUNCTION__"():: EXCEPTION_EXECUTE_HANDLE\n"));
    }
    ZxDebug((__FUNCTION__"():: a = %d b = %d\n", a, b));
}
 
int FilterException(ULONG ExceptionCode, _EXCEPTION_POINTERS* Exception)
{
    MEMORY_BASIC_INFORMATION Mbi={};
    SIZE_T Size = VirtualQuery(Exception->ExceptionRecord->ExceptionAddress, &Mbi, sizeof(MEMORY_BASIC_INFORMATION));
    DWORD flOldProtect = 0;
    ZxDebug((__FUNCTION__"():: ExceptionAddress:%p \n", Exception->ExceptionRecord->ExceptionAddress));
    if (Exception->ExceptionRecord->ExceptionAddress == HeapMemory)
    {
        assert(ExceptionCode == STATUS_ACCESS_VIOLATION && Mbi.Protect == PAGE_READWRITE);
        assert(Exception->ExceptionRecord->ExceptionAddress == HeapMemory);
        PVOID NextRip = (PVOID)(*(ULONG_PTR*)Exception->ContextRecord->Rsp);
        int a = *(int*)Exception->ContextRecord->Rcx; int b = *(int*)Exception->ContextRecord->Rdx;
        ZxDebug((__FUNCTION__"():: RunFunction(a = %d b= %d) NextRip=%p\n", a, b, NextRip));
        //将HeapMemory内存属性改为可执行。将Main函数改为不可执行
        VirtualProtect(HeapMemory, PAGE_SIZE, PAGE_EXECUTE_READ,&flOldProtect);
        VirtualProtect((PVOID)MainFunctionAddress, PAGE_SIZE, PAGE_READWRITE,&flOldProtect);
    }else
    {
        assert(ExceptionCode == STATUS_ACCESS_VIOLATION && Mbi.Protect == PAGE_READWRITE);
        if ((ULONG_PTR)MainFunctionAddress <= (ULONG_PTR)Exception->ExceptionRecord->ExceptionAddress
            &&(ULONG_PTR)Exception->ExceptionRecord->ExceptionAddress <= (ULONG_PTR)MainFunctionAddress +PAGE_SIZE)
        {
            int Ret = (Exception->ContextRecord->Rax);
            PVOID NextRip = (PVOID)(*(ULONG_PTR*)Exception->ContextRecord->Rsp);
            ZxDebug((__FUNCTION__"():: (%d)RunFunction(a , b) NextRip=%p\n", Ret, NextRip));
            //将Main函数改为可执行
            VirtualProtect((PVOID)MainFunctionAddress, PAGE_SIZE, PAGE_EXECUTE_READ,&flOldProtect);
            //将HeapMemory内存属性改为不可执行。
            VirtualProtect(HeapMemory, PAGE_SIZE, PAGE_READWRITE,&flOldProtect);
        }
 
    }
 
    return EXCEPTION_CONTINUE_EXECUTION;
}
PVOID HeapMemory = NULL;
PVOID MainFunctionAddress = NULL;
int RunFunction(int* a, int* b){
    *a = *a + 1;    *b = *b + 1;return *a + *b;
}
 
VOID main(int argc, char* argv[])
{
    MainFunctionAddress = GetDbgFunctionPointerAddress(main);
     
    //申请内存属性为读写权限
    HeapMemory = VirtualAlloc(NULL, PAGE_SIZE, MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
    int a=1, b=11;
    LPVOID Address = (LPVOID)RunFunction;
    Address = GetDbgFunctionPointerAddress(RunFunction);
    //将RunFunction的内容复制到HeapMemory。
    RtlCopyMemory(HeapMemory, Address, 0x3b);
    ZxDebug(("HeapMemory = %p MainFunctionAddress=%p \n", HeapMemory, MainFunctionAddress));
    __try
    {
        //执行HeapMemory,asmcall jmp r8
        //内存属性为读写,执行函数会产生异常
        for(int i =0 ; i < 3; i++)
            asmcall((PVOID)&a, (PVOID)&b, HeapMemory);
    }__except(FilterException(GetExceptionCode(), GetExceptionInformation()))
    {
        ZxDebug((__FUNCTION__"():: EXCEPTION_EXECUTE_HANDLE\n"));
    }
    ZxDebug((__FUNCTION__"():: a = %d b = %d\n", a, b));
}
 
int FilterException(ULONG ExceptionCode, _EXCEPTION_POINTERS* Exception)
{
    MEMORY_BASIC_INFORMATION Mbi={};
    SIZE_T Size = VirtualQuery(Exception->ExceptionRecord->ExceptionAddress, &Mbi, sizeof(MEMORY_BASIC_INFORMATION));
    DWORD flOldProtect = 0;
    ZxDebug((__FUNCTION__"():: ExceptionAddress:%p \n", Exception->ExceptionRecord->ExceptionAddress));
    if (Exception->ExceptionRecord->ExceptionAddress == HeapMemory)
    {
        assert(ExceptionCode == STATUS_ACCESS_VIOLATION && Mbi.Protect == PAGE_READWRITE);

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

最后于 1天前 被NoHeart编辑 ,原因:
收藏
免费 1
支持
分享
赞赏记录
参与人
雪币
留言
时间
nig
非常支持你的观点!
1天前
最新回复 (13)
雪    币: 1129
活跃值: (2901)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
"内存断点"
4天前
0
雪    币: 141
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
Oday小斯 "内存断点"
约等于内存断点吧。
4天前
0
雪    币: 141
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
Oday小斯 "内存断点"
抱歉昨天才了解到这是VEH Hook
1天前
0
雪    币: 413
活跃值: (752)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
5
有想法就是好事。
1天前
0
雪    币: 141
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
nig 有想法就是好事。
嗯嗯。
1天前
0
雪    币: 141
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
简简单单逆向了内核,提供VEH 内核获取参数值的思路,思路没做验证。
1天前
0
雪    币: 4037
活跃值: (3312)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
有种内存属性叫PAGE_GUARD(
1天前
0
雪    币: 141
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
ANormalUser 有种内存属性叫PAGE_GUARD(
PAGE_GUARD 和dll导出表中的函数没啥关系吧。
1天前
0
雪    币: 4037
活跃值: (3312)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
NoHeart PAGE_GUARD 和dll导出表中的函数没啥关系吧。
不是说和导出函数的关系,是系统本身就预留了PAGE_GUARD的属性位,根本不需要改内存RWX就能触发特定异常
1天前
0
雪    币: 141
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
ANormalUser 不是说和导出函数的关系,是系统本身就预留了PAGE_GUARD的属性位,根本不需要改内存RWX就能触发特定异常
嗯嗯,多谢指点
1天前
0
雪    币: 1628
活跃值: (3512)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
我想知道的是如何在内核不触发PG接管异常
17小时前
0
雪    币: 141
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
tmflxw 我想知道的是如何在内核不触发PG接管异常
这种方案只适合沙箱。。。。。
17小时前
0
雪    币: 141
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
tmflxw 我想知道的是如何在内核不触发PG接管异常

这只是版本迭代中缺失的一个版本,用理论来补齐。可以参考虚拟化版本[原创] Intel 虚拟化特性实现监视进程API 调用(工具)

最后于 17小时前 被NoHeart编辑 ,原因:
17小时前
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册
//