Anti-Debug Fiber Local Storage (FLS)

Peter Ferrie mentioned a nice trick in his Anti-Debugging Reference article http://pferrie.host22.com/papers/antidebug.pdf 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:

NTSYSCALLAPI
NTSTATUS
NTAPI
RtlProcessFlsData (
	PRTL_UNKNOWN_FLS_DATA Buffer
);

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;
} RTL_UNKNOWN_FLS_DATA,*PRTL_UNKNOWN_FLS_DATA;

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;
} FLS_CALLBACK, *PFLS_CALLBACK;

#define UNKNOWN_MAX_CALLBACKS 5

typedef struct _FLS_CALLBACK_INFO
{
	PVOID Unknown;
	FLS_CALLBACK Callbacks[UNKNOWN_MAX_CALLBACKS];
} FLS_CALLBACK_INFO, *PFLS_CALLBACK_INFO;

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
#define PEB_FLS_CALLBACK_OFFSET 0x0320
#define PEB_FLS_NUMBERCALLBACKS_OFFSET 0x0350
	pPeb = (DWORD_PTR)__readgsqword(12 * sizeof(DWORD_PTR)); //PEB Address
#else
#define PEB_FLS_CALLBACK_OFFSET 0x020C
#define PEB_FLS_NUMBERCALLBACKS_OFFSET 0x022C
	pPeb = (DWORD_PTR)__readfsdword(12 * sizeof(DWORD_PTR)); //PEB Address
#endif

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

	//backup
	backupFlsNumberOfCallbacks = *pFlsNumberOfCallbacks;
	backupFlsCallback = *pFlsCallbackInfo;

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

	RtlProcessFlsData(&rtl);
	
	//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:
https://bitbucket.org/NtQuery/teststuff/downloads/RtlProcessFlsData.rar
https://bitbucket.org/NtQuery/teststuff/src/bf9561261acb36bf992f0da2ca143d531086aa01/RtlProcessFlsData.cpp?at=master

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 comment