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.
ReadProcessMemory
and the second parameterpBaseAddress
is never even close to the memory i changed.. it must be something else or am i missing something?