IsDebuggerPresent学习

今天在Win7下分析Hamachi VPN Client的时候用windbg挂载之,弹出了一个Win32 on5的错误,由于调试方面很生疏,以为是使用了什么反调试的技术。放IDA中查看导入函数,看到了IsDebuggerPresent,以为是这个东西在作怪,最后发现这个错误很愚蠢,刚使用Win7没多久,一直不习惯使用右键里的管理员权限运行,点右键以管理员权限运行windbg之后F6挂上去就可以开始了。下面开始进入主题吧。

 

 ===============================

函数的原型可以从连接http://msdn.microsoft.com/en-us/library/windows/desktop/ms680345(v=vs.85).aspx或者,如下所示:

BOOL WINAPI IsDebuggerPresent( void );


这个函数的用途就是用来检查程序是否在ring 3调试器中运行。关于这个函数google出来一大把的文章,这个函数很被鄙视~~~~


我自己写了一个hello world的小程序来调试调试,程序代码如下:

#include <windows.h>

#include <stdio.h>

#define _WIN32_WINNT 0x0500

int main( void ) 

{

bool isDebugged;

while ( true ) {

isDebugged = IsDebuggerPresent();

             if ( isDebugged ) {

printf( "[-] kao, go away!\n" );

exit( -1 );

}

printf( "[+] Hello World!\n" );

}

return 0;

}

这个程序的目的是在console下输出hello world,如果程序没有在调试器中运行,使用了一个死循环,一直在hello world,

如果检查到程序在调试器中,程序就会退出。

接下来,我们的任务就是娱乐下可怜的hello  world,让它以为没有人在调戏它。

 

=======================================

调试过程:

=========

第一步:先让cmd下让hello world跑起来,可以在控制台下看到它不知疲倦的一直在hello world。

第二步:打开windbg  attach到这个程序

这个时候,程序会被断下来:

ntdll!DbgBreakPoint:

7c92120e cc              int     3

 

现在可以给IsDebuggerPresent函数下断点了;

bp  Kernel32!IsDebuggerPresent

现在可以用bl查看下断点,应该设置好了断点。

输入g,程序会在IsDebuggerPresent的入口处停下来

查看汇编代码:

7c813132 90              nop

kernel32!IsDebuggerPresent:

7c813133 64a118000000    mov     eax,dword ptr fs:[00000018h] fs:003b:00000018=7ffdf000

7c813139 8b4030          mov     eax,dword ptr [eax+30h]

7c81313c 0fb64002        movzx   eax,byte ptr [eax+2]

7c813140 c3              ret

7c813141 90              nop

7c813142 90              nop

红色的代码就是这个函数的实现了。

我们现在可以用p单步步过这几条指令,会到用户空间。

0040102f 7448            je      antidebug!main+0x69 (00401079)

00401031 8bf4            mov     esi,esp

00401033 ff153c514200    call    dword ptr [antidebug!_imp__IsDebuggerPresent (0042513c)]

00401039 3bf4            cmp     esi,esp

现在可以查看下eax的值为1,说明程序是在被调试的。

接下来,我们可以选择修改eax的值,这样这一轮循环,可以正常的输出hello world了,但下一次又需要重复这个过程了。

另一选择就是在内存中抹掉对这个函数的调用,从上面蓝色的指令行可以知道内存0x401033地址处开始的连续6个字节中存储了对这个函数调用的opcode。

我们可以用以下指令修改这6个字节 

ew 0x401033 0xc031 修改内存

ew 0x401035 0xc031

ew 0x401037 0xc031

0xc031 为xor  eax, eax的opcode。

再用reax=0修改eax的值。

bc 0 去掉断点,现在g一下,就可以看到永不知疲倦的hello world了。

这个方法虽然管用,但是很野蛮、暴力,我们还有另一个更好的选择。

现在我们再回来看看IsDebuggerPresent函数的实现。 

7c813133 64a118000000    mov     eax,dword ptr fs:[00000018h] fs:003b:00000018=7ffdf000

7c813139 8b4030          mov     eax,dword ptr [eax+30h]

7c81313c 0fb64002        movzx   eax,byte ptr [eax+2]

7c813140 c3              ret

Windows为每一个运行的进程在用户空间建立了一个进程环境块peb,我们可以用dt _peb来查看下这个数据结构,

每个进程默认有一个主线程,在用户空间为每一个线程建立一个线程环境块teb,同样也可以用dt _teb来查看下下这个数据结构。

其实teb据说以前叫tib,后来改名为teb了,但在数据结构的定义中teb的第一个元素就是tib,tib应该是win98时候的名称,

后来可能扩展了,改名为teb,但teb第一个包含了tib,使得它跟以前的tib兼容。

tib便宜0x18的地方有一个指针 self,这个指针指向了tib的起始地址,其实tib的起始地址就是teb的起始地址,所有从

这个指针我们就可以知道teb的起始地址了,从teb的数据结构中可以知道teb便宜0x30的地方也有一个指针,这个指针说明了

该线程是属于哪一个进程拥有的,指向了peb的起始地址,在从peb的数据结构中可以知道peb便宜0下的地方有一个变量,

:001> dt _peb 7ffd7000

ntdll!_PEB

   +0x000 InheritedAddressSpace : 0 ''

   +0x001 ReadImageFileExecOptions : 0 ''

   +0x002 BeingDebugged    : 0x1 ''

   +0x003 SpareBool        : 0 ''

这个标红的变量指明了进程是否是出于被调试状态。本质上IsDebuggerPresent就是检查了这个变量。
fs总是指向当前运行的线程的teb,现在应该很好理解IsDebuggerPresent的实现了,接下来我们就可以用eb直接修改BeingDebugged变量了。
到次关于IsDebuggerPresent的讨论应该可以暂时告一段落了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值