본문 바로가기
Reversing/리버싱 핵심 원리

[리버싱 핵심 원리] 19장, UPack 디버깅 - OEP 찾기

by Y06 2020. 11. 19.

19장, UPack 디버깅 - OEP 찾기

19.1. OllyDbg 실행 에러

UPack으로 압축된 메모장(notepad_upack.exe) 파일을 OllyDbg로 열어보면 에러 메시지가 보인다. UPack은 IMAGE_OPTIONAL_HEADER에서 NumberOfRvaAndSizes 값을 A로 변경(기본 값 10)하기 때문에 OllyDbg의 초기 검증 과정에서 에러 메시지가 출력되는 것이다.

위 에러 때문에 OllyDbg는 EP로 가지 못하고, 에러 메세지와 같이 ntdll.dll 영역에서 멈춰버린다.

 

OllyDbg의 버그(혹은 엄격한 PE 체크) 때문에 이런 현상이 발생한 것이므로 강제로 EP를 설정해줘야 한다. 그럼 먼저 PE가 어디인지 알아야 하기 때문에 Stud_EP를 이용한다.

Imagebase가 00400000이고 EP의 RVA 값이 1018이다. 따라서 EP의 VA 값은 00401018이다. OllyDbg의 Code 창에서 00401018로 이동한 후 'New origin here' 명령을 이용하여 강제로 EIP를 변경한다.

 

19.2. 디코딩 루프

모든 패커에는 디코딩 루프(Decoding Loop)가 존재한다. 압축/해제 알고리즘 자체가 ㅁ낳은 조건 분기와 루프로 구성되어 있다는 걸 알고 있다면 디코딩 루프가 왜 그리 복잡해 보이는지 이해할 수 있다. 이러한 디코딩 루프를 디버깅 할 때는 조건 분기를 적절히 건너 뛰어가며 루프를 탈출해야 한다. 경우에 따라서는 한 눈에 루프가 보이지 않을 수도 있다. 레지스터의 변화를 잘 포착하는 것이 중요하다.

 

UPack은 두 번째 섹션에 원본 데이터가 존재한다고 했다. 이 데이터를 디코딩 루프를 돌리면서 첫 번째 섹션에 압축 해제 한다.

 

처음 두 라인은 010011B0를 EAX에 저장하는 명령이다. LODS DWORD PTR [ESI] 명령은 ESI가 가리키고 있는 주소에서 4바이트 값을 읽어 EAX에 저장하라는 의미이다. EAX는 010739D 값을 가지는데 이 값은 원본 notepad의 OEP이다. 원래는 이 값이 OEP인 걸 알았으니 바로 하드웨어 BP를 설치하고 실행하면 정확히 OEP에서 멈춘다.

F8로 진행하다 보면 함수를 하나 호출하는데, 이 함수가 디코딩 함수이다.

0101FE57과 0101FE5D 에 있는 명령어는 EDI가 가리키는 위치에 값을 쓰는 명령(MOVS, STOS)가 있다. 이 떄, EDI 값은 01001334로 첫 번째 섹션 내의 주소를 가리키고 있다. 즉, 압축이 해제된 후의 명령어를 다루고 있다.

0101FE5E와 0101FE61에서는 CMP/JB 명령어로 EDI 값이 01014B5A가 될 때 까지 루프를 돌리고 있다.

(ESI+34=01014B5A)

0101FE16이 디코딩루프의 끝 부분이다.

 

19.2. IAT 세팅

일반적인 패커에서는 디코딩 루프가 끝나면 우너본 파일에 맞게 IAT를 새롭게 구성한다. UPack이 임포트 하는 2개의 함수 LoadLibraryA와 GetProcAddress를 이용하여 루프를 돌면서 원본 notepad의 IAT를 구성한다. notepad에서 임포트 하는 함수들의 실제 메모리 주소를 얻어서 원본 IAT 영역에 쓰는 것이다. 이 과정이 끝나면 0101FEAF 주소의 RETN 명령어에 의해서 드디어 OEP로 간다.