Log in

View Full Version : IsDebuggerPresent - how to bypass WITHOUT changing the mem


Fahr
May 7th, 2004, 08:17
Hello all,

I'm working on an ASPR packed file, no problems there (thanks to hobferret and LaBBa) and I was just wondering if it would be possible to bypass IsDebuggerPresent in some other way.
What I do now is break on IsDebuggerPresent, step twice and change the value in the memory that is going to be written to EAX. No probs, all runs fine.
However, I also tried to fix the JE that tests the AL after the call to IsDebuggerPresent. I also tried to fix the value in EAX itself after the call. In both cases everything goes bad!
For some reason, if I do anything else than changing the value in memory (like fixing the jump or changing EAX), the packer code eventually lands in either a data segment, an endless loop or at 0.
Not that it's really NEEDED to bypass it some other way (though it would be more convenient when writing a loader), I was just wondering WHY it goes like this. Logically, I'd say fixing the jump or EAX should take care of it. There is only one call to IsDebuggerPresent, so why does it only work when I change the value in memory?

Maybe someone can shed some light on this issue.

Thanks,
- Fahr

nikolatesla20
May 7th, 2004, 09:01
If you change the JE, you are modding the program code, and it no doubt detects this with a CRC routine of some sort. Also, if you wait until the code returns, and then change the value in eax, you are once again "modding" the code in a way because you are setting a breakpoint in the code.

The safest and most effective way to modify IsDebuggerPresent detection is to edit the Program's thread block. This is easy in OllyDbg. You can do this before the program even starts to run, after Olly loads it.

NOTE THIS example works for Windows 2000 / XP.

Open your program in OllyDbg. Note the value of the FS register. On my 2000 system, it's 7FFDE000. Go to the hex dump window in Olly (at the bottom) and right click and say Go To->Expression and type in this value.

Now, at FS[30], which would be 7FFDE030 on my machine (30 bytes in ) there is another address, this points to the program's thread environment block (TEB). Select this address in the window by clicking and selecting it, then right click and say "Follow DWORD in dump". This address by the way in my 2000 system is 7FFDF000.

Now, 3 bytes in you will see a 01. This is telling windows the program is being debugged. Change it to a zero by selecting it, and just start typing in zero, zero. Olly brings up the memory edit window, after entering the zeros just push ok and now you are hidden from the IsDebuggerPresent detector, and you didn't modify or edit any program memory or API memory. In fact, the program hasn't even started yet.

-nt20

SHaG
May 7th, 2004, 09:09
There are also plugins for OllyDbg that do this shit for you...
- IsDebuggerPresent by Asterix
- OllyScript v0.8 by SHaG (that's me =) )

Fahr
May 7th, 2004, 09:11
Quote:
[Originally Posted by nikolatesla20]If you change the JE, you are modding the program code, and it no doubt detects this with a CRC routine of some sort. Also, if you wait until the code returns, and then change the value in eax, you are once again "modding" the code in a way because you are setting a breakpoint in the code.


True, but setting a breakpoint seems to have no real effect; if I set a breakpoint on the CALL to IsDebuggerPresent (not INSIDE the call, but on the statement where it is called) or a few lines before it, then trace into the call and modify the mem, it runs fine...
Also, when I change the JE to JMP, then jump it, then change it BACK into JE, it also goes WRONG.
Even more extreme; if at the JE (which it doesn't take), I change the EIP into the value it SHOULD jump to (then I didn't modify anything), it goes wrong!
This is so bizarre...

Quote:
Open your program in OllyDbg. Note the value of the FS register. On my 2000 system, it's 7FFDE000. Go to the hex dump window in Olly (at the bottom) and right click and say Go To->Expression and type in this value.

Now, at FS[30], which would be 7FFDE030 on my machine (30 bytes in ) there is another address, this points to the program's thread environment block (TEB). Select this address in the window by clicking and selecting it, then right click and say "Follow DWORD in dump". This address by the way in my 2000 system is 7FFDF000.

Now, 3 bytes in you will see a 01. This is telling windows the program is being debugged. Change it to a zero by selecting it, and just start typing in zero, zero. Olly brings up the memory edit window, after entering the zeros just push ok and now you are hidden from the IsDebuggerPresent detector, and you didn't modify or edit any program memory or API memory. In fact, the program hasn't even started yet.

This is VERY interesting! I usually do it like this; I put a BP on IsDebuggerPresent, then once it breaks, I step twice, follow the address in mem and change the value (which is at 7FFDF002, like yours).
Is there a generic way to determine this TEB and the address of the debugger 01? One that will work on all platforms? That way I could disable the IsDebuggerPresent byte before running the actual program (from a potential loader).
There is a isDebuggerPresent hider plugin for OllyDBG, which uses the OllyDBG API to do about the same as far as I could see...

Thanks,
- Fahr

Fahr
May 7th, 2004, 09:13
Quote:
[Originally Posted by SHaG]There are also plugins for OllyDbg that do this shit for you...
- IsDebuggerPresent by Asterix
- OllyScript v0.8 by SHaG (that's me =) )


Thanks, I knew the first one, I'll look into the second one.
But I am more interested in how it actually works and why it doesn't than tools to bypass it (I can pretty much bypass it by hand).

Thanks,
- Fahr

Ricardo Narvaja
May 7th, 2004, 09:48
Varios debugger not only detect the byte 7ffdf002 by the apis IsDebuggerPresent, also test directly the value of this byte, for this reason, if you donīt change the value in memory to zero, the program detect and donīt run.

Ricardo

Fahr
May 7th, 2004, 10:16
Quote:
[Originally Posted by Ricardo Narvaja]Varios debugger not only detect the byte 7ffdf002 by the apis IsDebuggerPresent, also test directly the value of this byte, for this reason, if you donīt change the value in memory to zero, the program detect and donīt run.

Ricardo


That would indeed explain a few things...
new question now is; how do I find this byte by myself? I assume it's not always 7ffdf002...

Thanks,
- Fahr

Fahr
May 7th, 2004, 10:30
I fiddled around a bit. At the beginning of the process I can read the value of FS from the Context I get with GetThreadContext.
However, this value is 0x38, just like in Olly at startup, it says FS is 0x38. Olly also states that it is somehow connected 7FFDE000; the full line is:

S 0 FS 0038 32bit 7FFDE000(FFF)

I can only select (and change) the 0038... so how do I get 7FFDE000 if I have the FS value of 0x38?

Thanks,
- Fahr

Ricardo Narvaja
May 7th, 2004, 10:37
The packers uses generally the same lines of code of the api IsDebuggerPresent, but out of the api, in this form, the exe detect the debugger without the use of api IsDebug.
In my machine when i start a program, EBX point to the value, right click in ebx -follow in dump and the 3 value is the byte to change.

Ricardo.





Quote:
[Originally Posted by Fahr]I fiddled around a bit. At the beginning of the process I can read the value of FS from the Context I get with GetThreadContext.
However, this value is 0x38, just like in Olly at startup, it says FS is 0x38. Olly also states that it is somehow connected 7FFDE000; the full line is:

S 0 FS 0038 32bit 7FFDE000(FFF)

I can only select (and change) the 0038... so how do I get 7FFDE000 if I have the FS value of 0x38?

Thanks,
- Fahr

Fahr
May 7th, 2004, 11:09
You are right! EBX points to the right location

Thanks a lot, you just solved all my problems

- Fahr

nikolatesla20
May 7th, 2004, 12:09
Quote:
[Originally Posted by Fahr]I fiddled around a bit. At the beginning of the process I can read the value of FS from the Context I get with GetThreadContext.
However, this value is 0x38, just like in Olly at startup, it says FS is 0x38. Olly also states that it is somehow connected 7FFDE000; the full line is:

S 0 FS 0038 32bit 7FFDE000(FFF)

I can only select (and change) the 0038... so how do I get 7FFDE000 if I have the FS value of 0x38?

Thanks,
- Fahr



Code:

char KillIsDebuggerPresent (PROCESS_INFORMATION pi)
{
DWORD tib, pib;
LDT_ENTRY segselector;
CONTEXT TempContext;

TempContext.ContextFlags = CONTEXT_SEGMENTS;
GetThreadContext(pi.hThread,&TempContext);
GetThreadSelectorEntry (pi.hThread, TempContext.SegFs, &segselector);
tib = ((segselector.HighWord.Bytes.BaseHi) << 24) +
((segselector.HighWord.Bytes.BaseMid) << 16) +
(segselector.BaseLow);
//printf ("TIB @ %X\n", tib);

if (ReadProcessMemory (pi.hProcess, (void *)(tib+0x30), &pib, sizeof (pib), NULL) == 0)
{
printf ("Could not get PIB from TIB !\n";

return 0;
}
else
{
char debug_info = 0xFF;
// printf ("PIB @ %X\n", pib);
pib += 2;
if (ReadProcessMemory (pi.hProcess, (void *)pib, &debug_info, sizeof (debug_info), NULL) == 0)
{
printf ("Unable to read from PIB !\n";

return 0;
}
else
{
// printf ("Old debug value in PIB: %X\n", debug_info);
if (debug_info != 0x01)
{
printf ("PB value unexpected. Aborting!";

return 0;
}
else
{
debug_info = 0;
if (WriteProcessMemory (pi.hProcess, (void *)pib, &debug_info, sizeof (debug_info), NULL) == 0)
{
printf ("Could not write new value into PIB !\n";

return 0;
}
else
{
// printf ("PIB debug value override ok!\n";
return 1;
}
} // debug info
} // read pib
} // read tib
}


Shared with hopeful permission from Squidge.

-nt20

Fahr
May 8th, 2004, 10:11
A generic way! That is exactly what I was looking for

Thanks to you and thanks to Squidge

- Fahr