Reverse Engineering for Beginners

(avery) #1
CHAPTER 65. THREAD LOCAL STORAGE CHAPTER 65. THREAD LOCAL STORAGE

12 {
13 rand_state=init;
14 }
15
16 int my_rand ()
17 {
18 rand_state=rand_state*RNG_a;
19 rand_state=rand_state+RNG_c;
20 return rand_state & 0x7fff;
21 }
22
23 int main()
24 {
25 my_srand(0x12345678);
26 printf ("%d\n", my_rand());
27 };


Hiew shows us that there is a new PE section in the executable file:.tls.

Listing 65.2: Optimizing MSVC 2013 x86
_TLS SEGMENT
_rand_state DD 01H DUP (?)
_TLS ENDS

_DATA SEGMENT
$SG84851 DB '%d', 0aH, 00H
_DATA ENDS
_TEXT SEGMENT

_init$ = 8 ; size = 4
_my_srand PROC
; FS:0=address of TIB
mov eax, DWORD PTR fs:__tls_array ; displayed in IDA as FS:2Ch
; EAX=address of TLS of process
mov ecx, DWORD PTR __tls_index
mov ecx, DWORD PTR [eax+ecx*4]
; ECX=current TLS segment
mov eax, DWORD PTR _init$[esp-4]
mov DWORD PTR _rand_state[ecx], eax
ret 0
_my_srand ENDP

_my_rand PROC
; FS:0=address of TIB
mov eax, DWORD PTR fs:__tls_array ; displayed in IDA as FS:2Ch
; EAX=address of TLS of process
mov ecx, DWORD PTR __tls_index
mov ecx, DWORD PTR [eax+ecx*4]
; ECX=current TLS segment
imul eax, DWORD PTR _rand_state[ecx], 1664525
add eax, 1013904223 ; 3c6ef35fH
mov DWORD PTR _rand_state[ecx], eax
and eax, 32767 ; 00007fffH
ret 0
_my_rand ENDP

_TEXT ENDS

rand_stateis now in theTLSsegment, and each thread has its own version of this variable. Here is how it’s accessed:
load the address of theTIBfrom FS:2Ch, then add an additional index (if needed), then calculate the address of theTLS
segment.

Then it’s possible to access therand_statevariable through the ECX register, which points to an unique area in each
thread.

TheFS:selector is familiar to every reverse engineer, it is specially used to always point toTIB, so it would be fast to load
the thread-specific data.

TheGS:selector is used in Win64 and the address of theTLSis 0x58:
Free download pdf