Skip to main content

IsDebuggerPresent API Vs Process Environment Block

 Sometimes we've seen some application or process that can't be debugged using any debugger. As soon as we attach a debugger, either the application will terminate or pop up a message like a debugger attached with the process, so terminating the application.


What so ever, in windows world, there is an API, which detects if the process is being debugged or not. 

It's IsDebuggerPresent() Win32 API. You can refer to the MSDN link to get more details on it.

So, I've written a test sample below:

#include <Windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
    if (IsDebuggerPresent() == TRUE)
    {
        MessageBox(NULL, 
        TEXT("Please close your debugging 
            application and restart the program"), 
        TEXT("Debugger Found!"), 0);
       ExitProcess(0);
    }
    MessageBox(NULL, TEXT("Hello World!"), TEXT("Bypassed"), 0);
    ExitProcess(0);
    return 0;
}

As usual, I did compile the code using VS 2013 on Windows 8 and then launched it with WinDbg and executed the command 'g'. As we can predict, it executed the if construct and displayed the following message, and eventually it executed ExitProcess(), and this process terminated.


Now, the question is how we can bypass this check and execute the Hello World part. To do so, we need to understand the process environment block. We can refer MSDN link.

The structure of PEB is like below:

typedef struct _PEB {
  BYTE                          Reserved1[2];
  BYTE                          BeingDebugged;
  BYTE                          Reserved2[1];
  PVOID                         Reserved3[2];
  PPEB_LDR_DATA                 Ldr;
  PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
  BYTE                          Reserved4[104];
  PVOID                         Reserved5[52];
  PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
  BYTE                          Reserved6[128];
  PVOID                         Reserved7[1];
  ULONG                         SessionId;
} PEB, *PPEB;

The highlighted one is of our interest. If this is set to true (1), then IsDebuggerPresent() Win32 API will also return true. So the trick is we need to set this bit to false(0) while debugging through WinDbg.

So, let's examine first this structure through our sample application using WinDbg. So, after launching the application, execute the following command:

0:000> !peb
PEB at 7f41f000
    InheritedAddressSpace:    No
    ReadImageFileExecOptions: No
    BeingDebugged:            Yes
    ImageBaseAddress:         00a50000
    Ldr                       77b791e0
    Ldr.Initialized:          Yes
    Ldr.InInitializationOrderModuleList: 012c3760 . 012c3c40
    Ldr.InLoadOrderModuleList:           012c3850 . 012c5b38

    Ldr.InMemoryOrderModuleList:         012c3858 . 012c5b40

Now, from the above result, we can see the BeingDebugged of PEB structure is set to true(1). If we set it to false (0) and then execute, we'll see, the Hello world window will appear. 

So, I've executed the following command through WinDbg:

eb $peb+2 0 ---> Edit byte PEB+2 to 0.

Now let's see again, the PEB!BeingDebugged value:

0:000> !peb
PEB at 7f41f000
    InheritedAddressSpace:    No
    ReadImageFileExecOptions: No
    BeingDebugged:            No
    ImageBaseAddress:         00a50000
    Ldr                       77b791e0
    Ldr.Initialized:          Yes
    Ldr.InInitializationOrderModuleList: 012c3760 . 012c3c40
    Ldr.InLoadOrderModuleList:           012c3850 . 012c5b38
    Ldr.InMemoryOrderModuleList:         012c3858 . 012c5b40

So, finally, we set this value to false(0). Now I executed the program with the command 'g' and the Hello World pop-up message got displayed. Indeed we've successfully bypassed IsDebuggerPresent() win32 API while debugging the application.

Happy Debugging!

Comments

Popular posts from this blog

Variadic template class to add numbers recursively during compilation

 The idea of having a class to add numbers (variable parameters) during compilation time recursively. Also wanted to restrict types to a single type while sending parameters to class member function. That said, if we mix int, float and double types to add function shall result in compilation error. How do we achieve this. The below is the code which actually helps to achieve this: <code> #include < fmt/format.h > template < typename T> class MyVarSumClass{     private :         T _sum = 0 ;     public :         template < typename ... TRest>         T add(T num, TRest... nums){             static_assert (std::conjunction<std::is_same<TRest, T>...>{}); /* Assert fails                if types are different */             _sum += num;             return add(nums...); // Next parameter packs gets picked recursively         }         // Base case         T add(T num){             _sum += num;             return _sum;         } }; int main() {     My

A simple approach to generate Fibonacci series via multi-threading

T his is a very simple approach taken to generate the Fibonacci series through multithreading. Here instead of a function, used a function object. The code is very simple and self-explanatory.  #include <iostream> #include <mutex> #include <thread> class Fib { public:     Fib() : _num0(1), _num1(1) {}     unsigned long operator()(); private:     unsigned long _num0, _num1;     std::mutex mu; }; unsigned long Fib::operator()() {     mu.lock(); // critical section, exclusive access to the below code by locking the mutex     unsigned long  temp = _num0;     _num0 = _num1;     _num1 = temp + _num0;     mu.unlock();     return temp; } int main() {     Fib f;          int i = 0;     unsigned long res = 0, res2= 0, res3 = 0;     std::cout << "Fibonacci series: ";     while (i <= 15) {         std::thread t1([&] { res = f(); }); // Capturing result to respective variable via lambda         std::thread t2([&] { res2 = f(); });         std::thread t3(

A concept to a product (Kimidori [ 黄緑]) - Part 2

In the previous part , we have seen KIMIDORI [ 黄緑] detect if a URL is malicious. In this part, we will see the details that KIMIDORI [ 黄緑] fetches out of the URL provided. As an example, provided a safe URL, https://www.azuresys.com/, and let's see what it brings out: As we can see, the link is safe and the link is active, which means we can just click on the link to open it on IE.  Now it's time to look into the URL report (still under development):  We have URLs IP, Location, and HTTP Status code. The Report part is a sliding window, the Show Report button shows as well as hides the report. Show / Hide Report is a toggle button. Let's see if we get the same details for any bad (phishing / malicious) URL: Took an URL example from a phishing link and tested it. The tool detected it as not a good link (Screen Shot Below) & link does not activate unlike a safe URL: Now let's see the report part for more details including domain registration details: It looks like it&