본문 바로가기
리버싱(Reversing)/리버싱 개념

리버싱 핵심원리 15장(UPX 실행 압축된 notepad 디버깅)

by LIZ0904 2020. 11. 7.
반응형

15장에서는 UPX 실행 압축된 notepad_upx.exe를 디버깅하여 실행압축에 대한 개념을 이해하는 것이 목표이다. 즉, 코드를 트레이싱하면서 원본 notepad.exe 코드를 찾아내는 것이라고 할 수 있다.

 

1. 코드 트레이싱 명령

첫 디버거 화면

Notepad_upx.exe를 디버거로 열어보면 위와 같이 UPX EP 코드가 나타난다. EP 주소는 01015330이며, 실제로 압축된 notepad 원본 코드는 EP주소(01015330) 위쪽에 존재한다.

 

UPX 파일 트레이싱을 해볼 것인데, 이때 루프(Loop)를 만나면 그 역할을 살펴본 후 탈출한다라는 방대한 코드에 대한 원칙이 있다고 한다. 압축 해제 과정은 무수히 많은 루프의 연속임으로, 적절히 루프를 탈출할 줄 알아야 한다. 방대한 코드를 트레이싱 할 때는 일반적인 Step Into(F7)을 사용하지 않고, OllyDbg에서 별도로 제공되는 명령을 사용한다.

 

Animate Into(Ctrl+F7) : Step Into 명령 반복 (화면 표시 O)

Animate Over(Ctrl+F8): Step Over 명령 반복 (화면 표시 O)

Trace Into(Ctrl+F11): Step Into 명령 반복 (화면 표시 X)

Trace Over(Ctrl+F12): Step Over 명령 반복 (화면 표시 X)

 

애니메이트 명령어와 트레이스 명령어로 나뉘는데, 애니메이트 명령어는 트레이싱 과정이 화면이 표시되기 때문에 속도가 느리다는 점이 있다. 트레이스 명령어는 미리 설정한 트레이스 조건에서 자동으로 멈출 수 있고, 로그를 남길 수도 있다는 장점이 있다. 이번 UPX 파일 트레이싱에서는 Animate Over(Ctrl+F8)을 사용할 것이다.

 

 

 

 

 

EP 코드에서 Animate Over(Ctrl+F8)을 누르면 트레이싱이 시작되면서, 커서가 계속 루프를 돌 것 이다. 조금 진행하다 보면 짧은 루프가 나타나는데, Step Into(F7)을 눌러 트레이스를 멈추고 해당 루프를 살펴보자.

 

 

 

2-1. 첫번째 루프문

첫번째 루프문

위에 보이는 사진의 범위를 계속해서 반복한다. 루프의 내용을 보면, EDX(01001000)에서 한 바이트를 읽어 EDI에 쓰는 것이다. EDI가 가리키는 01001000의 주소는 첫 번째 섹션(UPX0)의 시작 주소이며, 메모리에서만 존재하는 섹션이다.

 

 

레지스터 영역

처음 루프문을 만났을 때의 레지스터 영역을 확인해보면 ECX0000036B, 루프문이 0x36B만큼 반복된다는 걸 알 수 있고, EDX의 값도 01001000임을 알 수 있다.

 

반복문 빠져 나오기

이러한 루프를 빠져 나오기 위해서 반복문의 마지막줄 아래에 Break Point(F2)를 설정해주고, 실행명령(F9)를 이용해 탈출한다.

 

 

 

2-2. 두번째 루프문

두번째 루프문

두번째 루프문은 이전보다 꽤 길다.두번째 루프가 본격적인 디코딩 루프, 또는 압축해제 루프라고 할 수 있다. ESI가 가리키는 두번째 섹션의 주소에서 차례대로 값을 읽어서 적절한 연산을 거쳐 압축을 해제하여, EDI가 가리키는 첫번째 섹션의 주소에 값을 써주는 형식으로 돌아가고 있다. 위에서 AL(EAX)에는 압축 해제된 데이터가 있고, EDI는 첫번째 섹션의 주소를 가리키고 있다.

 

루프문 탈출

이 루프문의 끝은 010153FD, 01015402BP를 걸어두고 F9를 하면 이 루프를 나올 수 있다.

 

실행 전 덤프영역

이 루프문을 실행하기 전에는 첫번째 섹션영역인 01007000 위치는 모두 NULL 값으로 채워져 있다.

 

실행 후 덤프 영역

하지만 루프문을 나온 뒤 덤프창을 확인해보면 첫번째 섹션영역인 01007000 위치에 압축 해제된 코드가 쓰여진 걸 확인할 수 있다.

 

 

 

2-2. 세번째 루프문

세번째 루프문

또다시 Ctrl+F8을 사용해 트레이싱을 시작하면 위와 같은 세번째 루프를 만날 수 있다. 이 루프는 원본 코드의 CALL/JMP 명령어의 destination 주소를 복원시켜주는 코드이다. 0105436주소에 BP를 걸어주고 탈출하면 된다.

 

 

 

 

2-4. 네번째 루프문

네번째 루프문

더 내려가다 보면 위와 같은 네번째 루프가 나타난다. 이 부분이 바로 IAT를 세팅하는 루프이다. 일반적인 실행 압축 파일은 원본 파일의 코드, 데이터 ,리소스의 압축 해제 과정이 끝나면 IAT를 세팅하고 OEP로 간다. 01015436 주소에서 EDI01014000으로 세팅되고, 이곳이 두번째 섹션영역이다.

 

 

01014000 주소의 내용

01014000 주소엔 원본 notepad.exe.에서 사용되는 API이름 문자열이 저장되어 있다. 이 문자열들은 UPX가 원본 notepad.exe를 실행압축 시킬 때 원본 파일의 IAT를 분석하여 프로그램에 사용되는 API 이름 목록을 뽑아 놓은 것이다. 이제 원본 notepad.exe의 압축을 모두 해제하였기 때문에 OEP로 제어를 돌려줘야 한다.

 

 

OEP로 가는 법

010154AD 주소의 POPAD 명령은 UPX 코드 중 가장 첫 번째 명령인 PUSHAD에 대응되는 명령으로, 레지스터를 원래대로 복원시키는 명령어이다. 최종적으로 010154BB 주소의 JMP 명령어에 의해서 OEP로 가게 된다. JMP하는 주소 0100739D는 원본 notepad.exeEP주소이다.

 

 

3. UPXOEP를 빨리 찾는 방법

1. POPAD 명령어 이후의 JMP 명령어에 BP 설치

UPX 패커의 특징 중 하나는 EP 코드가 PUSHAD/POPAD 명령어로 둘러싸여 있다는 것이다. 여기서 PUSHAD8개의 범용 레지스터의 값을 스택에 저장하는 명령어이고, POPADPUSHAD 명령에 의해서 스택에 저자된 값을 다시 각 레지스터들에게 입력하는 명령어이다. OEP코드로 가는 JMP 명령어가 POPAD 명령어 바로 이후에 나타나기에, JMP명령어에 BP를 설치하고 실행하면 바로 OEP로 갈 수 있다.


2.
스택에 하드웨어 브레이크포인트 설치

이 방법도 PUSHAD/POPAD의 특성을 이용하는 것이다. 하드웨어 BPCPU에서 지원하는 브레이크 포인터로, 4개까지 설치 가능하며, 일반적인 BP와는 다르게 BP 설치된 명령어가 실행된 이후에 제어가 멈추게 된다.

반응형

댓글