设为首页收藏本站
查看: 3032|回复: 0

[原创] [翻译]反调试:异常

[复制链接]
  • TA的每日心情
    开心
    2022-1-9 18:41
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2021-9-12 15:30:23 | 显示全部楼层 |阅读模式
    备注
    原文地址:https://anti-debug.checkpoint.com/techniques/exceptions.html
    原文标题:Anti-Debug: Exceptions
    更新日期:2021年6月10日
    此文后期:根据自身所学进行内容扩充
    因自身技术有限,只能尽自身所能翻译国外技术文章,供大家学习,若有不当或可完善的地方,希望可以指出,用于共同完善这篇文章。

    目录
    • 异常
    • 1. UnhandledExceptionFilter()
    • 2. RaiseException()
    • 3. 用异常处理程序来隐藏控制流
    • 反制措施

    异常
    下面的方法故意导致异常,以验证进一步的行为对于没有调试器运行的进程是否不是典型的。

    1. UnhandledExceptionFilter()
    如果一个异常发生而没有注册异常处理程序(或者已经注册但没有处理这样的异常),kernel32!UnhandledExceptionFilter()函数将被调用。可以使用kernel32!SetUnhandledExceptionFilter()来注册一个自定义的未处理异常过滤器。但是如果程序在调试器下运行,自定义的过滤器将不会被调用,异常将被传递给调试器。因此,如果未处理的异常过滤器被注册,并且控制被传递给它,那么这个进程就不是在调试器下运行。
    x86 汇编 (FASM):
    1. include 'win32ax.inc'

    2. .code

    3. start:
    4.         jmp begin

    5. not_debugged:
    6.         invoke  MessageBox,HWND_DESKTOP,"Not Debugged","",MB_OK
    7.         invoke  ExitProcess,0

    8. begin:
    9.         invoke SetUnhandledExceptionFilter, not_debugged
    10.         int  3
    11.         jmp  being_debugged

    12. being_debugged:
    13.         invoke  MessageBox,HWND_DESKTOP,"Debugged","",MB_OK
    14.         invoke  ExitProcess,0

    15. .end start
    复制代码

    C/C++ 代码:
    1. LONG UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
    2. {
    3.     PCONTEXT ctx = pExceptionInfo->ContextRecord;
    4.     ctx->Eip += 3; // Skip \xCC\xEB\x??
    5.     return EXCEPTION_CONTINUE_EXECUTION;
    6. }

    7. bool Check()
    8. {
    9.     bool bDebugged = true;
    10.     SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)UnhandledExceptionFilter);
    11.     __asm
    12.     {
    13.         int 3                      // CC
    14.         jmp near being_debugged    // EB ??
    15.     }
    16.     bDebugged = false;

    17. being_debugged:
    18.     return bDebugged;
    19. }
    复制代码


    2. RaiseException()
    诸如DBC_CONTROL_C或DBG_RIPEVENT之类的异常不会传递给当前进程的异常处理程序,而是由调试器使用。这让我们注册一个异常处理程序,使用kernel32!RaiseException()函数,并检查控件是否传递给了我们的处理程序。如果未调用异常处理程序,则该进程可能正在调试中。
    C/C++ 代码:
    1. bool Check()
    2. {
    3.     __try
    4.     {
    5.         RaiseException(DBG_CONTROL_C, 0, 0, NULL);
    6.         return true;
    7.     }
    8.     __except(DBG_CONTROL_C == GetExceptionCode()
    9.         ? EXCEPTION_EXECUTE_HANDLER
    10.         : EXCEPTION_CONTINUE_SEARCH)
    11.     {
    12.         return false;
    13.     }
    14. }
    复制代码


    3. 用异常处理程序来隐藏控制流
    这种方法不能检查调试器是否存在,但它有助于在异常处理程序的序列中隐藏程序的控制流。

    我们可以注册一个异常处理程序(结构化的或矢量的),引发另一个异常,这个异常被传递给下一个处理程序,引发下一个异常,以此类推。最后,处理程序的序列应该通向我们想要隐藏的程序
    使用结构化异常处理程序:
    C/C++ 代码:
    1. #include <Windows.h>

    2. void MaliciousEntry()
    3. {
    4.     // ...
    5. }

    6. void Trampoline2()
    7. {
    8.     __try
    9.     {
    10.         __asm int 3;
    11.     }
    12.     __except (EXCEPTION_EXECUTE_HANDLER)
    13.     {
    14.         MaliciousEntry();
    15.     }
    16. }

    17. void Trampoline1()
    18. {
    19.     __try
    20.     {
    21.         __asm int 3;
    22.     }
    23.     __except (EXCEPTION_EXECUTE_HANDLER)
    24.     {
    25.         Trampoline2();
    26.     }
    27. }

    28. int main(void)
    29. {
    30.     __try
    31.     {
    32.         __asm int 3;
    33.     }
    34.     __except (EXCEPTION_EXECUTE_HANDLER) {}
    35.     {
    36.         Trampoline1();
    37.     }

    38.     return 0;
    39. }
    复制代码

    使用矢量异常处理程序:
    C/C++ 代码:
    1. #include <Windows.h>

    2. PVOID g_pLastVeh = nullptr;

    3. void MaliciousEntry()
    4. {
    5.     // ...
    6. }

    7. LONG WINAPI ExeptionHandler2(PEXCEPTION_POINTERS pExceptionInfo)
    8. {
    9.     MaliciousEntry();
    10.     ExitProcess(0);
    11. }

    12. LONG WINAPI ExeptionHandler1(PEXCEPTION_POINTERS pExceptionInfo)
    13. {
    14.     if (g_pLastVeh)
    15.     {
    16.         RemoveVectoredExceptionHandler(g_pLastVeh);
    17.         g_pLastVeh = AddVectoredExceptionHandler(TRUE, ExeptionHandler2);
    18.         if (g_pLastVeh)
    19.             __asm int 3;
    20.     }
    21.     ExitProcess(0);
    22. }


    23. int main(void)
    24. {
    25.     g_pLastVeh = AddVectoredExceptionHandler(TRUE, ExeptionHandler1);
    26.     if (g_pLastVeh)
    27.         __asm int 3;

    28.     return 0;
    29. }
    复制代码


    反制措施
    调试期间:
    • 对于调试器的检测检查。只要在相应的检查中填入NOP即可。
    • 对于控制流隐藏。你必须手动追踪程序直到payload。

    对于反调试绕过工具的开发。这类技术的问题是,不同的调试器会产生不同的异常,并且不把它们返回给调试器。这意味着你必须为特定的调试器实现一个插件,并改变相应的异常后触发的事件处理程序的行为。
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    红盟社区--红客联盟 

    Processed in 0.058895 second(s), 21 queries.

    站点统计| 举报| Archiver| 手机版| 黑屋 |   

    备案号:冀ICP备20006029号-1 Powered by HUC © 2001-2021 Comsenz Inc.

    手机扫我进入移动触屏客户端

    关注我们可获取更多热点资讯

    Honor accompaniments. theme macfee

    快速回复 返回顶部 返回列表