Be myself :: TLS 콜백 안티디버깅

달력

122024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

1 개요

TLS콜백 함수가 어떻게 안티 디버깅으로 사용되는지 어떻게 우회가 가능한지 살펴 볼 것이다.

 

2 TLS

TLS(Thread Local Storage)는 쓰레드 별로 독립된 메모리 공간이다. 프로세스에서 전역변수나 static변수를 마치 쓰레드의 지역변수처럼 사용하고 싶을 때 사용된다. 하지만 TLS 콜백 함수가 EP코드가 실행되기 전에 동작하는 특징을 이용해 안티디버깅 기법으로도 사용 된다.

일단 TLS콜백함수를 사용하는 소스코드를 살펴 보자.

#include<Windows.h> #pragma comment(linker, "/INCLUDE:__tls_used") //링커설정. tls사용함으로 void NTAPI Tls_Callback(PVOID THandle, DWORD Reason, PVOID Reserved) { if (IsDebuggerPresent()) //IsDebuggerPresent()함수를 이용해 디버깅 중인지 확인 {         MessageBoxA(NULL, "Not allowed Debuging..", "TLSCallback",MB_OK);         ExitProcess(1); } } #pragma data_seg(".CRT$XLX") //TLS콜백 사용시 꼭 필요한 섹션 PIMAGE_TLS_CALLBACK TLS_CALLBACk[] = { Tls_Callback, 0 }; // TLS callback 함수 등록 #pragma data_seg() int main(void) { MessageBoxA(NULL, "Hi There! this is Inj3cti0n ! ", "mainbox", MB_OK); return 0; }

주석처리를 해놓아서 딱히 어려운점은 없을 것 같다. IsDebuggerPresent 함수가 처음 소개되었는데, 이는 PEB에서 3번째 멤버(PEB.BeingDebugged)를 이용해 디버깅중인지 아닌지 확인하는 함수이다. 자세한 내용은 다음에 설명하도록 하겠다.

자 그럼 이렇게 컴파일 된 파일을 실행시켜 보겠다.

잘 된다. 그럼 올리디버거로 열어 보겠다.

열리지 않는다. 자 일단 누군가가 어떠한 파일을 올리디버거로 열었을 때 디버깅이 되지 않는다면 무척 당황스러울 것이다. 그렇다면 필자는 원인이 뭔지 확인하기 위해 제일 먼저 PEview로 확인을 해 볼 것이다. 그래서 확인을 해 봤더니 TLS Table이 있는 것이 아닌가.

그렇다면 이 파일은 TLS Callback을 이용하여 안티 디버깅을 했을 가능성이 많다. 테이블 내용을 살펴 보면 다음과 같다.

여기서 제일 중요한 맴버는 Address of Callbacks이다. 여기서 주의할 점은 Callbacks 복수로 나타나 있다. 그래서 이 값은 배열의 주소 값을 나타내며 여러 개의 TLS Callback 함수를 등록할 수 있다는 것을 암시한다. 이 값은 VA값으로 나타나 있다.

3 TLS callback 디버깅

자 그럼 어떻게 디버깅은 어떻게 할까. EP가 실행되기 전에 디버깅을 해야 하므로 일단, 올리디버거 옵션부터 변경해 준다.

그리고, PEview를 이용하여 TLS 테이블에서 TLS콜백의 시작주소 값을 알아 낸 후 올리디버거에서 브레이크걸고 IsDebuggerPresent함수를 우회하면 된다.

디렉토리에서 TLS함수 배열 주소를 찾은 뒤

Hex에디터에서 함수 시작 값을 찾고

올리디버거에서 BP를 걸고 디버깅해서 우회하면 성공!

 

4 수작업으로 tls추가

지금까지 살펴 보았듯이 PE구조에 TLS table만 추가해 주면 코드를 수정하지 않고 패치가 가능하다. 직접 해보자.

직접 패치 시킬 때, 빈 공간을 잡아야 하기에 빈 섹션을 이용하거나, 마지막 섹션의 크기를 늘리거나, 마지막 섹션을 추가하거나 하는 방법이 있다. 여기서 우린 마지막 섹션의 크기를 200바이트 늘려서 해보도록 하자.


<Image_section_header .rsrc>

Size of Raw Data값을 Hex에디터를 이용해 400으로 수정하고 마지막 부분에 200바이트를 추가 시킨다. 그 다음 Optional_header의 TLS Table값을 설정해 준다.

다음엔, .rsrc섹션에 Characteristics값을 IMAGE_SCN_CNT_CODE, IMAGE_SCN_CNT_MEM_EXECUTE, IMAGE_SCN_CNT_WRITE의 값으로 설정한다

 

마지막으로 IMAGE_TLS_DIRECTORY의 멤버를 참고하여 구성한다.

여기서 RETN 0C를 하는 이유는. TLS callback 함수의 인자의 개수가 3개이기 때문에 보정해 주는 역할을 하는 것이다.

이제 마지막으로 할 일은 FileOffset 9230부분에 명령어를 입력하는 것인데, 이 땐, 올리디버거를 이용해 어셈프로그래밍을 하는 것이 쉽다.

다음과 같이 입력하자.

그런 다음 Copy to executable –selection –Save file 을 선택해 저장한 후 실행 시키면 메시지 박스가 뜬 다음 실행되는 걸 볼 수 있다.

<실행 후 첫 번째 메시지> <두 번째 메시지>

'Reversing' 카테고리의 다른 글

WinDbg, xp 연동  (0) 2014.05.16
SEH를 이용한 안티디버깅  (1) 2014.05.15
인라인 패치  (0) 2014.05.11
Upack 분석중 정리  (0) 2014.05.10
UPX압축 디버깅  (0) 2014.05.09
Posted by flack3r
|