10

I'm debugging this process which has a lot of anti debugging techniques in it, and I faced something new which I don't know how to bypass yet.

Changing the code dynamically causes exceptions to occur and the process to crash. So setting INT 3 breakpoints is not an option. The way I'm debugging the process is only with Hardware Breakpoints.

Now I have found the function (at least one of them…) which reads portions of the memory and using some CheckSum function over that memory, and then it checks if the memory CheckSum is as it expected. If I changed one byte in the memory, the CheckSum would not be as expected, thus the process would crash. This is actually very simple and done like this in the code:

CMP EAX,EDX                  ; Compare CheckSum
JE __GoodCode                  ; jmp must be taken
CALL <CrashProgram>
__GoodCode: 
XOR EAX,EAX
...

The hex value of JE short is 0x74 0x0B and I want to change it to JMP short which is 0xEB 0x0B. When I do that, the program would crash. I found out where the program is crashing using Memory breakpoints at different places of the code and then I found the function doing the CheckSum (it reads all the memory). But now I figured out there is another existing function which probably does something similar! causing the program to crash.

But this time when I put a Memory breakpoint on my 'changed' JE to JMP it never stops on the breakpoint.

So this is my first problem, another problem I had is that I had a function I suspected had something to do with the crashing when changing the code, but when I set a Hardware breakpoint on it, it didn't break. I know for sure that this function is being called and the code definitely runs. So I thought to myself there is probably something making sure my Memory & Hardware breakpoints won't work, some sort of anti-debugging mechanism.

I read a little bit about it and found out about GetThreadContext, in my case it calls Wow64GetThreadContext. It receives a Context structure which holds most registers. Here is how the Context structure looks like:

CONTEXT _X86_

typedef struct _CONTEXT {
DWORD ContextFlags;
/* ContextFlags contians CONTEXT_DEBUG_REGISTERS. */
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
/* ContextFlags contians CONTEXT_FLOATING_POINT. */
FLOATING_SAVE_AREA FloatSave;
/* ContextFlags contians CONTEXT_SEGMENTS. */
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
/* ContextFlags contians CONTEXT_INTEGER.*/
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
/* ContextFlags contians CONTEXT_CONTROL */
DWORD Ebp;
DWORD Eip;
DWORD SegCs; // MUST BE SANITIZED
DWORD EFlags; // MUST BE SANITIZED
DWORD Esp;
DWORD SegSs;
/* ContextFlags word contains CONTEXT_EXTENDED_REGISTERS */
BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
} CONTEXT;

The first parameters are my Hardware breakpoints and I can see them clearly, but it doesn't seem like it does something with their values. So I don't think it's this function which is causing the crash. Whenever it is called, it seems more like a debug code. Also, this function is never called regularly - only after the program is crashing.

Now there is also ReadProcessMemory which I read it might bypass my Memory breakpoints for some reason. I set logging breakpoints on that function and it never seemed like it reads a Page(size 0x1000) close to the function I changed, and yes I checked the size it was reading as well. Although this function is called regularly it still doesn't seem like this is it.

I have also heard about ZwProtectVirtualMemory functions to change the attributes of memory regions so that the Memory breakpoint 'exceptions' won't occur, and the debugger won't receive them. This function is being called out, but I'm not sure what is the usage, or what parameters are relevant to me in the memory.

Is there anything else I might be missing?

The article I was reading which was helping me quite a lot, but did not help me find out what was causing the crash: http://waleedassar.blogspot.in/2012/11/defeating-memory-breakpoints.html


I have changed my wording of this question. I hope it's clearer now.

7
  • Did you change the bytes on disk, or in memory only? The program might be reading its executable file. Also, some programs try to detect if they're running in a debugger. Did you install a Stealth plugin? Will the program work from Ollydbg if you don't patch anything? Or maybe the program detects memory breakpoints. Will the program work if you don't patch anything, but set a memory breakpoint anyway? Commented Mar 11, 2015 at 13:31
  • 1
    And you might be interested in this which links to this. Commented Mar 11, 2015 at 13:39
  • @GuntramBlohm I changed the byte dynamically only in the memory. not on the disk. I am using a Stealth plugin, the program does check if its being debugged or not. The program works good with a Stealth plugin in Olly and i can debug the program using Hardware Breakpoints (Normal breakpoints add Int 3)
    – 0xAK
    Commented Mar 11, 2015 at 14:16
  • 2
    At the end of the 2nd link, they say "N.B. ReadProcessMemory has also been used as a stealthy way to read memory without triggering Hardware Breakpoints." I'd assume that ReadProcessMemory copies the memory using kernel ring 0 mode, so it avoids the page restrictions that apply to user mode. Can't hurt to check if ReadProcessMemory gets called somewhere. Commented Mar 11, 2015 at 22:18
  • 1
    @GuntramBlohm, Wow yeah, ReadProcessMemory does happen! i would have never guessed that this API bypasses olly's memory breakpoints.. Always good to learn new things! Thought i have found that this API is called just before the crash happens in a new thread.. i logged all of the calls to ReadProcessMemory and the second parameter pBaseAddress is never even close to the memory i changed.. it must be something else or am i missing something?
    – 0xAK
    Commented Mar 12, 2015 at 9:56

1 Answer 1

2

Some possibilities (out of many):

1. The program may call SetThreadContext, or ZwContinue which sets all registers using a new CONTEXT. If the DRx registers are reset then your hardware breakpoints are removed.

2. The program calls ZwSetInformationThread with the 0x11 (ThreadHideFromDebugger) parameter. If the thread is hidden from the debugger then breakpoint exceptions will not be caught by a debugger but will be passed to the program, if unhandled - it will crash.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.