[TUT] Anti debug stuff and a short journey in the PEB (Process enviroment block)

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

x86asm

Jr.Coder
Full Member
Nobleman
Jan 3, 2013
53
438
0
Hello folks, I have wrote a little anti debug class for you.

I explain this stuff in short:

IsDbgPresent(); ( my own function )
This does the same like IsDebuggerPresent();( WIN API function )
The only advantage of my implementation is that a reverse engineer can´t see a call to IsDebuggerPresent in the intermodular call list.

How works this stuff interal?
Its really simple:

C++:
bool AntiDbg :: IsDbgPresent()
{
bool var;
        _asm
        {
            mov eax,dword ptr fs:[0x30]  ; Copy address of process enviroment block in eax
            mov eax,[eax+0x2]            ; Address of process enviroment block + 2  ( eax includes now the address of the BeingDebugged field )
            mov dword ptr [var],eax      ; Writes the value from the BeingDebugged field into our variable int var;
        }
return var;
}
[For 32 Bit window use the x86 WinDbg Version, for 64Bit Windows use the x64 WinDbg Version.)

Click in WinDbg on File-> Open Executable now choose a file that you want to debug:
Here we go, look at this output from WinDbg(I have truncated unimportant things from debugger output):

0:000> !peb
PEB at 7efde000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: Yes
ImageBaseAddress: 00400000


Okay, in WinDbg we write: 0:000> !peb
We see: PEB at 7efde000

Now write: 0:000> dt _peb 7efde000
And we see this ( I have truncated unimportant things again):

C++:
0:000> dt _peb 7efde000
ntdll!_PEB
   +0x002 BeingDebugged    : 0x1 ''
   +0x068 NtGlobalFlag     : 0x70

So lets start a second instance of WinDbg, now we will use WinDbg as a local kernel debugger:
But at first open your cmd.exe as administrator and type in: bcdedit /debug on
Now you must restart your computer, after this you can use WinDbg as a local kernel debugger.
With bcdedit /debug off you can disable the windows kernel debugging mode.(PC restart is necessary)

The nice thing now is that the process enviroment block dont know that we debug him.


Lets take a look at the kernel debugger output and compare it with the first output:
{ Ok, I dont want that you guys waste your time there are only 2 fields in process enviroment block which you can use for anti debug stuff.
BeingDebug and NtGobalFlag }

I have make also tests with the other fields (Ok I have just check the "surface" fields, if you go a little bit deeper you will find
maybe more useful stuff.)

But now the kernel debugger output(I have truncated unimportant things again):

C++:
0:000> dt _peb 7efde000
ntdll!_PEB
   +0x002 BeingDebugged    : 0 ''
   +0x068 NtGlobalFlag     : 0

The interesting fields of the first output:
+0x002 BeingDebugged : 0x1 ''
+0x068 NtGlobalFlag : 0x70

Now the kernel debugger output:
+0x002 BeingDebugged : 0x0 ''
+0x068 NtGlobalFlag : 0x0

So if the process is running NOT in a debugger enviroment the field BeingDebugger is set on 0 and NtGlobalFlag also 0.

Simple isnt it?


My second anti debug functions should be clear if you have understand one simple thing. If you set a breakpoint for example in OllyDebugger
(press F2 to set a breakpoint) the debugger will write to the target address this opcode: 0xcc

My function just scans a specified memory area for breakpoints.

Look at this example:

C++:
#include <iostream>
#include <windows>
#include "AntiDbg.h"
using namespace std;

int main()
{
AntiDbg dbg;
HANDLE h = LoadLibrary ( "user32.dll" );
	   if ( h == 0 )
	   {
		  cout<<"LoadLibrary error: " << GetLastError() << "\n";
		  cin.get(); return 0;
	   }
	   
void* addr = GetProcAddress ( h,"MessageBoxA");
	   if ( addr == 0 )
	   {
		  cout<<"GetProcAddress error: " << GetLastError() << "\n";
		  cin.get(); return 0;
	   }
	   
MEMORYSCAN mem;
mem.StartScanAddr = reinterpret_cast<unsigned>(addr);
mem.EndScanAddr   = mem.StartScanAddr + 0x48;   // 0x48 bytes until the last opcode
mem.DebuggerDetected = false;
HANDLE threadHandle = dbg.StartMemoryScan( &mem );
   while ( 1 )
   {
	  cout<<"Try to set a breakpoint in function MessageBoxA (user32.dll) \n";
	  if ( mem.DebuggerDetected == true )
	  {
		 cout<<"Debugger detected !\n";
		 CloseHandle(threadHandle);
		 ExitProcess(0);
	  }
   Sleep(500);
   }
}
This piece of code observes the MessageBoxA function, if you set a breakpoint inside the MessageBoxA function it will scream: Debugger detected !


Here you can download my AntiDebug class: https://www.pixelbanane.de/yafu/244442336/AntiDbg+class.rar
 

x86asm

Jr.Coder
Full Member
Nobleman
Jan 3, 2013
53
438
0
bool AntiDbg :: IsDbgPresent(); and bool AntiDbg :: NtGlobal(); flag is very easy to bypass.
Just write a 0 in the right process memory field.

I would recommend to write a debugger plugin for that, or take one of the million plugins which are already available.

C++:
	  if ( mem.DebuggerDetected == true )  // Just patch the jump to bypass this
	  {
		 cout<<"Debugger detected !\n";
		 CloseHandle(threadHandle);
		 ExitProcess(0);
	  }
Just must examine the application in a debugger, its very important to understand whats going on there, then you can bypass the anti debugger functions.
Detecting and bypassing anti debugger functions is not so easy, but the good thing is that a lot of anti debug plugins exist already which make the reverse engineering process a little bit easier.

I have also wrote a little console game, this game includes another anti debug routine, I have discovered that when I was reading in a Intel documentation.
I have saw this function and I thought mhhm maybe I can abuse it for anti debug purpose

Here you can find a lot of documentations: https://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html
I guess this documents include much more interesting stuff which you can use for anti debug stuff.

I talk about the RDTSC instruction, my anti debug function is very simple:

C++:
long GetTimeStampCounter()
{
long tsc1;
   _asm
   {
      RDTSC
      mov tsc1,edx // The RDTSC instruction loads the current count of the
                   // time-stamp counter into the EDX:EAX registers.
	  // I use just the edx register
   }
return tsc1;
}
How it works:

C++:
long TimeStamp1 = GetTimeStampCounter();

... alot of code
... alot of code
... alot of code

long TimeStamp2 = GetTimeStampCounter();

        if ( TimeStamp2 > TimeStamp1+1 )
        {
            cout<<"Debugger detected !\n";
        }
If someone executes the first GetTimeStampCounter(); function then a time stamp value is safed.
Now the reverse engineer is inspecting the other lines of code. After a few mins/hour/whatever he executes the second GetTimeStampCounter(); function.
So, if he was to slow with his reverse engineering then we got him. :D
I have wrote a little console game to demonstrate this and I have made also a little video of it.





Btw. here you can see the memory scan function (from my first post ) in action:
https://www.pixelbanane.de/yafu/2300231920/Memory+scan.rar


And now the console game source code:

C++:
#include <iostream>
#include <vector>
#include <conio>

#define KEYUP 119
#define KEYDOWN 115
#define KEYRIGHT 100
#define KEYLEFT 97


using namespace std;



long GetTimeStampCounter()
{
long tsc1;
   _asm
   {
      RDTSC
      mov tsc1,edx // The RDTSC instruction loads the current count of the
                   // time-stamp counter into the EDX:EAX registers.
				   // I use just the edx register
   }
return tsc1;
}


void SpawnFood(int &Food_x, int &Food_y, const char FoodSymbol )
{
    Food_x = rand()%20+1;
    Food_y = rand()%20+1;
    gotoxy(Food_x,Food_y);
    cout<<FoodSymbol; // The food^^
}


void ShowCurrentScores ( unsigned &scores)
{
        gotoxy(1,1);
        cout<<"Scores: " << scores;

}

void CollisionDetection( int &Food_x, int &Food_y, int &x, int &y, unsigned &scores )
{
char PlayerSymbol = '\x1';

        long TimeStamp1 = GetTimeStampCounter ();
        
        if ( Food_x == x && Food_y == y )
        {
            SpawnFood(Food_x,Food_y,'\x4');
            scores++;
        }

// Wall collision detection starts her -----------------------------------------
        if ( x <= 0 )
        {
           x=1;
           gotoxy(x,y);
           cout<<PlayerSymbol;
        }

        if ( x >= 81 )
        {
           x=80;
           gotoxy(x,y);
           cout<<PlayerSymbol;
        }
        if ( y <= 0 )
        {
           y=1;
           gotoxy(x,y);
           cout<<PlayerSymbol;
        }
        if ( y >= 26 )
        {
           y=25;
           gotoxy(x,y);
           cout<<PlayerSymbol;
        }
//------------------------------------------------------------------------------

        long TimeStamp2 = GetTimeStampCounter ();

        if ( TimeStamp2 > TimeStamp1+1 )
        {
            cout<<"Debugger detected !\n";
        }


}

void ShowCurrentPosition(int &x, int &y)
{
   gotoxy(20,1);
   cout<<"x: " << x << "    " << "y: " << y << "\n";
}

int main()
{
int x=8,y=8;
int Food_x=10,Food_y = 10;

const char Player = '\x1';
const char FoodSymbol = '\x4';

unsigned key;
unsigned scores=0;



srand(time(NULL));

ShowCurrentScores(scores);
ShowCurrentPosition(x,y);

gotoxy(x,y);
cout<<Player;

SpawnFood ( Food_x, Food_y, FoodSymbol );

  while(1)
  {
        gotoxy(x,y); // holds input cursor on player position
        key = getch();

        switch(key)
        {
            case KEYUP:
               y--;
               gotoxy(x,y);
               cout<<Player;
               gotoxy(x,y+1);
               cout<<" ";
            break;


            case KEYDOWN:
               y++;
               gotoxy(x,y);
               cout<<Player;
               gotoxy(x,y-1);
               cout<<" ";
            break;



            case KEYRIGHT:
               x++;
               gotoxy(x,y);
               cout<<Player;
               gotoxy(x-1,y);
               cout<<" ";
            break;


            case KEYLEFT:
               x--;
               gotoxy(x,y);
               cout<<Player;
               gotoxy(x+1,y);
               cout<<" ";
            break;
        }

        CollisionDetection(Food_x, Food_y, x, y, scores );
        ShowCurrentScores(scores);
        ShowCurrentPosition(x,y);

  }

}
And a video where you can see the anti debug function in action: https://www.pixelbanane.de/yafu/396356392/console+game.rar
Btw. you can move the character ingame with the keys: w a s d

[ In the download folder you will find also a file with the name "console game.udd" you can use this file
with ImmunityDebugger. If you use this file then you can see the comments which I have made in
the binary.]

How to use the UDD file:
Download and install ImmunityDebugger (its like Olly but with a few more extras): https://www.immunityinc.com/products-immdbg.shtml
Start ImmunityDebugger click on "Options" Apperance then choose your UDD path.

But I give you guys also the memory addresses:

C++:
00401DBD   E8 F2FAFFFF      CALL console_.004018B4                   ; void CollisionDetection( int &Food_x, int &Food_y, int &x, int &y, unsigned &scores )
004018BE  |. E8 E9F9FFFF    CALL console_.004012AC                   ;  long TimeStamp1 = GetTimeStampCounter();
004019C3  |> E8 E4F8FFFF    CALL console_.004012AC                   ;  long TimeStamp2 = GetTimeStampCounter();

This is the hot part :D 

004019CF  |. 3B45 F4        CMP EAX,DWORD PTR SS:[EBP-C]
004019D2  |. 7D 12          JGE SHORT console_.004019E6
004019D4  |. 68 A7C04100    PUSH console_.0041C0A7                   ;  ASCII "Debugger detected !
"
004019D9  |. 68 381E4200    PUSH console_.00421E38
004019DE  |. E8 65FBFFFF    CALL console_.00401548

To bypass this stuff just write: JMP SHORT console_.004019E6
In reverse engineering its very important to discover and understand the anti debug stuff ... Otherwise your target application will make you crazy. ^^

Instead of RDTSC you could also use a API function like: GetSystemTime
https://msdn.microsoft.com/de-de/library/windows/desktop/ms724390(v=vs.85).aspx

But for my taste is it to conspicuous.
 
Last edited:

x86asm

Jr.Coder
Full Member
Nobleman
Jan 3, 2013
53
438
0
Thank you guys for your feedback, I have updated my second post in this thread. Just check it out.
 
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods