In this final part of the anti-debugging series we're going to discuss process and thread block based anti-debugging. Processes and threads must be maintained and tracked by the operating system. In user space, information about the processes and threads are held in memory in structures known as the process information block (PIB), process environment block (PEB) and the thread information block (TIB). These structures hold data pertinent to the operation of that particular process or thread which is read by many of the API based anti-debugging methods we discussed previously.

When a debugger or reverse engineer tries to get aggressive and hook calls to anti-debugging related APIs we can move lower than the API and directly access the process and thread information to detect the attached debugger. By side stepping the operating system provided methods for querying process and thread information, we can effectively bypass some API based hooking techniques used in anti-anti-debugging efforts.

For example, in part II of this anti-debugging series I demonstrated how to make a call to IsDebuggerPresent() to detect if the debugger present process flag is set.

Prototype: BOOL WINAPI IsDebuggerPresent(void); 

if (IsDebuggerPresent()) {
    //Debugger Detected - Do Something Here
} else {
    //No Debugger Detected - Continue

If we analyzed what this API call actually does we would notice that it reads a flag from the PEB which indicates the presence of a debugger. Instead of directly calling the API, it is possible to emulate what the IsDebuggerPresent() function does and directly query the PEB ourselves.

The first step in analyzing data within the PEB structure is to locate the PEB structure in memory. To do this we can use a number of different methods, some more direct and low level that others. The method that is easiest to grasp is to call the function NtQueryInformationProcess with a second parameter of ProcessBasicInformation. This returns a pointer to the process information block (PIB) for the requested process. Once we have access to this PIB structure we look at the PebBaseAddress member to determine the base address of the PEB. Finally, we look at the boolean member BeingDebugged to return the same result that would be returned had we called the function IsDebuggerPresent().

The following code demonstrates our example:

hmod = LoadLibrary(L"Ntdll.dll");
_NtQueryInformationProcess = GetProcAddress(hmod, "NtQueryInformationProcess");

hnd = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
status = (_NtQueryInformationProcess) (hnd, ProcessBasicInformation, &pPIB, sizeof(PROCESS_BASIC_INFORMATION), &bytesWritten);

if (status == 0 ) {
  if (pPIB.PebBaseAddress->BeingDebugged == 1) {
    MessageBox(NULL, L"Debugger Detected Using PEB!IsDebugged", L"Debugger Detected", MB_OK);
  } else {
    MessageBox(NULL, L"No Debugger Detected", L"No Debugger Detected", MB_OK);

There are a number of different ways that we can query the PEB and TIB blocks to detect the presence of a debugger. Let's divert from the straight forward and instead look at a novel and interesting method of detecting a debugger specifically designed to operate under Windows Vista. In Vista, when a process is started without a debugger present, the main thread environment block contains a pointer to a Unicode string referencing a system DLL such as kernel32.dll. If the process is started under a debugger, that system DLL name is replaced with the Unicode string “HookSwitchHookEnabledEvent”. Thus if we know that the process we are trying to protect is running within a Windows Vista environment, we can use this technique to determine if the processes was launched from within a debugging environment.

To use this technique, the anti-debugging function should first check that it is running on the Windows Vista operating system. After confirming the operating system revision, the technique should locate the TIB. The TIB can be accessed as an offset of segment register FS as in the following code:

void* getTib()
  void *pTib;
  __asm {
    mov EAX, FS:[18h] //FS:[18h] is the location of the TIB
    mov [pTib], EAX
  return pTib;

Once the location of the TIB is found, the offset 0xBFC from the start of the TIB is read and the pointer checked. If this value is 0x00000C00 we then read the string at offset 0xC00 and compare this value to the Unicode string “HookSwitchHookEnabledEvent”. We check the pointer to ensure that we have a string located in the pointed to address and as a second level of assurance for the accuracy of this method. If we pass this final test we can be sure that our process running under Windows Vista was started from within a debugger.

wchar_t *hookStr = _TEXT("HookSwitchHookEnabledEvent");
strPtr = TIB+0xBFC;

delta = (int)(*strPtr) - (int)strPtr;
if (delta == 0x04) {
   if (wcscmp(*strPtr, hookStr)==0) {
      MessageBox(NULL, L"Debugger Detected Via Vista TEB System DLL PTR", L"Debugger Detected", MB_OK);
    } else {
      MessageBox(NULL, L"No Debugger Detected", L"No Debugger", MB_OK);
} else {
   MessageBox(NULL, L"No Debugger Detected", L"No Debugger", MB_OK);

In the four parts of this series we have discussed classes of anti-debugging methods, a few basic API based anti-debugging techniques, some slightly more advanced API techniques, and finally two methods that directly access process and thread information to detect the presence of a debugger.

Instead of continuing this series in blog format, I've decided to release a paper outlining the details of nearly 35 different anti-debugging methods. I'll be presenting the paper (and associated slides) at the SOURCE Boston 2009 security conference which starts March 11th, 2009 and finishes up March 13, 2009. The paper and presentation are geared towards developers and software engineers who may not understand the assembly dump of some anti-debugging code but can understand what I've presented to you thus far.

The pre-registration rates for SOURCE Boston end on February 28, 2009. So get your ticket at a discount while you still can! It's going to be a fantastic conference with some of the best information security topics and presenters in the industry.

Additionally, as a speaker, I've been given one ticket at half price to do with as I choose. As of yet I haven't given it away. If anyone would like a half off ticket to SOURCE Boston and can attend please let me know. I'll get the discount code over to you ASAP. I look forward to seeing you all at the conference, please come up and say hello!

Veracode Security Solutions
Security Threat Guides

About Tyler Shields

Tyler Shields is a Senior Researcher for the Veracode Research Lab whose responsibilities include understanding and examining interesting and relevant security and attack methods for integration into the Veracode product offerings. He also keeps track of new developments from other computer science and information security researchers to ensure that Veracode technologies are always kept in line with the most recent security advancements.

Comments (5)

Chris | February 28, 2009 5:09 pm

Too bad. I've been following this series, and was excited for it to go beyond API calls.

Tyler Shields | February 28, 2009 11:15 pm

@Chris Never fear! Like I said, the entire 35 or so methods are going to be released in a paper format at Source Boston. I'll be sure to make the paper available through a link on this blog as well. Thanks for following the posts to date, there is just too much information to write, it would tie up this blog indefinitely!

Jordan | March 16, 2009 11:39 am

Would love to see that paper now if it's available...

travis | March 18, 2009 7:11 am


excellent series and your presentation at was excellent as well. i'd be interested to see what debuggers do the best job at getting around these techniques.

Tyler Shields | March 26, 2009 3:02 pm

@Jordan. The paper and all associated source code is available in the whitepapers section of the Veracode web site.

Please Post Your Comments & Reviews

Your email address will not be published. Required fields are marked *

Love to learn about Application Security?

Get all the latest news, tips and articles delivered right to your inbox.