Be myself :: Be myself

달력

42024  이전 다음

  • 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

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
|

CodeEngn 베이직 올클

Wargame 2014. 5. 14. 20:40

ㅋㅋㅋ..;; 삽질하느라 시간 가고 롤하느라 시간가고 친구가 불러서 놀고.. 3일동안한게 고작 CodeEngn basic all clear..내일부터 초심으로 돌아가서 다시 빡세개 공부해야겠다!

'Wargame' 카테고리의 다른 글

Fc3 dark_eyes  (0) 2014.08.22
Suninatas all clear  (3) 2014.07.25
워게임 현황  (0) 2014.07.01
워게임 사이트  (0) 2014.05.05
BOF원정대 level3  (0) 2014.05.04
Posted by flack3r
|

인라인 패치

Reversing 2014. 5. 11. 13:45

1 개요

인라인 패치를 통해 지금까지 배운 내용들을 총 정리하는 시간을 가지자. 패치를 통해 파일의 내용이 어떻게 가상메모리상에 올라가는지, 가상메모리에 올라간 프로그램이 어떻게 실행 되는지 등의 그림을 그릴 수 있을 것이다. 이 기법은 후킹을 할때도 이용된다. 

2 분석

일단 파일의 내용이 어떻게 가상메모리 상에 올라가고, 연산되는지 전체적인 그림을 그리자
먼저 unpackme#1.aC.exe파일을 실행시켜 보자. 파일은 http://ap0x.jezgra.net/download/patchme_no1.rar 에서 받을 수 있다.

NAG(잔소리)라고 쓴 글자를 바꾸라는 것 같다.

Status의 메시지도 바꾸는 것이 우리의 목표이다.

일단 올리디버거로 디버깅하기 전에 우선, PE구조를 분석하여 이 파일이 가상메모리상에서 어떻게 존재하게 되는지 파악한다. 다음과 같은 그림이 그려진다. (각자 그려보자)

자, 이제 대략적인 메모리 구조가 파악이 됐으니 ollyDbg로 뜯어보면서 확인 이 메모리상에서 어떤 일이 벌어지는지 확인해 보자. 우선 분석을 하다보면 첫 번째, 반복 루틴을 만나게 된다.

EBX에 0x4010F5~0x401249까지의 값에 44의 XOR값으로 연산되고 있다. 여기서 XOR 은 기본적인 암호화, 복호화 연산에 잘 사용된다. 예를들어 a XOR 11로 암호화하고 a XOR 11로 복호화 하는식이다. 그렇다면 위의 값은 44로 위의 주소 값에 존재하는 값을 복호화 하고 있다. 계속 트레이싱 해보자. 두 번재 반복 루틴을 만난다.

EBX의 0x401007~0x401086까지의 값을 7로 복호화 하고있다. 계속 살펴 보자.

세 번째 루틴이다. EBX의 0x4010F5~0x401249 의 값을 11로 다시 복호화 하고 있다. 즉, 0x4010F5~0x401249영역은 첫 번째와 세 번째 루틴에서 두 번 복호화 하고 있다. 두 번 암호화 된 것이다.

자 계속 트레이싱 해보자.

0x401062의 명령어를 보면 0x4010F5~0x401249 영역의 값을 더한 값을 31EB8DB0의 값과 비교하고 있다. 이 것은 이 데이터가 손실되진 않았는지, 변형되진 않았는지 확인하는 CheckSum값이다. 계속 트레이싱 해보자. CALL 0040108A부분을 들어가면 다음과 같은 루틴이 확인된다.

EBX에 0x40124A~0x401280 까지의 값을 17로 복호화 하고 있다.

자, 지금까지의 과정을 정리해 보면 다음과 같다.

1.0x4010F5~0x401249까지의 값에 44의 XOR값으로 연산
2.0x401007~0x401086까지의 값을 7로 복호화
3.0x4010F5~0x401249 의 값을 11로 다시 복호화
4.0x4010F5~0x401249 영역의 값을 더한 값을 31EB8DB0의 값과 비교
5.0x40124A~0x401280 까지의 값을 17로 복호화
6.JMP 0040121E명령어로 OEP로 점프

이를 제일 처음에서 살펴 보았던 가상메모리상의 구조와 함께 이해하자. 그럼 다음과 같은 그림이 그려진다.

(출처: http://www.partner114.com/bbs/board.php?bo_table=B33&wr_id=91)
자 이제 분석이 끝났으니, 어떻게 패치 할까 고민해 보자. 우리는 인라인 패치 방법을 진행하려 한다. 이 방법은 파일의 빈영역에 명령어를 집어 넣고 OEP로 점프하는 부분을 우리가 입력한 패치 코드부분으로 JMP하도록 한다음, 패치를 수행한 후 원래의 OEP로 되돌려 주면 된다. 그럼 일단 빈영역을 확보해야 하는데, 우리는 text section을 이용하도록 하자. 앞에서 살펴 보았듯이 text section은 0x401280 부분에 끝이 나게된다. 그렇다면, 이 부분에 파일이 비었는지 확인을 해야하는데 이는 RVA->RWA변환을 하면 된다. 0x401280(RVA) – 0x1000(Virtual Address) + 400(PointerToRawData) = 680이다. 이부분을 헥스 에디터로 살펴 보자.

공간이 충분한 것 같다. 그럼 이 부분을 올리디버거를 이용해 어셈블리로 명령어를 입력해 파일을 저장한 후, JMP OEP부분을 이 부분으로 바꾸면 패치가 완료 된다.

다음과 같이 명령어를 입력하자.

자 이제 이 파일을 저장하자. 그 다음 OEP로 가는 부분을 찾아보자

명령어가 E9 96 01로 되어있는데 이 부분을 우리가 원하는 주소로 입력하면 된다.

이렇게 변경하면 명령어가 E9 F8 01 이렇게 된다. 이 값을 XOR 7으로 다시 암호화 해서 파일에 값을 적어 넣으면 완성이다. 401083(RVA)->483(RAW)값 이므로 이 위치의 값을 밑의 그림처럼 바꾸면 된다.

저장한 다음, 파일을 실행 시키면 다음과 같이 뜬다.

성공이다.!

'Reversing' 카테고리의 다른 글

SEH를 이용한 안티디버깅  (1) 2014.05.15
TLS 콜백 안티디버깅  (0) 2014.05.15
Upack 분석중 정리  (0) 2014.05.10
UPX압축 디버깅  (0) 2014.05.09
IAT와 EAT  (0) 2014.05.08
Posted by flack3r
|