My notes about anti-debugging
-----------------------------

all these routines are in secserv.dll

debug_check_isdebuggerp : 10010B20 :

The IsDebuggerPresent function determines whether the calling process is running under the context of a debugger.
note : it actually returns true only if the process has been created with the DEBUG_PROCESS flag.

inefficient under Softice

 debug_check_file_sice 100106E0 : patch for Meltice

100102D0 : debug_check_file_ntice same as above

debug_check_ntqueryprocess 1000FEA0

10010184 6A 00                             push    0               ; OUT PULONG ReturnLength OPTIONAL
10010186 6A 04                             push    4               ; IN ULONG ProcessInformationLength
10010188 8D 95 60 FF FF FF                 lea     edx, [ebp+var_A0]
1001018E 52                                push    edx             ; OUT PVOID ProcessInformation
1001018F 6A 07                             push    7               ; IN PROCESSINFOCLASS ProcessInformationClass (ProcessDebugPort)
10010191 FF 15 80 80 03 10                 call    ds:GetCurrentProcess
10010197 50                                push    eax             ; IN HANDLE ProcessHandle
10010198 FF 95 4C FF FF FF                 call    [ebp+var_B4]    ; NtQueryInformationProcess
1001019E 89 85 48 FF FF FF                 mov     [ebp+var_B8], eax ; NtQueryInformationProcess(
1001019E                                                           ;      IN HANDLE ProcessHandle,
1001019E                                                           ;      IN PROCESSINFOCLASS ProcessInformationClass,
1001019E                                                           ;      OUT PVOID ProcessInformation,
1001019E                                                           ;      IN ULONG ProcessInformationLength,
1001019E                                                           ;      OUT PULONG ReturnLength OPTIONAL
1001019E                                                           ;      );
1001019E                                                           ;
100101A4 EB 04                             jmp     short loc_100101AA


NtQueryInformationProcess fills in a DWORD with the port number of the debugger for the process being queried. The ProcessInformationLength parameter to NtQueryInformationProcess should be set to sizeof(DWORD). The debug port is a value that's useless to ring 3 code. However, you can infer that a nonzero debug port means that the process is being run under the control of a ring 3 debugger such as the Visual C++ IDE or Turbo Debugger.

(thanks Mark)

1000FBC0 : code of IsDebuggerPresent reproduced in case of the hacker (in that case me :-) patched the kernel

mov eax, dword ptr fs:[00000018]
mov eax, dword ptr [eax+30]
movzx eax, byte ptr [eax+02]
ret

does not work for ntice

1000F970 : debug_check_fs1820

reads [fs:[18]+20]... can not tell what it is exactly, but it does not work. :-)

Inefficient for Softice

1000F290 : BCHK check (not executed under NT)

patch against BCHK if ever you encounter it, either with ElicZ macro (PBCHK) or in editing your driver.

1000ee80 : this function will check all kernel32.dll exports , each first byte is compared to 0xcc (breakpoint)

 - you need to disable all your breakpoints on kernel32.dll
 - Softice puts a breakpoint on UnhandledExceptionFilter which is a kernel32.dll export, ElicZ's macro PUHF will solve that.

1000EA70 : secdrv.sys interface

dr7 check, secserv.dll will issue a call to secdrv.sys so that it checks the content of the dr7 register (I also noticed some dr1 checking).

The only way to overcome this is to patch secdrv.sys to remove that check, secdrv.sys being a KMD it runs in ring-0,
this also implies that there are no fancy things such as decryption in the driver (one would have to be crazy to do that in
ring-0).

to be sure replace

mov eax, dr1 (0F 21 C8) with xor eax, eax nop (33 c0 90)

mov eax, dr7 (0F 21 F8) with mov eax, 400 (B8 00 04 00 00)

the exact code is :

00012356 0F 21 F8                          mov     eax, dr7
00012359 89 45 FC                          mov     [ebp+dr7_content], eax
0001235C
0001235C                   loc_1235C:                              ; CODE XREF: dr_check+A6j
0001235C EB 04                             jmp     short loc_12362


mov eax, 400 being larger than mov eax, dr7, you'll have to fix up things a little, fortunately obfuscation gives you
all the room you need.

but here is a better place (safer place)

0001239D 8B 45 FC                          mov     eax, [ebp+dr7_content]
000123A0 25 00 05 00 00                    and     eax, 500h
000123A5 89 45 FC                          mov     [ebp+dr7_content], eax
000123A8 EB 04                             jmp     short loc_123AE

replace and eax, 500h with mov eax, 400, that's the same length !


25 00 05 00 00 -> b8 00 04 00 00

so the patch for secdrv.sys is

s/250005
p/b800040000

I have not yet determined how the program interfaces with secdrv.sys, it uses DeviceIoControl, but I cannot interface
with secdrv with my own routines, my input buffer must be wrongly initialized.

(note : there is more anti-debug than dr7 check within secdrv.sys)


there is an int 1 check 1000E5F0 calls 1000E810 :

1000E815 68 F0 81 03 10                    push    offset stru_100381F0
1000E81A 68 D8 D1 02 10                    push    offset __except_handler3
1000E81F 64 A1 00 00 00 00                 mov     eax, large fs:0
1000E825 50                                push    eax
1000E826 64 89 25 00 00 00+                mov     large fs:0, esp

...

1000E869 CD 01                             int     1               ; - internal hardware - SINGLE-STEP
1000E869                                                           ; generated at end of each machine instruction if TF bit in FLAGS is set

use ElicZ macro UINT0 1, and you're fine

1000E270 : int 68h check (not working under NT)

debug_check_zwquerysysinfo : 1000DE20 (NT only) -> OK under NTice

1000db60 : another secdrv.sys interface

same problem as above.
The only big change being that 0x3d is given as a paramater instead of 0x3c.

call 1 :

1000EBA8 52                                push    edx ; that's the "unknown pointer"
1000EBA9 6A 00                             push    0
1000EBAB 6A 00                             push    0
1000EBAD 6A 3C                             push    3Ch
1000EBAF E8 2C FE FF FF                    call    debug_check_secdrv_stuff ; this functions does everything
1000EBB4 83 C4 14                          add     esp, 14h

call 2 :

1000DD38 52                                push    edx ; that's the "unknown pointer"
1000DD39 6A 00                             push    0
1000DD3B 6A 00                             push    0
1000DD3D 6A 3D                             push    3Dh
1000DD3F E8 9C 0C 00 00                    call    debug_check_secdrv_stuff
1000DD44 83 C4 14                          add     esp, 14h

cross reference also gave me those parameters : 0x3f, 0x40, 0x41, 0x42 (where is 0x3e ? :-)

I really need to make my program work, I am sure we would get nice information from that.

Other problem is patching secdrv.sys, if you patch the KDM, you need to reboot for the changes to take effect,
so patch from softice using drivers to list the drivers, etc.

when you patch the secdrv.sys do not forget to update the checksum.






