본문 바로가기
Study/Reversing

[Reversing] UPX packing & unpacking

by Jamie Lim 2020. 10. 26.

이번 실습의 내용은 32bit notepadUPX로 패킹하고 이를 디버거를 통해 패킹을 푸는 것이다. 이 실습에서 사용할 패커는 제목에서 알 수 있듯 UPX이다. 

 

우선 UPX를 패킹하기 위해서는 아래 사이트에서 UPX를 다운받아야 한다.

https://github.com/upx/upx/releases/tag/v3.96

 

Release UPX 3.96 · upx/upx

Please see the file NEWS for a detailed list of changes. Note: all versions are functionally equivalent, i.e. each version can handle all executable formats, so you only need the file that runs on ...

github.com

* 현재 필자는 win 32bit를 다운받았다.

 

 

다운을 받으면 UPX와 함께 실습에 사용할 notepad.exe(32bit)를 아래와 같이 같은 파일에 둔다.

 

 

그리고 해당 폴더에서 cmd를 실행시켜 UPX를 다음과 같이 실행시켜 notepad.exeUPX로 패킹한다.

 

< UPX 사용법 >

 

UPX 사용법

 

 

< notepad.exe UPX로 패킹 >

 

 

 

그럼 다음과 같이 notepad_upx.exe 파일이 생성된다.

 

 

 

그리고 사이즈를 확인하면 155,136에서 79,360으로 줄어든 것을 볼 수 있다.

 



notepad.exenotepad_upx.exe의 차이는 다음과 같다.

1. PE header의 크기는 동일하다.
2. “.text” 파일은 “.UPX0”으로 “.data” 파일은 “.UPX1”로 바뀌게 된다.
3. 첫 섹션의 RawDataSize = 0이다.
4. EP는 두 번째 섹션에 위치한다. (원본인 notepad는 첫 섹션에 위치한다.)
5. .rsrc(리소스 섹션)은 거의 변하지 않는다.

 

notepad.exe와 notepad_upx.exe 파일을 PE파일 관점에서 비교하면 다음과 같습니다.

 

notpad.exe와 nopad_upx.exe 비교

 

다음과 같이 UPX로 패킹한 notepad의 첫 섹션의 raw data의 사이즈는 0인 것을 확인할 수 있고 virtual size는 원본 파일과 동일하다. 이 의미는 UPX로 실행 압축된 파일은 실행되는 순간 압축된 코드를 첫 섹션에서 푼다는 것이다. , 압축해제 코드와 압축된 원본 코드는 두 번째 섹션에 존재한다는 뜻이다. 그래서 파일이 실행되면 압축 해제 코드가 실행되어 원본 코드를 첫 번째 섹션에 해제시킨다. 그리고 이 압축해제가 끝나면 원본 EP 코드를 실행한다.

 

notpad_upx.exe의 IMAGE_SECTION_HEADER

 

 

UPX로 압축된 notepad 디버깅

< notepad.exeEP 코드 >

010073B2 주소에서 GerModuleHandleA() API를 호출해서 notepad.exe 프로세스의 ImageBase를 구한다. 그리고 010073B4 010073C0 주소에서 각각 MZ PE 시그니처를 비교한다.

 

notepad.exe EP Code

 

< notepad_upx.exe EP 코드 >

EP 주소 0101C950은 두 번째 섹션의 끝부분이다. 실제로 압축된 notepad 원본 코드는 EP 주소 위쪽으로 존재한다. Pushad 명령은 EAX ~ EDI 레지스터 값을 스택에 저장하고, ESI EDI 레지스터를 각각 두 번째 섹션 시작 주소(01011000)와 첫 번째 섹션 시작 주소(01001000)로 세팅한다. 이로 우리는 UPX로 패킹된 파일은 압축된 코드를 압축 해제하는 코드부터 시작된다는 것을 알 수 있다.

 

   

 

 

첫 번째 섹션의 RVA = 1000000 + 10000 = 1010000

→ EDI에 저장

 

 

 

 

두 번째 섹션의 RVA = 1000000 + 11000 = 1011000 

→ ESI에 저장

 

 

 

UPX 파일에서 첫 번째 섹션은 메모리에서만 존재하고 이 곳에 압축이 해제된 원본 파일의 코드가 저장될 것이다. 디버깅할 때 이처럼 ESI EDI가 동시에 설정되면 ESI가 가리키는 버퍼에서 EDI가 가리키는 버퍼로 메모리 복사가 일어날 것이라 예측할 수 있다. 이 경우 ESI로부터 데이터를 일어 압축을 해제한 후 EDI에 저장시킨다.

 

ESI가 가리키고 있는 두 번째 섹션 덤프

 

 

EDI가 가리키고 있는 첫 번째 섹션 덤프

 

 

 

UPX 파일 트레이싱

루프 #1

EP 코드에서 Animate Over [Ctrl+F8] 명령을 내려 트레이싱을 시작한다.

* 트레이싱을 멈추고 싶다면 Step Into[F7] 명령을 내리면 된다.

 

해당 루프는 EDX(01001000)에서 한 바이트를 읽어 EDI(01001001)에 쓰는 것이다. EDX 레지스터가 가리키는 01001000 주소는 첫 섹션의 시작 주소이고 메모리에서만 존재하는 섹션이다. 010153E6break Point를 걸고 실행명령(F9)으로 해당 루프를 탈출한다.

 

 

 

루프 #2

해당 루프는 디코딩 루프로 압축을 해제해주는 루프다. ESI가 가리키는 두 번째 섹션의 주소에서 차례대로 값을 읽어 적절한 연산을 거쳐 압축을 해제해 EDI가 가리키는 첫 번째 섹션의 주소 값을 써준다.

 

 

 

위 루프에서 사용되는 명령어는 아래와 같다. 여기서 AL(EAX)에는 압축 해제된 데이터가 EDI에는 첫 번째 섹션의 주소를 가리키고 있다.

 

0101C99E    8A06              mov al,byte ptr ds:[esi] 
0101C9A0    46                 inc esi                         

...

0101C9F8    8807               mov byte ptr ds:[edi],al 
0101C9FA    47                  inc edi                      

...

0101CA09    8907               mov dword ptr ds:[edi],eax     
0101CA0B    83C7 04           add edi,4

 

이 루프를 탈출하기 dln해서는 0101CA1A 주소에 BP를 걸어 실행하면 된다. 루프를 제대로 탈출했다면 덤프 창에 나타나있는 것처럼 첫 번째 섹션 영역에 압축해제 된 코드가 쓰여진 것을 확인할 수 있다.

 

 

 

루프 #3

해당 루프는 원본 코드의 CALL/JMP 명령어의 목적지 주소를 복원시켜주는 코드다. 이 루프 역시 루프 바로 아래 명령에 bp를 걸고 F9를 눌러 탈출할 수 있다.

 

 

 

루프 #4

해당 루프는 IAR를 세팅하는 부분이다. 0101CA4E 주소에서 EDI 1A000+ 1000(esi) = 1B000으로 설정되고 이 곳은 두 번째 섹션 영역이다.

 

 

 

원본 notepad.exe에서 사용되는 API 이름 문자열이 저장되어있다. 이 문자열들은 UPX가 원본 notepad.exe 실행 압축을 시킬 때 원본 파일의 IAT를 분석해 프로그램에 사용되는 API 이름 목록을 뽑아 놓은 것이다

 

 

위에서 API 이름 문자열들로 GetProcAddress()를 호출하여 API 시작 주소를 얻어 EBX 레지스터가 가리키는 원본 notpad.exe의 IAT 영역에 API 주소를 입력하면 된다. 이를 API 이름 문자열이 끝날 때까지 반복하면 notpad.exe IAT 복원 과정이 마무리된다.

 

 

OEP로 이동 #3

notepad의 압축을 모두 해제 했으니 OEP로 제어를 돌려줘야 한다. 아래는 OEP로 점프하는 코드다.

 

 

위 코드에서 0101CAC5 주소의 POPAD 명령은 UPX 코드 중 가장 첫 번쨰 명령어인 PUSHAD에 대응되는 명령으로 레지스터를 원래대로 복원시켜준다. 그럼 jmp 부분에서 f7을 통해 step into를 하면 아래와 같은 코드로 이동한다. 이동한 주소 100739D가 바로 원본 notepad.exe의 EP 주소다.

 

 

 

< 참고 자료 > 
리버싱 핵심원리 - 이승원 저

댓글