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 개요

PEB를 이용한 안티디버깅 기법을 알아보고 우회법을 파악한다.

2 PEB

PEB(Process Environment Block)은 프로세스에 관한 정보를 담고 있는 구조체이다. 이를 WinDbg상에서 확인해 보자.(window xp sp3환경에서 테스트 했다)

여기서 안티 디버깅에 사용되는 멤버는 BeingDebugged, Ldr, ProcessHeap, NtGlobalFlag 가 있다. 이 각각의 것들을 '리버스코어'에서의 StaAD_PEB.exe예제에서 알아보고 우회방법 까지 다루겠다.

2-1 BeingDebugged

BeingDebugged 멤버를 어떻게 사용하는지 예를 보자.

FS:[18]은 TEB의 주소값이다. TEB:[30]은 PEB의 주소 값이다. PEB[2]가 바로 BeingDebugged멤버인데 이 값은 디버그 중일 때 1이된다. 그렇다면 회피방법 또한 간단하다. PEB[2]의 값을 0으로 만들어 주면 된다.

TEB가 무엇인지 설명을 빠뜨렸는데, 다음과 같은 멤버들을 가진다. 멤버들을 보면 프로그램 시작주소나 PEB(프로세스 정보) 등을 가지는데 TEB는 각 쓰레드 마다 가지는 구조체이다.

 

2-2 PEB.Ldr

이번엔 PEB.Ldr멤버가 어떻게 사용되는지 알아보자. Ldr은 프로세스에 로딩된 Dll의 로딩베이스 주소를 알아낼 때 많이 쓰이는데, 힙 영역에 존재하는 특징을 이용한 것이다. 디버깅시 사용되지 않는 힙영역의 값이 EEFEEEFE로 초기화 되는데 이 특징을 이용한 것이다.

*주의할점)
윈도우 xp이하 적용되는 내용이다. Win 7, 8 등은 안 된다.

위의 그림을 보면, NtCurrentTeb 함수를 CALL EAX로 호출하는데 이 함수는 TEB의 주소값을 리턴한다. 즉, EAX엔 TEB주소값이 들어가게 된다.

자, 위의 루틴을 보면, PEB.Ldr 값에서부터 1씩 증가해 가며 EEFEEEFE값을 가지나 확인하는 루틴이다. 그럼 우회법은 Ldr의 주소값을 참조하여 메모리값을 본 다음 EEFEEEFE라고 쓰여진 부분을 0으로 초기화 시키면 끝이다. 다음과 같이.

 

2-3 Process Heap

이번엔 Process Heap의 flag를 이용해 안티 디버깅을 수행하고 있다. 아까 EBX에 PEB의 주소값이 있었으므로, 401112주소에서 [EBX+18]은 PEB.ProcessHeap을 가리키고, ProcessHeap구조체에서 12(0xC)만큼 떨어진 곳에 flag값이 존재한다. 이 flag값은 디버그 중이 아니면 2의 값을 가지므로 이 값을 2로 하면 우회까지 완성된다.

ProcessHeap구조체는 다음과 같은 멤버들을 가진다. 환경이 xp가 아니라서 멤버들의 위치가 xp에서의 HEAP과 다르다. XP에선 Flags가 0xc에 위치하고 ForceFlags가 0x10에 위치한다.

<출처: http://gogil.kr/24>

다음 ProcessHeap의 ForceFlags값을 이용하는 방법이다. 이 값은 정상 실행중일 때, 0이 된다. 따라서 이 값을 0으로 하면 우회까지 완벽하다.

아까 EDI에 PEB.ProcessHeap값이 있었으므로 [EDI+10]은 ForceFlags의 값이 된다. 401152주소를 보면 ESI이 0인지 아닌지 확인하는 루틴이 있고, 0이면 Not debugging이 뜨도록 되어있다. 우리는 [EDI+10]의 값을 0으로 바꾸면 된다.

2-4 NtGlobalFlags

TEB.NtGlobalFlag 값은 디버깅 중일 때 0x70의 값을 가진다. 따라서 이 값을 0으로 만들어 줘버리면 우회가 가능하다.

아까 EBX에 TEB의 주소 값이 있었으므로 0x68만큼 떨어진 위치에 NtGlobalFlag가 위치하게 된다. 이 값이 0x70인지 확인하는 루틴이 40117E에 있다. 우린 이 값을 0으로 만들면 된다.

'Reversing' 카테고리의 다른 글

치트엔진을 활용한 환세취호전 핵  (2) 2014.07.28
DLL Injection  (1) 2014.05.17
WinDbg, xp 연동  (0) 2014.05.16
SEH를 이용한 안티디버깅  (1) 2014.05.15
TLS 콜백 안티디버깅  (0) 2014.05.15
Posted by flack3r
|

WinDbg, xp 연동

Reversing 2014. 5. 16. 16:13

1 개요

Windbg와 Vmware에서 XP를 연동하는 법을 알아본다.

2 vmware 세팅

1. Edit virtual machine settings를 누른다.

2 Serial Port 를 추가하고 use named pipe 의 마지막에 com_1라 적힌걸 기억하라 WinDbg에서 연결할 때 필요하다.

3 xp세팅

1. 내 컴퓨터-> 속성-> 고급-> [시작 및 복구] 설정 을 누른다

2. 편집을 눌러준다.

3. 위와 같이 제일 마지막 줄에 아래와 같이 추가해준다.
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="XP kernel debug" /fastdetect /debugport=com1 /baudrate=115200

4 windbg 세팅

1. 윈디버그 속성창에서 '대상'에
"C:\Program Files\Windows Kits\8.0\Debuggers\x86\windbg.exe" -k com:port=\\.\pipe\com_1,baud=115200,pipe,reconnect

이런 식으로 입력한다. 프로그램 위치와 버전이 다를 수 있으니 확인하고 적용한다. 핵심은 경로 + 뒤에 옵션을 주는 것이다. 여기서 주의할 점은 \\.\pipe\com_1이 부분에 com_1이라고 아까 vmware설정에서 적었던 이름 그대로 넣어주어야 한다.

2. 이제 Windbg를 실행시킨 후 xp를 실행시키면 된다. 그 후 Ctrl+Break를 누르면 디버깅 상태가 되고 F5나 g를 누르면 running상태가 된다.

'Reversing' 카테고리의 다른 글

DLL Injection  (1) 2014.05.17
PEB를 활용한 안티디버깅  (0) 2014.05.16
SEH를 이용한 안티디버깅  (1) 2014.05.15
TLS 콜백 안티디버깅  (0) 2014.05.15
인라인 패치  (0) 2014.05.11
Posted by flack3r
|

1 개요

SEH(Structured Exception Handler)는 윈도우에서 제공하는 예외처리 매커니즘이다. 이 SEH는 안티 디버깅 기법으로도 사용되는데 SEH가 무엇인지, 어떻게 안티 디버깅으로 사용되는지, 우회법은 무엇인지 등을 알아보자.

2 SEH(프로그래밍으로)

예외 처리의 과정을 알아보자. 우선 프로그램에서 예외가 발생할 경우, OS는 프로세스에게 예외처리를 맡긴다. 하지만, 프로그램이 적절한 예외처리를 하지 못할 경우 OS에서 오류처리를 한답시고 프로그램을 종료시켜 버린다. 이것이 일반적인 예외처리 메커니즘인데 디버깅을 하는 경우, 예외처리 루틴을 디버기(디버그를 수행하는 프로그램)에 맡겨버린다. 이러한 상황을 한번 보자.

다음과 같이 예외처리를 하는 프로그램을 작성하였다.

#include<Windows.h>
#include<stdio.h>
int main(void)
{
	int seh_flag = 0;
	int a = 1;
	int b = 0;
	int result = 0;
	__try{
		result = a / b;
	}

	__except(EXCEPTION_EXECUTE_HANDLER){
		seh_flag = 1;
		printf("normal processing \n");
	}

	if (seh_flag == 0)
	{
		printf("debuge detected \n");
		getchar();
	}
	getchar();
	return 0;
}

0으로 나누는 것은 EXCEPTION_INT_DIVIDE_BY_ZERO예외를 발생 시킨다. 이 것을 그냥 실행했을 때와 올리디버그상에서 실행했을 때를 보자.

<일반 실행> <디버그로 실행>

왜 이렇게 될까? 그것은 앞에서 설명 했듯이 예외 발생 시 디버기에서 예외처리를 담당하기 때문에 프로그램에서의 예외처리는 무시된다. 이는 올리디버거 상에서 확인할 수 있다.

IDIV 즉, 나누는 과정에서 break되고 과정을 살펴 보면, normal processing이라 뜨는 루틴이 생략되는 것을 알 수 있다.

그렇다면 이를 우회하는 방법은 이제 답이 나온 셈이다. 아예 예외가 발생하는 명령어 부분을 고쳐서 디버깅을 다시 하던지, 아님 올리디버거에 예외처리를 디버기(디버깅을 당하는 프로그램)에게 맡기는 옵션을 주면 정상 실행된다.

위 그림과 같이 설정하면 된다.

 

3 SEH(어셈블리로)

아깐, 디버기에서의 예외처리를 이용하여 안티디버깅을 했지만 이번엔, SEH chain에 직접 예외 핸들러를 등록해서 예외처리 루틴에서 안티디버깅을 수행한다.

먼저 SEH를 등록하는 과정을 보자.

처음 PUSH한 것이 예외를 처리하는 핸들러의 주소 값이다 FS:[0]는 TEB의 주소 값인데, NtTib.ExceptionList구조체 멤버의 주소값이기도 하다. TEB에 관한 내용은 다음에 설명하도록 하겠다. 즉 위에서 명령어가 수행되면, 전 FS:[0] (SE핸들러 멤버를 가진 구조체의 주소값 더 자세히는 EXCEPTION_REGISTRATION_RECORD 구조체의 첫 번째 멤버인데 자세한 내용은 구글을 통해 알아 보시길) 를 스택에 넣고 SEH를 등록하는 과정이다.

이후 프로그램 과정에서 다음과 같이 일부로 예외를 발생시킨다.

EAX의 주소값이 0인데 이 부분에 1이라는 값을 넣고 있다. 이제 예외가 발생했으므로 우리가 아까 등록한 예외 핸들러가 실행될 것이다.

어디서 많이 본 명령어 이지 않은가? 0x40105E~ 0x401064명령어를 보면 TEB의 30번째 멤버(PEB)에 접근해 PEB의 BeingDebugged멤버에 접근해 이 값이 1인지 아닌지 판별하는 IsDebuggerPresent() 함수의 내용과 같은 명령어를 수행한다.

여기서 ESI엔 예외가 발생하기 전 pContext값이 들어가게 된다. 예외처리 핸들러의 3번째 매개변수이다. Context엔 예외가 발생하기 전 레지스터나 세그먼트 들의 값이 저장되어 있다. Context는 각 스레드마다 내부적으로 가지고 있다. Context가 존재하는 이유는, 전에 OS kernel관련 포스팅에 게시되어 있는데 멀티스레딩 환경에서 필수적이기 때문이다.

아무튼, Context에서 B8만큼 떨어진 값에는 Eip의 값이 들어 있으므로, 이 값을 변경하면 예외 핸들러루틴이 마무리되면, 설정된 주소값으로 JMP하게 된다. 따라서, 디버깅 중이라면, 40106A로 점프하게 되는게 이 명령어를 보면 Eip를 401023으로 설정하고 있다. 이 값에 해당하는 영역으로 가보자.

예상 했듯이, 디버거가 발견되었다는 메시지박스가 출력된다.

우회방법은 위의 __try, __except방법과 같고 그 후 위의 IsDebuggerPresent() 함수의 우회법을 적용하면 된다.

'Reversing' 카테고리의 다른 글

PEB를 활용한 안티디버깅  (0) 2014.05.16
WinDbg, xp 연동  (0) 2014.05.16
TLS 콜백 안티디버깅  (0) 2014.05.15
인라인 패치  (0) 2014.05.11
Upack 분석중 정리  (0) 2014.05.10
Posted by flack3r
|