# dynamic TLS callbacks instead of SEH

static TLS are not static at all! actually, they’re dynamic. statically declared TLS could be changed in run-time without using any API. it’s possible to register/unregistered new TLS callbacks on the fly even after the file has been loaded.

it was a long story – I tried to found where OS keeps TLS info, but was unable to do it. suddenly something hit me – maybe OS does not keep TLS info at all? maybe OS reads PE file directly? quick investigation confirmed this suggestion. as a matter of fact: OS re-reads PE-header and .tls every time it need the data.

on any following even DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH, DLL_PROCESS_DETACH Windows NT reads Data Directories -> TLS Directory. if VirtualAddress isn’t zero, OS reads Address of Callbacks Array and executes the first callback in the list. after it, OS reads the next element of Address of Callbacks Array.

what does it mean? it means: a) we can add/remove new TLS callbacks from another TLS callback or the program; b) if TLS Directory does not fit our needs it’s possible to create the new one on the fly;

guess, we have a program with statically declared TLS callbacks or without TLS at all. the program changes TLS array or creates it from the scratch. how interesting and how useful for malware!

shell-codes and malware sometimes make errors leading to exceptions. not good! thus, malware uses SEH to intercept expectations and suppress them. it was easy. “was” because SafeSEH mechanism has been infixed. too bad for hackers! well, what’s about TLS? if TLS data or TLS callback array belongs to writable memory – no problem to change it on the fly. as it was mentioned before, any exception generated by TLS is suppressed by OS. so, we got what we want.

moreover. guess, a hacker attacking an application, does something wrong and the application crashes. OS terminates it, Dr. Wantons saves the log for future analysis. quite common scenario, isn’t? well, dynamic TLS callbacks is absolute differing thing. TLS callback is called after the critical error, but _before_ process will be finished. in other words, malicious code inside TLS callbacks will be called _after_ Dr. Watson have finished loggin!!!

another thing. add new TLS callback (or create TLS Dir from the scratch), raise an exception (kind of XOR EAX, EAX/MOV EAX, [EAX]) and… pass control to TLS. of course, critical message will appear, but… not every reverser will find out where control is passed after pressing “OK” key.

no matter how TLS info is changed, it might be a local process or something else. yes, it’s possible to add new callback to another process, using WriteProcessMemory.

to demonstrate this I wrote a simple test program adding TLS callback on the fly. download it and run. if you speaker makes “buzz” before and after Message Box it means the program works fine. otherwise: either you have no speaker, either something wrong.

source code is very simple. see it bellow:

BOOL WINAPI TLS_callback_01(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
BOOL WINAPI TLS_callback_02(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);

// TLS callback_01 is declared statically
// TLS callback_02 is not declared yet (will be added dynamically)
DWORD ptr[] = { (DWORD) TLS_callback_01, 0, 0 };
DWORD *xl[] = { (DWORD*) 0xEFBEADDE, ptr, ptr, (DWORD*) xl, ptr, 0, 0};

// this callback is declared statically
BOOL WINAPI TLS_callback_01(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
// add new call-back
if (fdwReason == 1) ptr[1] = (DWORD) TLS_callback_02;
return 0×666;

// this callback is not declared statically, will be added dynamically
BOOL WINAPI TLS_callback_02(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
// make sound
Beep(96, 6000); return 0×999;

// main function, just to be
nezumi() { MessageBox(0, “press ok to hear buzz”, “[x]“, 0); }



  1. Yes, this TLS trick and some others are in my new paper that Virus Bulletin published at the start of January. It will be free from my site in February.

  2. man, you’re the most interesting hacker I ever met!

  3. Fun stuff, I’ve played with this too. ;)

  4. Excellent. I found it in May, so only one month after you, but I did more with it. You’ll see next month. :-)

Leave a comment

Comments are closed.