Hi. I've implemented various ant-re methods to detect debugger presence. I'm not trying to create unbreakable app, just wanting to see how it all works. So, having those method I can call them at the beginning of program and they will do what they should... but if app is not debugged at that time but instead dbg will be attached later - the whole mechanism is broken.

So here's my question - when and how often should those method be called? Should I have separate thread for this? (somehow it does not sound reliable...)

Indy

November 21st, 2010, 10:25

o The ring of transitions.
- Features implementing functions of converting trap-frame. For example: register using Gs instead of the Ds(debugger its zeroes, ie the trace is not available), context on return from service and current(Ecx & Edx, EFlags etc., morph perfect technique..), the use of zeroing in segments between the ring switching(Iret, Retf. if the selector is zero, then the field of RPL reset the processor), determining whether a swapping(Smsw), etc.
o The use of delays in the trace and using the debug port(SEH, VEH, UEF), measurement of the delay in between the ring transitions(Int 0x2A etc).
o Direct detection of the debug port and its removal(ProcessDebugObjectHandle, NtRemoveProcessDebug etc.)
o Exit from a trace(NtContinue, Int 0x2B - very effective ways to U-mode impossible to cheat ).
o And many, many other ways

kunai

November 21st, 2010, 15:44

Indy, thank you for your answer
I think, however, that you misunderstood my question. The second option is that your answer is too complex for me to understand

I have already implemented some anti-re methods, not so complex as those that you described, although for now I will stick to what I already have.

Let's say I have GUI app. At the beginning of main() I do bunch of anti-re checks. If they completed successfully it means no debugger is attached. Then app starts doing some real code, like secret algorithm. And NOW someone attach debugger which obviously is not detected in this approach.

My ideas are to either put those checks in one of (often triggered) event handlers, or into separate thread. Which one is better?

Indy

November 23rd, 2010, 21:36

kunai
This is a simple and effective methods. Can be divided into several types:
o Detection of trace(TF).
o Detection of breakpoints.
o Detection of debug port.
o Outside of trace.
o Bypass breakpoints.
o Disable debug port or hide the thread of it.

To reset the TF can use the following methods:
o Services NtSetContextThread, NtRaiseException and NtContinue allow you to load in the context of flags without imposing on them a mask for TF. Например:

Code:

Context.TF -> 0
NtContinue(@Context)

o Using the shadow callbacks. There is a stack of shadow callbacks. For each entry stored context and on return from callback loaded into the processor. In the context of TF also copied a previously saved:

This method is not possible to cheat in U-mode. Stack of shadow callbacks in the kernel and is not available to user code, even for reading
http://wasm.ru/forum/viewtopic.php?id=37300

o At the kernel of TF can be reset, loading descriptor in the IDT and calling gateway.

o Removing breakpoints. They can be of several types(hardware Dr*, in memory and on memory). Hardware detected and cleared as well as TF. For memory type PAGE_GUARD duped change attribute memory or load limits of the region in TEB.Tib(StackBase & StackLimit). Then the memory manager will not deploy an exception. Setting breakpoints in memory can be disabled altogether. To this end, the code must be placed in not the file section of the map only for reading. This mechanism can be used for the entire module, remap all its file sections. After such a manipulation of a write in memory will not be possible.

o Disable debug port is a system mechanism. Service NtQueryInformationProcess(ProcessDebugObjectHandle) copies handle port, then port is disconnected(service NtRemoveProcessDebug). It is also a way to detect the port. Thread can be marked for exclude from the Dbg-processing(NtSetInformationThread(ThreadHideFromDebugger)). In the presence of a debug port of the processing speed of exceptions is slow in reduced to ~200%2000 times.

o Using registry Gs. This register is not changed scheduler, and reset when converting trap-frame in the context. The code uses it can not be traced without changing the kernel http://wasm.ru/forum/viewtopic.php?id=38465&p=1

o Detection of TF in the context of the just, for this there are many ways and it makes no sense to describe them.

Iwarez

November 24th, 2010, 16:06

I think it's best to not notify the user instantly. You are better of killing your app a step at a time when you detect a debugger. The checks are often not very time consuming. So throw one check in a timer, another one when a user clicks a button, another when a user selects a menuitem and mess with the results of the program if your check returns positive. If there is no messagebox or program termination it's much harder to detect the antidebugger code.

Indy

November 25th, 2010, 15:04

Iwarez
For example the use of Gs in the trace itself is not possible, and no other checks are not needed. Can proceed as follows. Assemble code into a special format(mutation independed), to create a graph for it, modify it by introducing a set of prefixes Gs and compile the graph. Ie use morphing. This code will normally displayed in the disassembler(debugger), but tracing it is very problematic - for this will need to patch the kernel. For example:

Code:

push ds
pop gs ; KGDT_R3_DATA | RPL_MASK
mov eax,dword ptr gs:[Var]

Maximus

November 26th, 2010, 06:52

indy, may i make you a question? The NtContinue trick is cool, but I am having some problem with the R3 callback.

* we call directly a GDI r0 function that uses R3 callback - ok (by the way, do we need to go manually on it, or we can just use the 'legal' call?)
* Since the GDI needs to support multiple calls to the kernel, as callbacks can call the kernel, a sequence of stack frames are saved, including processor state for each sequence.
* You start with a call to the R0 function then we let allthe code executes normally, then let's say we start tracing the code with a debugger, at some point in the traced code we execute the 'end of callback' code, so our previous register status (with TF=0) gets restored and we are freed of tracing, right?

The GS trick: I am a bit of lost for it - I will try it for sure, but i would like to understand why...
hmm... the base of GS selector is changed like FS for addressing kernel structures, so that while stepping you HAVE kernel kicked in so the base is restored with kernel gs base...
however, if you catch a random interrupt in beneath pop and mov during normal execution??

Indy

November 26th, 2010, 10:32

Maximus

Quote:

The GS trick: I am a bit of lost for it - I will try it for sure, but i would like to understand why...

Kernel manipulates his native state of the task. This is a trap frame. When the conversion to a custom structure describes the context run some amendments. You can follow any responses to see it in the functions KeContextFromKframes() & KeContextToKframes(). The scheduler uses these functions, moreover all the segment registers stored in the trap frame. The scheduler does not cause these functions, moreover all the segment registers stored in the trap frame. This does not affect the planning. The debugger calls these functions to get/change the context. And he can not get/set register Gs, since it is reset by these functions.

Quote:

we call directly a GDI r0 function that uses R3 callback - ok (by the way, do we need to go manually on it, or we can just use the 'legal' call?)

We can use a large number of system services, causing shadow callbacks. When you entry into the kernel trap frame is stored, must be cleared by TF. When you entry into the kernel of callback service is completed and saved the trap frame is loaded into the processor. This mechanism supports is full of recursive calls. See KeUserModeCallback(), KiCallbackReturn(), NtCallbackReturn() etc.

Indy

November 27th, 2010, 08:00

Build a simple sample. Code MessageBox() is transferred to the buffer that is in the map does not file section, available for R/E. In this case, change the memory access is impossible, ie to put breaks in the memory will not work:
http://img827.imageshack.us/img827/2660/hdscr.png

2363
Possible to automatically generate a series of Gs-prefixes. This will make the debugger useless

The same manipulation can be done remap image.

Maximus

December 2nd, 2010, 20:21

Hi Indy - thanks alot.

Unfortunately I'm on an x64 system, and I am scared to even think of using WinDBG for anything different from crash analysis... I'll re-setup a VM and put something like Syser or such on it for examining the calls you suggest.

nice shared library, by the way

Indy

December 19th, 2010, 06:24

Sample displays a message. The code is automatically reconstructed and added to Gs-series. Tracing is not possible.