본문 바로가기

Reverse Engineering

올리디버거(OllyDBG)를 이용한 nag 제거와 윈도우 PE 구조 문제 풀이

레나(Lena)라는 제작자가 리버싱 플래시 강좌 40강 중에 3번 강좌에 있는 RegisterMe.exe와 RegisterMe.Oops.exe파일을 풀어보겠다. 강좌 파일을 다운로드 받으면 연습 문제와 강의 파일이 모두 들어 있다.

참고로 관심이 있으신 분들은 1강부터 40강까지 순서대로 모두 보는 것을 추천한다. 자료는 모두 영문이다. 조만간 풀이를 올리도록 하겠다.



문제의 설명을 보면 nag를 제거하고, 헤더 문제를 해결이라고 되있다. nag는 경고창 정도를 의미한다.

#03.tutorial 폴더의 files 폴더에 RegisterMe.exe 문제를 올리디버거로 실행해보면


nag 창이 떴다. 확인을 누르면 메인 폼이 뜬다.


종료를 하면 또 nag 창이 뜬다.


처리해야 할 부분은 실행할 때 1번, 종료할 때 1번 총 두 곳이다.

대부분 Strings를 검색해보기 마련인데, 패킹이나 암호화 프로텍터가 있거나, 함정이 숨겨져 있는 경우가 많기 때문에 올리디버거로 재시작하고, 초반부터 F8로 StepOver해 보겠다.


GetModuleHandleA를 통해서 얻어진 값을 비교한 후에 JE 구문을 만나 첫 nag 창이 뜬다.
강제로 jump를 시켜서 진행해보면, 종료할 때에 창이 또 뜨게 된다. 모든 nag 창을 강제로 jump시켜버려도 되지만, PE 구조를 이용하기 위해 EP 주소를 변경하여 해당 nag가 실행되지 않도록 해보겠다.

(윈도우 PE 구조 참고 : http://dakuo.tistory.com/entry/Windows-PE-구조)

M(Memory Map)을 클릭해서 PE 헤더 부분을 확인해보면


00400000주소부터 사이즈인 0x1000h까지가 PE 헤더이다. 해당 라인에서 더블클릭하면 DUMP창이 나타나고, DOS 헤더 구조를 볼 수 있다.


DOS 헤더를 지나 PE 구조 부분까지 내려보면 PE signature 부분을 시작으로 해서 PE 구조가 나타난다.


004000E8    00100000    DD 00001000          ;  AddressOfEntryPoint = 1000

ImageBase 값에 OEP 값을 더해서 시작하므로 00401000 주소에서 코드가 실행된다.

시작되는 지점을 수정해서 첫 번째 nag 창을 제거할 것이므로 Memory Map 창에서 PE 덤프를 하여 나타난 OEP 주소지(004000E8)로 Hex dump 창에서 이동(Ctrl+G)한다.


덤프된 hex 값 00 10 00 00 을 확인하고 24 10 00 00 으로 수정한다. 수정할 곳을 블록잡고, 우클릭을 하여 Binary -> Edit를 선택하여 수정하고 저장하자.
Hex dump에서 24 10 00 00으로 수정하면 리틀엔디안에 의해서 00 00 10 24로 처리된다.

004000E8    24100000    DD 00001024          ;  AddressOfEntryPoint = 1024


저장한 파일을 실행해보면 첫 번째 nag는 해결되었다.



종료시에 나타나는 nag 창은 프로그램을 종료할 때 나타나는 것으로 Messagebox 부분을 Nop(No Operation) 처리하면 된다. 종료할 때에 나타나는 nag 창은 어떻게 찾는 것이 좋을까?
1. nag 창에 나타나는 문자열을 추출하여 검색.
2. Back To User 모드 기능 사용
3. Commandline or Commandbar 플러그인 사용 bpx MessageboxA로 검색.

각각 이미 서술한 방법이니 3가지 방법중에 마음에 드는 것으로 골라 해당 코드 부분을 찾자.


PUSH 0부터 Call MessageBoxA까지 블록 선택하고 Binary -> Fill with NOPs를 선택한다. 수정후 저장한다. 실행해보면 nag 창이 하나도 안뜨며 문제 풀이가 끝났음을 알 수 있다.



이번에는 RegisterMe.Oops.exe파일을 풀기 위해 올리디버거로 열어보자. 그러면 화면과 같은 잘못된 실행 포맷이라는 에러 문구가 나타난다.

확인을 누르면 이상한 주소지가 선택되어 디버거가 실행될 것이다. 이문제는 기존 문제에서 PE 구조만 꼬아놓은 경우로, 수작업으로 수정하거나 자동으로 PE 구조를 보정해주는 플러그인을 이용하는 방법을 소개할 것이다.

먼저 PE 구조를 살펴보고, 어떤 문제가 있는지 확인해보자.
M(MemoryMap)을 선택한 후 PE header 부분을 더블클릭하여 Dump 창을 연다.


일반적인 PE Header의 길이는 1000인데, 5000으로 되어 있는 것을 체크하고 더블클릭하여 덤프된 창에서 내려가면서 PE 구조를 확인한다.


AddressOfEntryPoint = 1000, ImageBase = 400000. EP(시작되는 부분)는 00400000 + 1000 = 00401000이다. 직접 CPU 창에서 00401000 주소지로 이동(Ctrl+G)하고, BreakPoint(F2)를 걸면 올리디버거가 혼란스러워 하며, 다음과 같은 경고를 낸다.


~~~~~~~~~~~~~~

'예(Y)' 버튼을 눌러 Breakpoint(F2)를 설정하고, Run(F9)을 하면 00401000에서 정지된다.

PE 구조가 잘못되었더라도 시작 지점까지 로드가 되었기 때문에 M(Memory Map)을 열어서 다시 PE 구조를 확인해보면 아까와는 다르게 나타난다.


PE 사이즈는 5000이고 text 섹션은 없어져 있는 상태이다. PE 구조를 DUMP에서 보면 더 확실하게 우리가 알고있는 일반적인 PE 구조와 어떻게 다른지 알 수 있다.


이상한 부분과 수정해야 할 값을 정리하면 다음과 같이
NumberOfRvaAndSize를 제외하고 사이즈 값을 크게 늘려놓은 것을 복원하는것 뿐이다.

004000DC    00040040    DD 40000400          ;  SizeOfCode = 40000400 (1073742848.)
: 40000400 -> 400

004000E0    000A0040    DD 40000A00          ;  SizeOfInitializedData = 40000A00 (1073744384.)
: 40000A00 -> A00

004000EC    00100040    DD 40001000          ;  BaseOfCode = 40001000
: 40001000 -> 1000

004000F0    00200040    DD 40002000          ;  BaseOfData = 40002000
: 40002000 -> 2000

00400134    04000040    DD 40000004          ;  NumberOfRvaAndSizes = 40000004 (1073741828.)
: 40000004 -> 10 (이 값은 옵셔널 헤더의 디텍터리 엔트리 개수로 일반적으로 10이며, 이 값을 변경함으로써 올리디버거가 오작동하게 만들 수 있다고 알려져 있다.)

00400138    00005000    DD 00500000          ;  Export Table address = 500000
: 500000 -> 0

0040013C    00000500    DD 00050000          ;  Export Table size = 50000 (327680.)
: 500000 -> 0

이문제는 문제 제작자가 사이즈 값들이 400이면 40000을 앞에 붙여 PE 구조를 바꾸어놓거나 특별한 값으로 변경하여 올리더버거가 잘못 작동하도록 해둔 것이다.
수정을 할 때에는 NumberOfRvaAndSzies 값의 경우 hex dump 창에서 00400134 주소로 이동(Ctrl_+G)하여 , 기존의 값인 40000004를 10으로 변경하면 된다. 리틀엔디안 값으로 표시되어 04 00 00 40으로 나타나 있으니 거꾸로 뒤집어서 10 00 00 00 으로 수정해서 정상적인 값으로 복원시키면 된다. 나열한 항목들을 모두 수정한 후에 바이너리를 저장하고 올리디버거로 다시 열어 PE 구조를 확인하면 text 색션도 나타나며, 기존의 nag 창이 뜨는 문제와 동일하게 나타나게 된다.

참고로 Hex Dump에서 Binary -> Edit 기능을 사용할 때는 PE 구조 부분을 한꺼번에 블록을 씌워서 수정을 하도록 하고, 아니면 헥스에디터를 이용하여 수정하는 것이 더 편할 수도 있다.



Tip : 올리디버거의 플러그 인 중 Olly_Advanced_v1.27.rar을 소개한다. 이것은 설치하여 옵션을 조절하는 것만으로 자동으로 fake된 ExportTable을 수정해주거나 Copy to Exe 메뉴에서 에러나는 버그를 수정해주고, 그 외에도 anti debugging을 우회할 수 있는 기능 등을 사용할 수 있다.


다운받아서 advancedolly.dll 파일만 올리디버거의 plugin 폴더에 넣어주면 된다.
다음은 Olly Advanced 1.27의 옵션창이다.


Bugfixes 탭에는 올리디버거의 버그를 고치는 옵션들이 있다.

Additonal Options 탭에는 여러 기능들이 있는데 잘 생각해서 체크하기 바란다. 나중에 플러그인을 많이 설치하다 보면 플러그인들끼리 기능상 충돌이 생기게 된다 따라서 필요할때만 켜놓는것이 좋다.

Anti-Debug 탭에는 디버그하는 것을 막는 루틴들이 여러 가지 있는데 그런 부분들을 우회할 수 있도록 해준다.


마지막에 풀었던 PE 헤더를 꼬아놓은 문제는 이 플러그 인을 설치한 후에 열면 모두 정확한 값으로 수정되어 열리기 때문에 풀이에서처럼 수작업을 해줄 필요가 없었다.