先导入原版OD。看函数列表,里面只有ExitProcess。显然有函数被隐藏。
OD调试器比较特殊,即便函数列表里没有
GetProcAddress
也可下段,我们bp GetProcAddress。仅仅只有这个函数是例外。
多数程序都有反调试,或许是退出,或许是蓝屏,或者格式化磁盘。一般的思路是,在退出函数下断,反汇编窗口跟随它的返回地址,在程序领空找关键跳。但是这里我们不能只满足于绕过退出,我们要知道程序究竟执行了哪些步骤,做到了然于胸。
我们看看它都执行了啥函数了。
先在
GetProcAddress
下断,看获取了哪些函数。
Createtoolhelp32snapshot进程快照,bp eax,给这个函数设一个断点,它执行完会返回一个句柄,里面是快照的内容。快照的句柄是0x38,在H窗口看得到
下一个openprocess,bp eax 再注释
下一个Process32First:bp 注释
同理,Terminateprocess
同理,LstrcmpA
虽然说我们的确是在这些函数下断了,但是不能在程序领空看到这些断点,只能在系统领空看到,这是一个遗憾。但是我不建议使用bpx在程序领空下断,那样不利于分析重复调用的API。
接着是FindwindowA,执行到返回,bp eax 注释。这个函数很关键。
接着,Process32next。
获取完毕后,先执行Createtoolhelp32snapshot,它会返回快照句柄。
然后传入该句柄执行Process32First,这个函数是取出进程快照里的第一个进程的详细信息存在结构体里。
然后是Process32next,作用同
Process32First ,只是一个一个提取剩下的进程快照里的内容,不是一下子全提取出来。
结合OD分析这个函数。在堆栈窗口看出,第一参数是存储句柄数值的,比如0x38的,就是之前那个快照的句柄了,而第二参数是pProcessentry,我们没有用到它。当然必须得先执行到返回才能获取到内容哦。Ctrl+f9,堆栈窗口第一行是返回地址,第二行是38是句柄,第三行是获取内容所在的地址了,这个参数是指向一个
叫PROCESSENTRY32
结构体,里面存储进程的各种数据。在数据窗口跟随这个地址,就能看到里面的信息,比如进程名,父进程名等。
想知道哪里存储了什么,可以看看
PROCESSENTRY32结构体是如何定义的
typedef struct tagPROCESSENTRY32
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
TCHAR szExeFile[MAX_PATH];
} PROCESSENTRY32, *PPROCESSENTRY32;
具体的含义如下图所示。
这个CM后来执行了比较进程名,即提取了szExeFile里的内容,并用一个规定好的进程名和这结构体里的进程名比较。
接着执行FindWindowA,发现堆栈窗口class里的值是OllyDbg,Title里的值是NULL。对了,这个函数并没有依赖上一个函数,而是单独起作用的,就是检查当前所有打开的窗口的类名或者标题名有没有符合设置的。所以他不依赖之前获取的信息。这两个参数输入任一个,二选一就能执行个函数。这里只设置class=ollydbg,title则为null,说明只要类名是ollydbg,它就可以获得这个程序的句柄,执行完成后把句柄返回给EAX。否则f返回0。规定类名是ollydbg。执行完后Eax=009e029e就是OD的句柄。这个函数就是本讲的核心,它既可以检测类名,也可以检测标题名。
如何使用插件来插件绕过检测呢,我们可以用HiddenDebugger.dll,当然不止有这一个插件。在OD主界面点击插件-
HiddenDebugger -Option来到设置里面,把FindWindow、EnumWindow勾选,点击保存,并且重启OD。它的作用是,让标题名为空。
而本例中检测还类名,想修改OD的类名,就要借助一个补丁,repair。打开repair,勾选ollydbg勾选上start tool after patching和 rename tool,点fix it ,选择OD的源程序,就把类名改为Rrr20了,进程名也成Rrr20。
最后安利一个小程序,算是一个彩蛋把~
WinDowse
可以查看任一程序的所有信息。安装打开以后,把鼠标放到OD的标题那,所有的信息都显示出来了。介绍这个软件是为了验证我们的判断。