如何防范动态调试(Anti-Debug)(SoftICE篇)
Windows NT/2000/XP系统:
1.判断NTICE服务是否运行
在Windows NT/2000/XP系统中,SoftICE是一个内核设备驱动类型的服务,服务名为NTICE,因此可通过判断NTICE服务是否运行来检测SoftICE.
BOOL SoftICEIsLoad()
{
SERVICE_STATUS ssStatus;
// 打开服务控制管理器
SH_HANDLE shServiceManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
if(NULL == shServiceManager)
return FALSE;
// 打开NTICE服务
SC_HANDLE shMyService = OpenService(shServiceManager, "NTICE", SERVICE_ALL_ACCESS);
if(QueryServiceStatus(shMyService, &ssStatus)) == 0)
{
CloseServiceHandle(shMyService);
return FALSE;
}
// NTICE服务正在运行
if(SERVICE_RUNNING == ssStatus.dwCurrentState)
{
CloseServiceHandle(shMyService);
return TRUE;
}
return FALSE;
}
2.利用 UnhandledExceptionFilter 检测
如果SoftICE加载,SoftICE会在kernel32.dll的UnhandledExceptionFilter函数第一字节外设一个INT 3指令,即用"CC"代替原机器码"55".因此就可根据这个"CC"机器码,判断SoftICE是否加载.
BOOL SoftICEIsLoad()
{
FARPROC Uadder;
BYTE Mark = 0;
(FARPROC&)Uaddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "UnhandledExceptionFilter");
Mark = *((BYTE)Uaddr);
// 取UnhandledExceptionFilter函数的第一字节
if(0xCC == Mark) // 如是则SoftICE已加载
return TRUE;
return FALSE;
}
3.检测断点
由于SoftICE有针对API设置断点的强大功能,它工作时是在函数前插入INT 3指令(机器码CC),因此检测函数首地址机器码是否为CC就可以判断是否被SofeICE设置断点跟踪.
#include <windows.h>
BOOL IsBPX(void* address);
int WINAPI WinMain(HINSTANCE hInstanec, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
void* addr;
addr=MessageBox;
if(IsBPX(addr))
{
MessageBox(NULL,"don't debug me.","help!",MB_HELP);
}else{
MessageBox(NULL,"no one.","go go go!",MB_OK);
}
return 0;
}
BOOL IsBPX(void* address)
{
_asm
{
MOV ESI , address // 被监视函数的地址
MOV AL , [ESI] // 取该函数的机器码
CMP AL , 0xCC // 检测机器码是否为0xCC
JE SoftICELoad // 如果是则函数被跟踪
}
return FALSE;
SoftICELoad:
return TRUE;
}
Windows 9x系统:
1.检测INT 1和INT 3服务的差
在Windows 9x系统中,SoftICE驻留后修改INT 1和INT 3中断的入口,指向它自己的处理程序,其中INT 1和INT 3服务的差总是为1EH利用这点就可检测SoftICE.
这种方法要结合SEH来实现,否则在Windows 2000/XP系统中会产生断点异常.
BOOL SoftICEIsLoad()
{
char pIDT[6]={0};// IDT保存在这
try
{
_asm
{
sidt fword ptr pIDT // 取IDT内容
mov eax,dword ptr[pIDT+2] // 获取IDT表的基地址
add eax,8
mov ebx,[eax] // 取INT 1的低位偏移
add eax,16
mov eax,[eax] // 取INT 3的低位偏移
and eax,0ffffh
and ebx,0ffffh
sub eax,ebx // 计算低位偏移这差
cmp eax,0xle 如果SoftICE驻留内存,则差为0xle
jz SoftICELoad
}
}
catch(...)
{
return FALSE
}
return FALSE;
SoftICELoad:
return TRUE;
}
2.检测SoftICE VxD ID
BOOL SoftICEIsLoad()
{
_asm
{
xor di,di
mov es,di
mov ax, 1684h
mov bx, 0202h ; VxD ID of winice
int 2Fh
mov ax, es ; ES:DI -> VxD API entry point
add ax, di
test ax,ax
jnz SoftICELoad
}
return FALSE;
SoftICELoad:
return TRUE:
}