对抗IDA分析备忘

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对抗IDA分析备忘相关的知识,希望对你有一定的参考价值。

参考 http://bobao.360.cn/learning/detail/4732.html

一、通过返回劫持技术欺骗IDA的 F5

    现在的反编译器一直在追求一个目标,就是准确识别并抽离编译器生成的低级簿记(bookkeeping)逻辑,这类信息包括函数的预处理代码段/结尾代码段或者控制流元数据

    反编译器会在输出结果中去掉这类信息,因为源代码级别并不会涉及到寄存器保存、栈帧空间分配管理等概念。下面是一种实例:

void __declspec(naked) Func()
{
    printf("hello 2");
    __asm
    {
        pop eax
        mov esp,ebp
        pop ebp
        ret
    }
}
unsigned int next = (unsigned int )Func;

void AntiMethod2()
{
    __asm
    {
        sub esp,4
        mov eax,next
        mov [esp],eax
        ret
    }
}

    使用IDA反编译结果如下,Func函数的调用明显被忽视了

    技术分享图片

 

二、正数SP(堆桟指针)值

    对IDA Pro而言,如果某个函数在返回之前没有清理已分配的堆桟(即平衡堆桟指针stack pointer sp),那么反编译器将拒绝处理该函数

    这种情况之所以出现,原因在于IDA无法合理的方式推断特定函数调用的类型定义。

    因此开发者可以将其作为反编译对抗技术,具体方法是使用不透明谓词技术来破坏堆栈指针的平衡状态,达到干扰效果。

    这里的add esp, 0x102永远不会被执行,但是反编译的时候栈帧已经被破坏了

void AntiMethod3()
{
    __asm
    {
        pop eax
        lea esp,[esp-4]
        cmp esp,0x1000
        ja _Label
        add esp,0x102
    }
_Label:
    __asm add esp,4
    printf("Hello Method3");
    __asm{
        mov esp,ebp
        pop ebp
        ret
    }
}

    结果F5如下:

技术分享图片

 

 三、碎片指令迷惑F5

    让反编译的结果和运行结果完全不一样  ,这里的xor和jz指令就是不让反编译器直接识别E8

 
void AntiMethod3()
{
    __asm
    {
        xor eax,eax
        jz _Label
        _emit 0xE8
    }
_Label:
    printf("Hello Method3");
}

    这里利用E8字节,让反编译的结果有一个call指令,但实际上我们并没有执行,反编译结果如下

技术分享图片

    F5结果如下:

技术分享图片

 

四:利用返回指令

    我们经常能看到这类函数,比如标准库中的exit()或者abort()函数都属于noreturn函数。

    在生成指定函数的伪代码时,反编译器会忽略调用noreturn函数后的任何代码。因为反编译器认为,调用类似exit()函数时,位于这些函数后面的代码永远得不到执行机会。技术分享图片

 

    

 

以上是关于对抗IDA分析备忘的主要内容,如果未能解决你的问题,请参考以下文章

IDA动态调试破解AliCrackme与反调试对抗

Android逆向笔记-通过tracerPid对抗IDA调试

恶意代码分析实战15-1

Android安全-代码安全4-逆向工具对抗

C#常用代码片段备忘

恶意代码分析实战15-2