Peter Ferrie posted an interesting comment on my previous article. I decided to reply here, coz not everybody reads comments, but it’s discussion worth to be read.

Author : Peter Ferrie
> That’s not correct. You can’t display a message anymore from a TLS callback
> because USER32 is not initialised at that point,

I don’t try to display a message from TLS callback, I try do _not_ display it
XP SP3 and S2K3 allow me to call MessageBox form TLS, Vista does not, but I’m not talking about calling something from TLS. the point is - if there is no USER32, TLS isn’t called at all. check out FSC08_Level2.exe. it’s F-Secure’ crack-me. guys packed a file with UPX and added TLS callback, thus “upx -d” loses the TLS. it’s easy and you probably noticed this. but you definitely missed the point. there is MSVCR71.dll!exit there that is imported, but not actually used. UPX does not use MSVCR71.dll, so it was added by someone else. added manually. but for what’s reasons? the answer is - without it XP and S2K3 refuse to call TLS. so, guys from F-Secure met the bug and found the workaround. it proves that I’m right and the bug does exist :-)

> but it does really run. Create a TLS callback that looks like this:
> mov eax, dword ptr fs:[30h]
> l1: cmp byte ptr [eax + 2], 0
> je l1
> int 3
> and run it. The file will wait until the debugger attaches.
> That shows that the callback is running.

guess, your TLS callback is executed when the process is about the end, you don’t check for the reason argument. could you please show me your exe file? I show you mines. plz, download two examples. they are very simple:

#define Msg (int (WINAPI *)(int, char*, char*, int))
#define Box GetProcAddress(LoadLibrary(”USER32.DLL”),”MessageBoxA”)

#define TLS_B ” not”
#define TLS_C ” executed! *\n\n”
#define TLS_A “\n* TLS callback has been”

char TLS[] = TLS_A TLS_B TLS_C;

BOOL WINAPI TLS_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
if (fdwReason == 1) memmove(&TLS[sizeof(TLS_A)], &TLS[sizeof(TLS_A TLS_B)], sizeof(TLS_C));
return 0×666;

nezumi(){Msg Box (0, TLS, “[x]“, 0);}

DWORD ptr[] = { (DWORD) TLS_callback, 0 };
DWORD *xl[] = { (DWORD*) 0xEFBEADDE, ptr, ptr, (DWORD*) xl, ptr, 0, 0};
TLS callback just removes “not ” from the string displayed from the main functions. compile it, apply TLS Dir and run. under W2K TLS is executed, but it does not executed under XP/W2K3, however if you replace GetProcAddress(LoadLibrary(”USER32.DLL”),”MessageBoxA”) by a direct MessageBox call it will work fine.

btw, I found another interesting thing. run TLS-nousr.exe under Olly 1.10 (have not checked another ver) under XP/S2K3. ops! TLS callback is called. ok, run it under IDA-Pro debugger (console ver). wow! it’s not called! so, OllyDbg forces system to execute TLS somehow. have not found out how yet.