更新
加一个github地址DBGHider,里面加了inline hook。
背景
许多人喜欢用IDA进行静态分析,用OllyDbg进行动态分析,似乎很少人喜欢使用IDA进行调试。然而我这个菜鸟不会用OD,所以没有体会它的强大之处,我更喜欢用IDA的调试器。
IDA的调试器功能也很强大。
支持x64位程序。
可以充分利用静态分析的结果。
支持多种平台,Windows版本的IDA支持本地Windows调试,同时也支持远程Windows、远程Linux、远程Android、远程Mac调试。
支持多种架构,远程Android调试自然要用到ARM架构,配合QEMU模拟器还可以调试MIPS等架构。
由于IDA 7.x更改的SDK的API,就带来了一个很尴尬的事情,没有使用于IDA 7.x的反反调试插件,所以利用空闲时间写了一个小脚本,实现了对部分反调试方法的绕过。
反调试方法的分类
就我个人的理解,反调试的方法可大致分为以下3类:
PEB->BeingDebugged类,包括调用IsDebuggerPresent()或手动检测BeingDebugged标志。以及由于设置了BeingDebugged标志所引起的连锁反应,包括NtGlobalFlag, Heap Flags等。这种反调试方法可以通过在程序运行前清除标记位来绕过反调试。
函数调用类,包括调用CheckRemoteDebuggerPresent(),NtQueryInformationProcess()函数等。这类方法无法通过清楚标志位来绕过,但可以通过Hook相应函数来绕过。
触发异常类,包括int 3, icebp等,原理是通过触发异常,然后检测是否收到异常来确定是否正在被调试。这类方法可以直接修改调试器的配置,使调试器把相应的异常传递给被调试的程序
DBG_Hooks
在IDAPython中,可以通过idaapi.DBG_Hooks类挂钩调试器的行为,进行一些操作。利用DBG_Hooks可以挂钩程序的开始,退出,加载dll,卸载dll等操作。具体挂钩点可以参考下面的Python脚本,这个脚本取自https://github.com/idapython/src。
#---------------------------------------------------------------------
# Debug notification hook test
#
# This script start the executable and steps through the first five
# instructions. Each instruction is disassembled after execution.
#
# Original Author: Gergely Erdelyi
#
# Maintained By: IDAPython Team
#
#---------------------------------------------------------------------
from idaapi import *
class MyDbgHook(DBG_Hooks):
""" Own debug hook class that implementd the callback functions """
def dbg_process_start(self, pid, tid, ea, name, base, size):
print("Process started, pid=%d tid=%d name=%s" % (pid, tid, name))
def dbg_process_exit(self, pid, tid, ea, code):
print("Process exited pid=%d tid=%d ea=0x%x code=%d" % (pid, tid, ea, code))
def dbg_library_unload(self, pid, tid, ea, info):
print("Library unloaded: pid=%d tid=%d ea=0x%x info=%s" % (pid, tid, ea, info))
return 0
def dbg_process_attach(self, pid, tid, ea, name, base, size):
print("Process attach pid=%d tid=%d ea=0x%x name=%s base=%x size=%x" % (pid, tid, ea, name, base, size))
def dbg_process_detach(self, pid, tid, ea):
print("Process detached, pid=%d tid=%d ea=0x%x" % (pid, tid, ea))
return 0
def dbg_library_load(self, pid, tid, ea, name, base, size):
print "Library loaded: pid=%d tid=%d name=%s base=%x"