伪造返回地址绕过CallStack检测以及检测伪造返回地址的实践笔记

Author:[CISRG]KiSSinGGer
E-mail:kissingger@gmail.com
MSN:kyller_clemens@hotmail.com

题目有点搞......Anti-CallStack Check and Anti-Anti-CallStack Check...(;- -)

发现最近MJ0011的“基于CallStack的Anti-Rootkit HOOK检测思路”和gyzy的“基于栈指纹检测缓冲区溢出的一点思路”两篇文章有异曲同工之妙。
两者都通过检测CallStack中的返回地址来做文章。
最近在初步学习一些AntiRootkit技术,这两个不得不吸引我的眼球。

按照MJ0011大侠的逻辑,从Rootkit Detector的Hook点向上检测CallStack.
但是CallStack里面都是些DWORDs,怎么判断哪儿是参数,哪儿是返回地址呢?
我Goo了两把...普遍是用EBP回溯的方式.
考虑大部分的__stdcall的形式:
mov     edi edi
push     ebp
mov     ebp esp
...
...
我们从dword ptr [EBP]里面可以获得上个call的EBP,dword ptr [EBP+4]里面获得需要检测的返回地址,然后EBP = dword ptr [EBP],继续找下去.找到栈基址为止.
每次得到的返回地址,判断一下它是否在一个合法的模块中.

但是,根据gyzy大侠的<编写绕过卡巴主动防御的Shellcode>一文启示,我们可以知道如下一种方式,可使这样的检测方式失效.

1.在合法的系统模块里(e.g. ntoskrnl.exe),找到一个'C3'(ret Opcode)字节,它的指针是K.
2.使用如下方式的Hook函数

HookedZwXxx(...)
{
    //
    // 一些参数处理操作
    //
    
    jmp  __pushrealretaddr
    __trickstage:
    
    push     Arg[N]
    push     Arg[N-1]
    ...
    push  Arg[0]
    
    push     K
    jmp     ZwXxx; //调用原始函数
    
    __pushrealretaddr:
    call     __trickstage
    
    realretaddr:
    
    //
    //  另一些结果处理操作
    //    
}

这样,在ZwXxx深处检查调用栈,dword ptr [EBP+4]是一个处于合法模块中的地址K.

我写了一个如下的ring3示例程序.

定义如下一些函数:
int __stdcall Call_C(int a, int b)
{
    check_callstack();
    return a+b;
}

int __stdcall Call_B(int a, int b)
{
    return Call_C(a,b);
}

int __stdcall Call_A(int a, int b)
{
    return Call_B(a,b);
}

调用次序是A->
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值