Limee AKA Lamer
August 29th, 2004, 11:35
this Program can test the present of OD
Please get rid of the plugin of isdebuggerPresent
Please get rid of the plugin of isdebuggerPresent
View Full Version : Ring3 debugger detection stuph (was Please test a program)
[Originally Posted by hobgoblin]I don't get it. When I run this program in Olly, I get the message "Debugger NOT present". (This happens when I have the Hide debugger plugin activated, and it happens when I run Olly without). What's the purpose with this? |
MOV EAX,DWORD PTR FS:[18] ;TEB self pointer
MOV EAX,DWORD PTR DS:[EAX+30] ;PEB pointer
MOVZX EAX,BYTE PTR DS:[EAX+2] ;IsDebuggerPresent Flag
MOV EAX,DWORD PTR FS:[18]
mov AntiDebug1,eax
....;lot of code
mov eax,AntiDebug1
MOV EAX,DWORD PTR DS:[EAX+30]
mov AntiDebug2,eax
...;lot of code
mov eax,AntiDebug2
MOVZX EAX,BYTE PTR DS:[EAX+2]
mov AntiDebug3,eax
;if eax==1 then a Debugger is here
;just test it far away with some complicated way
// Override QueryInformationProcess to return a zero value, so the program
// does not detect our debugger process.
NtQueryInformationAddress = LookupAPIAddress("NtQueryInformationProcess","ntdll.dll";
PlaceBreakPoint(hProcess,NtQueryInformationAddress,QueryInformationHandler);
......
BOOL QueryInformationHandler(HANDLE hProcess, HANDLE hThread)
{
CONTEXT TempContext;
ZeroMemory(&TempContext,sizeof(TempContext));
TempContext.ContextFlags = CONTEXT_CONTROL;
GetThreadContext(hThread,&TempContext);
DWORD ProcessInfoArg = 0;
// get the return address
ReadProcessMemory(hProcess,(LPVOID)TempContext.Esp,&NtQueryInformationReturn,4,NULL);
ReadProcessMemory(hProcess,(LPVOID)((DWORD)TempContext.Esp +8),&ProcessInfoArg,4,NULL);
if (ProcessInfoArg == 0x07)
{
//ShowString("Called ProcessDebugPort";
PlaceBreakPoint(hProcess,NtQueryInformationReturn,QueryInformationReturnHandler);
return TRUE;
} else
return FALSE;
}
......
BOOL QueryInformationReturnHandler(HANDLE hProcess, HANDLE hThread)
{
CONTEXT TempContext;
ZeroMemory(&TempContext,sizeof(TempContext));
TempContext.ContextFlags = CONTEXT_CONTROL;
GetThreadContext(hThread,&TempContext);
// have to edit the value at [esp+8] to zero
DWORD EspValue =0;
//ReadProcessMemory(hProcess,(LPVOID)((DWORD)TempContext.Esp+8),&EspValue,4,NULL);
WriteProcessMemory(hProcess,(LPVOID)((DWORD)TempContext.Esp+8),&EspValue,4,NULL);
return TRUE;
}
[Originally Posted by hobgoblin]I don't get it. When I run this program in Olly, I get the message "Debugger NOT present". (This happens when I have the Hide debugger plugin activated, and it happens when I run Olly without). What's the purpose with this? |
:0044F691 xor esi, esi
...
:0044F8BB mov eax, large fs:124h ; KTHREAD
:0044F8C1 mov [ebp+var_88], eax
:0044F8C7 mov eax, [eax+44h] ; [KTHREAD+44h]
:0044F8CA cmp [eax+120h], esi ; DebugPort
:0044F8D0 jz short loc_44F924
:0044F8D2 loc_44F8D2: ; CODE XREF: NtClose+25Dj
:0044F8D2 push 0C0000008h ; Invalid Handle error
:0044F8D7 call KeRaiseUserException
0: kd> !kthread
struct _KTHREAD (sizeof=432)
+000 struct _DISPATCHER_HEADER Header
...
+034 struct _KAPC_STATE ApcState
+034 struct _LIST_ENTRY ApcListHead[2]
struct _LIST_ENTRY *Flink
struct _LIST_ENTRY *Blink
+044 struct _KPROCESS *Process
...
mov eax, large fs:124h ; KTHREAD
mov eax, [eax+44h] ; KTHREAD.KAPC_STATE.Process -> PTR EPROCESS
cmp [eax+120h], 0 ; EPROCESS.DebugPort (LPC_PORT_OBJECT)
jnz debugger attached
[Originally Posted by Kayaker] >dangerous to encrypt ring 0 code.. I think I remember someone mentioning that before, why would that be the case? As long as you know you're not paged out... code is code is code n'est pas? |
struct _EPROCESS (sizeof=648)
+000 struct _KPROCESS Pcb
+000 struct _DISPATCHER_HEADER Header
+000 byte Type
...
+06a byte Spare[2]
--------------------------------> KPROCESS ends
+06c int32 ExitStatus
+070 struct _KEVENT LockEvent
+070 struct _DISPATCHER_HEADER Header
...
+120 void *DebugPort
+124 void *ExceptionPort
...
[Originally Posted by Kayaker] Code:
|
ntdll!_ETHREAD
struct _ETHREAD, 54 elements, 0x258 bytes
+0x000 Tcb : struct _KTHREAD, 73 elements, 0x1c0 bytes
+0x000 Header : struct _DISPATCHER_HEADER, 6 elements, 0x10 bytes
.....
+0x033 Priority : 127 ''
+0x034 ApcState : struct _KAPC_STATE, 5 elements, 0x18 bytes
+0x000 ApcListHead : (2 elements)
[00] struct _LIST_ENTRY, 2 elements, 0x8 bytes
[ 0x0 - 0x0 ]
+0x000 Flink : (null)
+0x004 Blink : (null)
[01] struct _LIST_ENTRY, 2 elements, 0x8 bytes
[ 0x0 - 0x0 ]
+0x000 Flink : (null)
+0x004 Blink : (null)
+0x010 Process : (null)
+0x014 KernelApcInProgress : 0 ''
....
[Originally Posted by 0rp] where did you found this code? |
0044F685 mov eax, large fs:124h ; KTHREAD
0044F68B dec dword ptr [eax+0D0h] ; KernelApcDisable
; [KTHREAD+D0h] uint32 KernelApcDisable
:0044F691 xor esi, esi
...
:0044F8BB mov eax, large fs:124h ; KTHREAD
:0044F8C1 mov [ebp+var_88], eax
:0044F8C7 mov eax, [eax+44h] ; [KTHREAD+44h] *Process
:0044F8CA cmp [eax+120h], esi ; [EPROCESS+120] *DebugPort
:0044F8D0 jz short loc_44F924
:0044F8D2 loc_44F8D2: ; CODE XREF: NtClose+25Dj
:0044F8D2 push 0C0000008h ; STATUS_INVALID_HANDLE
:0044F8D7 call KeRaiseUserException
; [KTHREAD+44h] is a pointer to the EPROCESS/KPROCESS block for the running application
; +044 struct _KPROCESS *Process
; [EPROCESS+120] is a pointer to EPROCESS.DebugPort (LPC_PORT_OBJECT)
; +120 void *DebugPort
.586
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
include \masm32\include\masm32.inc ; for FPU routine
includelib \masm32\lib\masm32.lib
CTEXT MACRO text:VARARG
LOCAL TxtName
.data
TxtName BYTE text, 0
.code
EXITM <ADDR TxtName>
ENDM
;======
.DATA?
;======
;---------------------
hInstance HINSTANCE ?
hFile HANDLE ?
StringBuff db 64 dup(?)
FloatBuff db 32 dup(?)
lpPerformanceFrequency LARGE_INTEGER <>
CountsPerSec QWORD ?
lpPerformanceCount LARGE_INTEGER <>
StartCount QWORD ?
EndCount QWORD ?
ExecutionTime QWORD ?
msec DWORD ?
;##################################################
;======
.CODE
;======
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
; ==================================================
; Create a dummy file in the current directory
; ==================================================
invoke CreateFile, CTEXT("dummy.txt", GENERIC_READ, FILE_SHARE_READ, NULL,\
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
.if (!eax)
invoke MessageBox, NULL, CTEXT("Error", CTEXT("Can't create the file"
,\
MB_OK+MB_ICONERROR+MB_TASKMODAL+MB_TOPMOST
invoke ExitProcess, 0
.endif
mov hFile, eax
invoke CloseHandle, hFile ; the valid CloseHandle call
; ==================================================
; Initialize our timing check
; ==================================================
finit ; initialize FPU
; -------------------------------------------------------------
; Get the frequency of the high-resolution performance counter
; -------------------------------------------------------------
invoke QueryPerformanceFrequency, ADDR lpPerformanceFrequency
fld qword ptr [lpPerformanceFrequency] ; push result onto top of FPU stack st(0)
fstp qword ptr [CountsPerSec] ; store value in st(0) into variable
; -------------------------------------------------------------
; Get the starting tick value
; -------------------------------------------------------------
invoke QueryPerformanceCounter, ADDR lpPerformanceCount
fld qword ptr [lpPerformanceCount]
fstp qword ptr [StartCount]
; ==================================================
; Call CloseHandle a second time using the same file handle
; Will generate STATUS_INVALID_HANDLE and force
; KeRaiseUserException if debugger attached
; ==================================================
invoke CloseHandle, hFile
; -------------------------------------------------------------
; Get the ending tick value
; -------------------------------------------------------------
invoke QueryPerformanceCounter, ADDR lpPerformanceCount
fld qword ptr [lpPerformanceCount]
fstp qword ptr [EndCount]
; -------------------------------------------------------------
; The time in seconds between the two QueryPerformanceCounter calls is
; (EndCount - StartCount) / CountsPerSec
; -------------------------------------------------------------
fld qword ptr [EndCount] ; load EndCount to st(0)
fsub qword ptr [StartCount] ; sub StartCount from st(0)
fdiv qword ptr [CountsPerSec] ; divide result by CountsPerSec
mov msec, 1000 ; shift decimal place to milliseconds
fimul msec ; multiply result in st(0) by 1000
fstp qword ptr [ExecutionTime] ; store result in st(0) to variable
; -------------------------------------------------------------
; Convert floating point result to a string using the
; masm32lib function FloatToStr
; -------------------------------------------------------------
invoke FloatToStr, qword ptr [ExecutionTime], ADDR FloatBuff
;===============================================
invoke wsprintf, offset StringBuff,\
CTEXT("%s is the elapsed time for CloseHandle",\
offset FloatBuff
; A direct check of the elapsed time is probably better here, say
; ExecutionTime > 10 milliseconds might be considered a
; positive test for a debugger
;
; Instead, this is a lame check of where the decimal point is in the string
; Since we are forcing FloatToStr to convert milliseconds, anything less
; than 1 ms will be expressed as i.e. "1.0 x 10-3"
; and the decimal point will be the second character
lea eax, offset StringBuff
.if byte ptr [eax+1] != '.'
invoke MessageBox, NULL, offset StringBuff,\
CTEXT("Wise choice, you're using a debugger...",\
MB_OK+MB_ICONWARNING+MB_TASKMODAL+MB_TOPMOST
.else
invoke MessageBox, NULL, offset StringBuff,\
CTEXT("No debugger detected. Have you tried Olly?",\
MB_OK+MB_ICONINFORMATION+MB_TASKMODAL+MB_TOPMOST
.endif
invoke ExitProcess, 0
end start
//PEB offset
+010 struct _RTL_USER_PROCESS_PARAMETERS *ProcessParameters
typedef struct _RTL_USER_PROCESS_PARAMETERS {
// (sizeof=656)
+000 uint32 MaximumLength
+004 uint32 Length
+008 uint32 Flags
+00c uint32 DebugFlags <= here !
+010 void *ConsoleHandle
//...[cut]