Anti-Debug Fiber Local Storage (FLS)

Peter Ferrie mentioned a nice trick in his Anti-Debugging Reference article with RtlProcessFlsData. He provided a “cryptic” example code in assembler. Although his example will work, there are a lot of open questions he doesn’t answer. His code is not usable in a productive environment and I wanted to demonstrate this trick with a more readable and solid example. This trick is very undocumented and I couldn’t find any further information with Google. This trick works since Vista. Fiber Local Storage (FLS) is similar to Thread Local storage (TLS), because a thread is created which can be used to execute some hidden stuff.

Let’s start with the function RtlProcessFlsData, the real declaration is unknown, but it must be similar to this:

RtlProcessFlsData (

The API takes some unknown struct pointer as parameter. The structure must be similar to this:

typedef struct _RTL_UNKNOWN_FLS_DATA {
	PVOID unk1;
	PVOID unk2;
	PVOID unk3;
	PVOID Argument;

Only one structure member is relevant for this anti-debug trick. The trick further involves the Process Environment Block (PEB). We must replace two values. Again, the declaration/definition is unknown and not documented.

First we must replace a callback structure inside the PEB. The structure could look like this:

typedef struct _FLS_CALLBACK {
	PVOID Unknown;
	PVOID StartAddress;


typedef struct _FLS_CALLBACK_INFO
	PVOID Unknown;

We can define different callback addresses which will be executed one by one. The second PEB manipulation is the number of callbacks we have in our structure.

A working example code for x64 and x86 can look like this:

	info.Callbacks[0].StartAddress = ContinueExecution;

	rtl.unk1 = UnknownReturnBuffer;
	rtl.unk2 = UnknownReturnBuffer;
	rtl.unk3 = UnknownReturnBuffer;
	rtl.Argument = (LPVOID)0x1337;

	DWORD_PTR pPeb = 0;
#ifdef _WIN64
	pPeb = (DWORD_PTR)__readgsqword(12 * sizeof(DWORD_PTR)); //PEB Address
	pPeb = (DWORD_PTR)__readfsdword(12 * sizeof(DWORD_PTR)); //PEB Address

	pFlsNumberOfCallbacks = (ULONG *)(pPeb + PEB_FLS_NUMBERCALLBACKS_OFFSET);
	pFlsCallbackInfo = (DWORD_PTR *)(pPeb + PEB_FLS_CALLBACK_OFFSET);

	backupFlsNumberOfCallbacks = *pFlsNumberOfCallbacks;
	backupFlsCallback = *pFlsCallbackInfo;

	//we have only 1 callback in the struct
	*pFlsCallbackInfo = (DWORD_PTR)&info;
	*pFlsNumberOfCallbacks = 1;

	//restore everything like nothing happened
	*pFlsCallbackInfo = backupFlsCallback;
	*pFlsNumberOfCallbacks = backupFlsNumberOfCallbacks;

We must fill the RTL_UNKNOWN_FLS_DATA structure with the thread argument and some return buffer. In the FLS_CALLBACK_INFO structure we only have to fill in our thread start address. After RtlProcessFlsData, we should restore the original values in the PEB.

Source code and binaries here:


1 thought on “Anti-Debug Fiber Local Storage (FLS)

  1. I’m on a fully updated Windows 8.1 x64
    The 32bit version executable does the following effect:
    – Messagebox shows up
    – After pressing OK, executable crashes

    It isn’t happening with the 64bit executable.

Leave a Reply

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

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

Google photo

You are commenting using your Google 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 )

Connecting to %s