[ Team LiB ] |
12.15 Detecting SoftICE12.15.1 ProblemSoftICE is a ring0 debugger that cannot be detected using standard debugger detection techniques. 12.15.2 SolutionNumega's SoftICE debugger is a kernel-mode debugger intended for debugging device drivers and Windows itself. It is favored by software protection crackers because of its power. Four well-known methods for detecting the presence of SoftICE exist, which are detailed in Section 12.15.3. 12.15.3 DiscussionThe "Meltice" technique is one of the oldest methods for detecting SoftICE. It attempts to open virtual devices created by SoftICE; if any of these devices exist, the debugger is present. #include <windows.h> BOOL spc_softice_meltice(void) { HANDLE hFile; hFile = CreateFile(TEXT("\\.\\SICE"), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); if (hFile = = INVALID_HANDLE_VALUE) hFile = CreateFile(TEXT("\\.\\NTICE"), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); if (hFile = = INVALID_HANDLE_VALUE) hFile = CreateFile(TEXT("\\.\\SIWDEBUG"), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); if (hFile = = INVALID_HANDLE_VALUE) hFile = CreateFile(TEXT("\\.\\SIWVID"), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); if (hFile = = INVALID_HANDLE_VALUE) return FALSE; CloseHandle(hFile); return TRUE; } SoftICE provides an interface via the debug breakpoint (int3) instruction that allows a process to communicate with the debugger. By loading a magic value ("BCHK") into the ebp register and executing an int3, the Boundschecker (originally the Numega Boundschecker utility) interface can be accessed. The function to be called is loaded into the eax register; function 4 will set the al register to 0 if SoftICE is present. #include <windows.h> _ _declspec(naked) BOOL spc_softice_boundschecker(void) { _ _asm { push ebp mov ebp, 0x4243484B ; "BCHK" mov eax, 4 ; function 4: boundschecker interface int 3 test al, al ; test for zero jnz debugger_not_present mov eax, 1 ; set the return value to 1 pop ebp ret debugger_not_present: xor eax, eax ; set the return value to 0 pop ebp ret } } The int3 interface can also be used to issue commands to SoftICE by setting the esi and edi registers to magic values, then invoking function 0x911: #include <windows.h> char *sice_cmd = "hboot"; BOOL spc_softice_command(char *cmd) { _ _asm { push esi mov esi, 0x4647 ; "FG" push edi mov edi, 0x4A4D ; "JM" push edx mov edx, [cmd] ; command (string) to execute mov ax, 0x0911 ; function 911: execute SOFTICE command int 3 pop edx pop edi pop esi } } Finally, the presence of SoftICE can be detected by invoking function 0x43 of interrupt 0x68: #include <windows.h> _ _declspec(naked) BOOL spc_softice_ispresent(void) { _ _asm { mov ah, 0x43 int 0x68 cmp ax, 0xF386 jnz debugger_not_present mov eax, 1 ret debugger_not_present: xor eax, eax ret } } SoftICE detection and counterdetection is a continuously evolving field. Different versions of SoftICE have different memory footprints and runtime behavior that can be used to detect them; however, because most software protection crackers have modified their versions of SoftICE to foil known detection methods, it is advisable not to rely entirely on SoftICE detections for protection. 12.15.4 See Also
|
[ Team LiB ] |