문서 작성일 : 2008년 12월 19일
최종 수정일 : 2008년 12월 19일
Hong10님께서 작성하신 “Anti Reversing Code” 큰 주제를 바탕으로 4개로 나눠 작성하였습니다.
Anti-Reverse
개인적으로 많은 리버서들을 짜증나게 하는 것 이 이 안티리버싱 기법이라고 생각합니다. 언팩을 하든 프로그램을 분석하든 이 안티리버싱 코드가 있으면 어떻게든 리버서들을 방해하고 혼란을 가중 시키기 위하여 여러가지 방법을 동원하여 괴롭힙니다. 물론 방어자 입장에서는 자신의 코드가 쉽게 분석 당하지 않기 위하여 더없이 고마운 기법이긴 하지만 말입니다.
1.1 IsDebugerPresent()
대부분의 기초적인 디버거 탐지 기법에는 PEB의 BeingDebugged 값을 체크를 하는 기법을 가지고 있습니다. PEB(Process Environment Block)의 위치는 TEB(Thread Environment Block)에서 0x30 만큼 떨어진 곳에 존재 합니다.
IsDebugerPresent는 유저모드의 디버거가 프로세서를 디버깅하고 있는지 flag 값을 체크 하여 확인합니다. 여기서 간단히 PEB과 TEB에 대해서 알아 보겠습니다. PEB은 유저레벨 프로세서의 대한 추가적인 정보를 가지고 있는 구조체이고 TEB은 쓰레드에 대한 정보를 가지고 있다고 말할 수 있습니다
이 구조체를 어떻게 구동되며 핸들링 하는지는 애기가 길어 지므로 생략합니다. 여기서는 PEB의 구조체 값중 BeingDebugged값을 체크하여 디버깅 유무를 판별 한다고 생각 하시면 될꺼 같습니다. 그 외 에도 PEB 구조체 값을 이용하여 판별 할수 있습니다. 그건 추후에 나오는 기법에 대하여 언급 하겠습니다. 아래의 코드를 바탕으로 기본적이 MASM 문법과 IsDebugerPresent 의 기능을 살펴 보겠습니다.
IsDebugerPresent 소스를 EDIT-PLUS stx에 적용한 코드입니다.
.386 .model flat, stdcall option casemap :none ; case sensitive include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib .data DbgNotFoundTitle db “Debugger status:”,0h DbgFoundTitle db “Debugger status:”,0h DbgNotFoundText db “Debugger not found!”,0h DbgFoundText db “Debugger found!”,0h .code start: CALL IsDebuggerPresent CMP EAX,1 JE @DebuggerDetected PUSH 40h PUSH offset DbgNotFoundTitle PUSH offset DbgNotFoundText PUSH 0 CALL MessageBox JMP @exit @DebuggerDetected: PUSH 30h PUSH offset DbgFoundTitle PUSH offset DbgFoundText PUSH 0 CALL MessageBox @exit: PUSH 0 CALL ExitProcess end start |
.386 은 어떠한 인스트럭션 를 가질 것인까에 대한 정의 정도가 되겠습니다 위와 같이 .386이 되어 있다면 386의 인스트럭션을 가질 것이며 .486 .586 등이 존재 합니다 이와 같은 정의는 각각의 사양에 따른 아키텍쳐가 조금씩 차이가 나기 때문입니다.
(가령 386에서는 32비트 레지스터와 32비트 주소 버스 및 외부 데이터 버스의 특징을 가지고 있으며 펜티엄 계열 에서는 실행 속도를 향상시킨 새로운 마이크로 구조 설계를 기반 하는 차이 입니다 이에 대한 설명은 대부분의 어셈블리어 책에 초반부에 설명이 되어 있습니다)
다음은 .model 지시자은 메모리 모델에 해당하는 지시자 입니다. 윈도우는 항상 flat 모델을 쓰고 있으므로 flat이라 지정해주며 뒤에 stdll은 콜링컨베션중 스탠다드 콜에 해당하는 정의 입니다. Flat의 간단한 정의는 no segment, 32bit address,protected mode only 라고 정의 되어 있습니다. Option에 대해서는 잘 모르겠군요. 다음으로는 include입니다 이건 조금이라도 프로그래밍을 하신분들이 라면 아실꺼라 생각하고 생략합니다.
.data 지시자는 데이터 세그먼트를 지정하는 지시자 입니다. DB(Define Byte) 라고 해서 원바이트 형으로 데이터를
아래는 PEB 구조체 입니다.
여기서는 0x030 오프셋 만큼의 위치에 PEB의 포인터가 하며 PEB의 0x002 오프셋 위치에 BeingDebugged 가 존재합니다. EDIT-PLUS 에서 설정한 컴파일 환경을 이용하여 위의 코드를 컴파일 하여 OLLY로 좀더 디테일 하게 알아 보겠습니다.
아래는 OLLY 로 열어본 IsDebugerPresent 입니다.
위의 코드에서 IsDebugerPresent()가 호출된뒤에 리턴값이 1이라면 디버거를 찾았다는 메시지를 띄워 준다는 걸 알 수 있습니다. 좀더 자세히 콜문의 어셈루틴을 알아 보겠습니다.
아래는 IsDebugerPresent call 세부 루틴 입니다.
위의 달랑 세줄에서 위에 설명한 것들에 대한 것을 실행합니다. 일반적으로 FS 세그먼트 영역은 데이터 세그먼트 일종이다. FS:[18]은 TEB의 위치를 가르키며 그 주소값을 EAX에 담고 Eax+0x30 은 PEB의 위치를 다시금 EAX 에 담고 다시 EAX+0X2 값 BeingDebugged 값을 담아서 리턴 하고 있다. Livekd를 이용하여 TEB의 주소와 올리에서 뿌려주는 주소값이 일치 함을 알수있다.
1.2 IsDebugerPresent 우회
이를 우회 하는 방법에는 여러 가지 방법이 존재합니다 우선 해당 플래그 값을 수정 하면 됩니다. 하지만 올리에서 해당 안티 디버깅 에 대한 플러그인 이 존재 합니다. 해당 플러그인은 다음 사이트에서 다운로드 받을수 있습니다.
http://www.openrce.org/downloads/details/111/IsDebuggerPresent
올리의 플러그인 폴더에 압축을 풀면 다음과 같은 플러그가 생기는 걸 확인 할 수 있습니다.
위 그림에서 Hide는 IsDebugPresent를 우회 한다는 말이고 Restore은 다시금 복원 한다는 의미 입니다. 각자 실행하여 정말로 돌아가는지 확인 해보시길 바랍니다.
[계속…]
참고사이트 및 문서
EDIT PLUS 를 이용한 MASM 환경 구축
http://mysilpir.net/entry/EditPlus-Assembly-%EC%84%A4%EC%A0%95-MASM
ANTI REVERSE
http://zesrever.xstone.org/
http://slaxcore.tistory.com
http://beist.org/research/public/artofunpacking/artofunpacking.pdf
http://openrce.org
정덕영님의 윈도우 구조와 원리
THX to zersrever,slaxcore,ashine,ap0x,정덕영FROM Hong10