TLS에 관한 간단한 탐구

2013. 10. 21. 23:26 from Security

TLS는 Thread Local Storage의 약자로 스레드별로 연관 데이터를 기록하기 위해 사용될수 있다.

예를 들어 스레드의 생성 시간을 저장할 수 있도록 각 스레드별로 공간을 마련하여 스레드가 종료될 때 이 값을 이용하여 스레드의 수행 시간을 계산할 수 있다.


TLS도 Dynamic TLS와 Static TLS로 나뉘는데 이들 각각은 애플리케이션과 DLL에서 사용할 수 있다.

Static TLS는 사실상 다룰 내용이 많이 없기 때문에 이번 포스팅에선 Dynamic TLS에 관해서 다뤄볼려한다.


애플리케이션에서 Dynamic TLS의 장점을 활용하려면 네 개의 함수를 이용해야되는데 실제로 이런 함수들은 

DLL 개발시 자주 사용되기도 한다. 아래 그림은 마이크로소프트가 TLS를 관리하기 위해 내부적으로 사용하는

자료 구조의 모습이다.



위 그림은 시스템에서 수행 중인 단일 프로세스에 포함되어 있는 사용 중인 플래그들의 집합을 보여준다.

각각의 플래그는 FREE 상태나 INUSE 상태가 될 수 있으며 이 플래그들은 각각의 TLS 슬롯이 사용 중인지의

여부를 나타낸다. 


Dynamic TLS를 사용하려면 가장 먼저 TlsAlloc 함수를 호출해야 하는데 이 함수는 프로세스 내의 비트 플래그 배열로부터 FREE플래그의 위치를 찾아내어 해당 플래그 값을 INUSE 상태로 변경하고 비트 플래그 배열에서의 인덱스를 반환한다. 


스레드가 생성되면 시스템은 해당 스레드와 연계되는 TLS_MINIMUM_AVAILABLE 개수의 PVOID형 배열을 할당하고 0으로 초기화 한다. 스레드 별로 존재하는 PVOID 배열에 값을 저장하기 전에 이 배열의 어느 요소가 사용 가능한지를 알아야 하는데 이를 위해 TlsAlloc 함수를 호출 했다.


스레드 배열 내에 값을 할당하기 위해서는 TlsSetValue 함수를 호출하면 된다.


BOOL TlsSetValue(

DWORD dwTlsIndex,

PVOID pvTlsValue);


이 함수는 스레드가 가지고 있는 배열에서 dwTlsIndex 매개변수 값을 인덱스로 하는 공간에 pvTlsValue 매개변수로 전달하는 값을 할당한다. 스레드는 이렇게 TlsSetValue 함수를 호출하여 자신이 소유하고 있는 배열의 값을 변경할 수 있지만 다른 스레드에 있는 배열의 값은 변경하지 못한다.


스레드 배열로부터 값을 얻어오기 위해서는 TlsGetValue 함수를 호출하면 된다.


PVOID TlsGetValue(DWORD dwTlsIndex);


이 함수는 스레드가 소유하고 있는 TLS 슬롯으로부터 dwTlsIndex번째 값을 가져온다. TlsSetValue 함수와 마찬가지로 TlsGetValue 함수를 호출하는 스레드는 자신이 소유하고 있는 배열에서만 값을 가져올 수 있다.


프로세스 내의 모든 스레드에서 앞서 예약하였던 TLS  슬롯을 더이상 사용할 필요가 없는 시점이 되면 TlsFree 함수를 호출하면 된다.


BOOL TlsFree(DWORD dwTlsIndex);


아래는 스레드는 40바이트 크기의 구조체를 가리키는 포인터를 함수를 최초로 호출할때 전달한다고 가정하고 이런 종류의 함수는 이 함수가 다시 호출될 때 앞서 전달된 구조체를 다시 사용할 수 있도록 그 값을 저장하도록 하는 코드이다.



DWORD g_dwTlsIndex; // TlsAlloc 함수의 반환 값으로 가정


...


void MyFunction(PSOMESTRUCT pSomeStruct)

{

if (pSomeStruct != NULL)

{


if (TlsGetValue(g_dwTlsIndex) == NULL)

{

TlsSetValue(g_dwTlsIndex, HeapAlloc(GetProcessHeap(), 0, sizeof(*pSomeStruct));

}


memcpy(TlsGetValue(g_dwTlsIndex), pSomeStruct, sizeof(*pSomeStruct));


}


else

{

pSomeStruct = (PSOMESTRUCT) TlsGetValue(g_dwTlsIndex);


...


}

} 



# Reference


제프리 리쳐의 Windows via c/c++ 

http://debugjung.tistory.com/45

http://studyfoss.egloos.com/5259841







'Security' 카테고리의 다른 글

안티디버깅 간단 정리  (1) 2013.10.30
바인드쉘, 리버스쉘  (0) 2013.10.24
허..  (0) 2013.10.17
php extract vulnerability  (0) 2013.10.13
RTL시 pop pop ret, exit 함수 호출의 원리  (2) 2013.09.26
Posted by xer0s :