A time-based anti-debugging technique using the Kernel Transaction Manager

Anti-debugging techniques have been known for a long time. One way to detect the presence of debuggers (and also DBI frameworks like Pin, emulators, etc) is by measuring the time taken to execute a piece of code and comparing it against a maximum tolerated amount of time. This way we can detect if our code is being debugged/instrumented/emulated by detecting the latency introduced by the instrumentation tool.

In this Reverse Engineering StackExchange thread you can find a set of time-related functions that are commonly used in Windows environments in order to detect the presence of debuggers using time-checking strategies:

  • GetTickCount()
  • time()
  • RDTSC instruction
  • RDPMC instruction
  • GetLocalTime()
  • GetSystemTime()
  • KiGetTickCount()
  • QueryPerformanceCount()
  • timeGetTime()

You can find more details on these time-based antidebugging tricks on “The Ultimate Anti-Debugging Reference” by Peter Ferrie [PDF].

So a few weeks ago I found one more way to perform time-based debugger detection; the (mildly) interesting thing is that it doesn’t use functions that are directly related to time stuff, so it can be a bit more subtle than those well-known time functions.

The technique is based on the Windows Kernel Transaction Manager, which can be used to implement both transacted file operations and transacted Registry operations.

By calling the CreateTransaction function we can create a new transaction object. This is the signature of the function:

HANDLE WINAPI CreateTransaction(
  _In_opt_  LPSECURITY_ATTRIBUTES lpTransactionAttributes,
  _In_opt_  LPGUID UOW,
  _In_opt_  DWORD CreateOptions,
  _In_opt_  DWORD IsolationLevel,
  _In_opt_  DWORD IsolationFlags,
  _In_opt_  DWORD Timeout,
  _In_opt_  LPWSTR Description
);


The description of the Timeout parameter is interesting:

Timeout [in, optional]

The time-out interval, in milliseconds. If a nonzero value is specified, the transaction will be aborted when the interval elapses if it has not already reached the prepared state.

So yes, the idea is pretty straightforward:

  1. We create a transaction object with a timeout of, say, 1000 miliseconds.
  2. We trigger an action that should take longer than that timeout value when our program is being debugged/instrumented/emulated.
  3. We operate on the transaction object that we’ve previously created in step 1), for example by calling SetTransactionInformation. If step 2) took more than our (arbitrary) 1000 miliseconds timeout, the operation will fail. To be precise, when operating on an expired transaction object, GetLastError() will return error code 0x1A2D (ERROR_TRANSACTION_NOT_ACTIVE).

So this is the proof-of-concept code:

#include "stdafx.h"
#include <windows.h>
#include <ktmw32.h>
#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])
{
	int *pointer = NULL;

	HANDLE hTransaction = CreateTransaction(NULL, 0, TRANSACTION_DO_NOT_PROMOTE, 0, 0, 1000, L"Anti-debugging");
	if (hTransaction == INVALID_HANDLE_VALUE){
		printf("CreateTransaction failed.\n");
		exit(1);
	}

	printf("Transaction handle: 0x%08x\n", (DWORD)hTransaction);

	/* Do something that takes more than 1000 miliseconds when being debugged */
	__try{
		printf("Triggering an access violation...\n");
		*pointer = 0x4141;
		printf("This message shouldn't be shown.\n");
	}
	__except (EXCEPTION_EXECUTE_HANDLER){
		printf("Exception handler in action!\n");
	}

	if (SetTransactionInformation(hTransaction, 0, 0, 1000, L"A new description")){
		printf("[-] Debugger not detected.\n");
	}
	else{
		/* 0x1A2D: ERROR_TRANSACTION_NOT_ACTIVE */
		printf("[+] Debugger detected! Last Error: 0x%X\n", GetLastError());
	}
	CloseHandle(hTransaction);
	return 0;
}


Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s