关于IsDebuggerPresent

  关于IsDebuggerPresent()函数的文章已经数不胜数了,随便一搜就能找出一堆来,但是我还是准备写一份放在这里,算是留个备份吧。

  微软给我们提供了一个API函数用来检测当前程序是否正在被调试,这就是可怜的IsDebuggerPresent() ,这个函数的存在似乎只是为了证明在Windows的世界里确实存在一个最杯具的API函数……这个函数的实现很简单,直接windbg查看一下:

0:000> u kernel32!IsDebuggerPresent
kernel32!
IsDebuggerPresent:
7c813133 64a118000000
mov eax,dword ptr fs:[00000018h]
7c813139 8b4030
mov eax,dword ptr [eax+30h]
7c81313c
0fb64002 movzx eax,byte ptr [eax+2]
7c813140 c3
ret

  fs:[0]是本线程TEB的头部,那么fs:[18h]呢?继续让windbg告诉我们:

0:000> dt -b ntdll!_TEB
+0x000 NtTib : _NT_TIB
+0x000 ExceptionList : Ptr32
+0x004 StackBase : Ptr32
+0x008 StackLimit : Ptr32
+0x00c SubSystemTib : Ptr32
+0x010 FiberData : Ptr32
+0x010 Version : Uint4B
+0x014 ArbitraryUserPointer : Ptr32
+0x018 Self : Ptr32
+0x01c EnvironmentPointer : Ptr32
+0x020 ClientId : _CLIENT_ID
+0x000 UniqueProcess : Ptr32
+0x004 UniqueThread : Ptr32
+0x028 ActiveRpcHandle : Ptr32
+0x02c ThreadLocalStoragePointer : Ptr32
+0x030 ProcessEnvironmentBlock : Ptr32
+0x034 LastErrorValue : Uint4B
下面的省略掉了

  很显然,fs:[18h]是一个指向自身的指针,那么[eax+30h]就是获得PEB的地址,再来看PEB的结构:

0:000> dt -b ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 SpareBool : UChar
+0x004 Mutant : Ptr32
+0x008 ImageBaseAddress : Ptr32
+0x00c Ldr : Ptr32
+0x010 ProcessParameters : Ptr32
下面的省略掉了

  那个movzx eax,byte ptr [eax+2]就取出BeingDebugged中的值,然后就直接返回了。

  现在IsDebuggerPresent()就兴高采烈地返回了,我们自然可以事先偷偷地改掉BeingDebugged这个值,让它将杯具进行到底。

  最后贴一个垃圾代码充字数吧,这是一个使用IsDebuggerPresent()检测调试器的例子。

#include <windows.h>
#include
<tchar.h>

int main(int argc,char *argv[])
{
if (IsDebuggerPresent())
{
MessageBox(GetDesktopWindow(),_T(
"发现调试器!!"),_T("IsDebuggerPresent"),MB_OK);
}
else
{
MessageBox(GetDesktopWindow(),_T(
"没有发现调试器。"),_T("IsDebuggerPresent"),MB_OK);
}
return 0;
}
posted @ 2011-05-30 22:53  pianoid  阅读(4413)  评论(0编辑  收藏  举报