I. 개요

II. 본론

A. 윈도우

  1. CPU 윈도우

  2. Log

  3. Executable modules 윈도우

  4. Memory map

  5. List of Windows

  6. Threads

  7. Handles

  8. Watches

  9. Search Results

  10. Run trace

  11. Patches

  12. INT3 breakpoints

  13. Memory breakpoints

  14. Hardware breakpoints

  15. VEH/SEH chain

  16. Call stack

  17. Source files

B. 메뉴

  1. File

  2. View

  3. Debug

  4. Trace

  5. Plugins

  6. Options

  7. Windows

  8. Help

C. 우클릭

  1. 디스어셈블러 패널에서 우클릭

  2. 레지스터 패널에서 우클릭

  3. 스택 패널에서 우클릭

  4. 덤프 패널에서 우클릭

D. 옵션

  1. Code

    1.1 Mnemonics

    1.2 Operands

    1.3 Dump

    1.4 Strings

  2. Debugging

    2.1 Debugging data

    2.2 Start

    2.3 Events

    2.4 Exceptions

    2.5 Run trace

    2.6 Hit trace

    2.7 SFX

    2.8 Just-in-time

  3. Analysis

    3.1 Advanced

    3.2 Invalid commands

  4. Search

  5. CPU

    5.1 More CPU

  6. Directories

  7. Errors and warnings

  8. Appearance

    8.1 Defaults

    8.2 Startup

    8.3 Fonts

    8.4 Colours

    8.5 Code highlighting

    8.6 Text-to-speech

  9. Miscellaneous

III. 결론

IV. 참고문헌




I. 개요

  올리디버거에는 디버깅을 하는데 많은 도움이 되는 여러가지 기능들이 있지만 실질적으로 알고 사용하는 기능은 몇 개 안된다는 생각에 이렇게 정리를 하게 되었습니다. 이 문서의 목적은 올리디버거 사용법이 아니라 기본적인 사용법을 아는 사람들에게 여러 가지 기능들을 소개하는 것입니다. 아직 이걸 쓰고 있는 본인도 이렇게 정리하면서 처음 알게 된 것이 대부분이므로 이 문서의 내용은 많이 부족한게 사실이며 주기적으로 업데이트를 할 것입니다. 오타나 추가하고 싶은 내용은 메일이나 블로그의 댓글에 달아주시면 감사히 수정하겠습니다.


  참고로 OllyDbg 2.01은 시작 시 초기 루틴에서 SeDebugPrivilege를 Enable하려고 시도한다. 그래서 윈도우 비스타 이후 부터는 관리자 권한으로 실행시키지 않으면 권한이 없으므로 제한된 기능만 사용 가능하다는 메시지 박스가 나온다. 윈도우 XP에서도 현재 계정이 Administrators Group 등에 속해있지 않는 이상 해당 메시지 박스를 볼 수 있다. 분석 시에 조심해야 할 것이 디버기가 자식 프로세스로 실행되는데 올리디버거의 권한 즉 SeDebugPrivilege를 상속하기 때문에 디버기 분석 시 권한과 관련해서는 이것을 생각하고 진행해야 한다.





II. 본론


A. 윈도우

1. CPU 윈도우

  올리디버거의 기본 윈도우(CPU 윈도우)는 크게 5개의 패널로 나뉜다.


1.1 디스어셈블러 패널

  Address, Hex dump, Command, Comments를 보여준다. Comments 부분의 경우 API들의 파라미터까지 보여주므로 쉬운 디버깅 환경을 제공해 준다.


1.2 인포 패널

  디스어셈블러 패널 아래에 존재하는 작은 패널로서 선택된 명령어에 대한 추가적인 정보를 보여준다. 예를들면 어셈블리어로 RETN 명령어를 실행할 차례라면 이 공간에는 Return to “Address” 같이 어디로 리턴할지 보기 쉽게 해준다. 특히 MOV 명령어의 경우에는 출발지와 목적지 주소를 가르쳐주기도 하고 계산도 직접해서 보여주므로 도움이 많이 되는 부분이다. 또한 소스 코드 존재 시에는 소스 코드를 같이 보여주기도 한다.


1.3 덤프 패널

  주소와 거기에 따른 Hex dump를 볼 수 있다. 그리고 3번째 부분에서는 이 Raw Data를 ASCII, UNICODE 또는 Multibyte (UTF-8) 형식으로 볼 수 있다(윗 부분을 누르면 차례대로 바뀐다).


1.4 스택 패널

  스택의 주소, 주소에 들어있는 값, 문자열 그리고 설명을 보여준다. 설명에 자주 보이는 값들로는 먼저 SEH와 관련된 SE handler, Pointer to next SEH record가 있다. 그 외에도 함수를 호출하기 전에 파라미터들도 정리해서 보여주며(특히 API의 파라미터를 보여주므로 많은 도움이 된다) 호출된 함수 별로 구분해서 보여주는 역할도 한다. 즉 함수 호출 시에 스택을 보면 "RETURN from 주소1 to 주소2"와 같이 쓰여져 있는데 여기서 "주소2"는 이 프로시저가 복귀할 주소이며 "주소1"은 현재 호출된 프로시저의 주소(첫 부분)이다. 이것을 보고 함수들의 콜 스택을 구분할 수도 있다.


1.5 레지스터 패널

  가장 위에서는 자주 확인하게 될 EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI 그리고 EIP의 값과 설명을 보여준다. 그 아래에는 EFLAGS 즉 플래그 비트를 보여준다. C(Carry Flag), P(Parity Flag), A(Adjust Flag), Z(Zero Flag), S(Sign Flag), T(Trap Flag), D(Direction Flag), O(Overflow Flag)가 그것이다. 플래그 비트 아래에는 “표 1-4”와 같은 Condition Code들이 있다. 

  이것들은 위에서 설명한 플래그 비트들을 가지고 분기 명령어의 조건을 알 수 있다. 예를들면 현재 명령어가 JAE라고 하자. 이 때 아래 "표 1-5"를 찾아보면 JAE에서 AE는 NB와 같다는 것을 알 수 있다. 이것은 CF == 0이라는 것을 의미하므로 EFLAGS 즉 플래그 비트의 Carry Flag가 1인지 0인지를 보고 판단할 수 있다. 하지만 BE와 같이 여러 개의 플래그들을 가지고 할 경우 헷갈릴 수 있는데 이 때 도움이 되는것이 이것이다. 

  예를 들어 보겠다. 현재 실행하려는 분기문이 JAE이다. 그리고 옆의 레지스터 창을 보니 다음과 같은 부분이 보인다.

EFL 00000202 ( NO, NB, NE, A, NS, PO, GE, G)

  이 때 AE가 NB와 같다고 했는데 NB가 셋팅되어 있는것을 보니 (J)AE 명령어는 분기할 것이다. 물론 올리디버거의 화살표의 색깔이 빨간색으로 변했으므로 굳이 이것을 볼 필요는 없겠지만 여러가지로 해석하는데 도움을 준다는 것을 알 수 있다.

----- 표 1-5 ------------------------------------------------------

Mnemonic Condition Tested For             Status Flags Setting

O         Overflow                            OF == 1

NO       No overflow                        OF == 0

B Below                                CF == 1

NAE      Neither above nor equal        ''

NB Not below                          CF == 0

AE        Above or equal                    ''

E Equal                                 ZF == 1

Z Zero                                  ''

NE Not equal                           ZF == 0

NZ        Not zero                            ''

BE Below or qual                      CF == 1 || ZF == 1

NA        Not above                           ''

A Above                                CF == 0 && ZF == 0

NBE  Neither below nor equal         ''

S Sign                                   SF == 1

NS No sigh                              SF == 0

PE Parity even                          PF == 1

P    Parity                                 ''

PO Parity odd                           PF == 0

NP   No parity                            ''

GE Greater or equal                   SF == OF

NL   Not less                              ''

L    Less                                   SF != OF

NGE   Neigher greater nor equal      ''

LE   Less or equal                       ZF == 1 || SF != OF

NG     Not greater                         ''

G    Greater                               ZF == 0 && SF == OF

NLE  Neither less nor equal            ''

-----------------------------------------------------------------

  다시 위를 봐서 플래그 비트의 오른편에는 ES(Extra Segment), CS(Code Segment), SS(Stack Segment), DS(Data Segment), FS(F Segment), GS(G Segment)라는 세그먼트 레지스터가 보인다. 마지막에 있는 LastErr는 레지스터가 아니라 윈도우 API 함수들이 에러 코드를 저장하는 메모리의 내용이다. 


참고]

  Win32 API는 오류가 발생하면 NULL을 반환하는 구조로서 단지 오류 발생 유무만 확인할 수 있다. 하지만 오류의 원인을 알 수 없기 때문에 이 때 사용할 수 있는 것이 GetLastError() API이다. 이것을 사용하면 오류 코드를 확인할 수 있다. 더 깊게 들어가서 이 API는 실제로는 TEB의 LastErrorValue 필드의 값을 읽어오므로 직접 이 구조체를 통해 확인할 수도 있다. 올리디버거에서도 이 필드의 값이 위의 LastErr에 보여진다.


  플래그 레지스터 아래에는 st0~st7 까지 8개의 부동 소수점 레지스터 등이 있다.

부동 소수점 레지스터 아래에는 SSE(Streaming SIMD Extensions)를 위한 XMM 레지스터 등이 있다. 사실 이 부분은 그다지 관심이 없어서 그냥 넘어가겠다.


2. Log

  주소와 거기서 발생한 메시지들을 보여준다. 메시지들의 예로 Access violation 예외가 발생했다던지 BP에 걸렸다던지 등이 있다.


3. Executable modules

  메모리에 로드된 실행 파일과 DLL들을 보여준다. Base 주소, 크기, 엔트리 주소, 이름, 타입, 파일 버전, 정적 링크, 경로가 있다. 예를들면 현재 디버깅 중인 실행 파일부터 kernel32.dll, ntdll.dll 같은 것들이 올라와 있다. 


4. Memory map

  현재 애플리케이션의 메모리 맵을 보여준다. 실행 파일부터 로드된 DLL들의 메모리 맵과 간단한 정보를 볼 수 있다. 주소별로 크기와 Owner, 섹션, 포함된 내용, 종류, 접근 권한 등을 보여준다.

  예를들어 VirtualAlloc()으로 메모리를 할당하면 해당 주소 영역이 보여지기도 하여 눈으로 직접 확인할 수 있고(생성된 부분은 빨간색으로 보여진다), 마우스 오른쪽 클릭 후 메모리 BP를 걸 수도 있다. 이것은 굉장히 유용하게 사용될 수 있는데, 예를들어 현재 DLL 내부의 어느 부분인줄 모를 때 .text 섹션에 BP를 걸어놓고 실행시키면 해당 부분에서 멈출 수 있기 때문이다.

  문제는 더 복잡한 바이너리를 분석할 때이다. 이 때는 간단하게 DLL에서 복귀하는 부분이 아니라 할당한 메모리에 코드를 생성하고 여기에서 복잡한 연산을 수행하는 것이 그 예가 될 것이다. 물론 이러한 경우에도 위의 방식이 유용하게 사용될 수 있지만 메모리 BP이기 때문에 해당 영역에서 코드가 실행될 때 뿐만 아니라 해당 영역을 참조할 때도 멈추게 된다. 만약 돌아오고 싶은 영역이 단지 실행될 때 멈추고 싶은데 계속 해당 영역에 대한 읽고 쓰기가 반복되어 참조할 때마다 멈춘다면 BP의 의미가 없어질 것이다.

  이 때는 간단하게 마우스 오른쪽 클릭 후 "set access"에서 "Execute"만 설정하면 된다.


5. List of Windows

  윈도우의 목록을 보여준다. 핸들, 설명, 부모의 핸들, WinProc, ID/menu, Type, Style, ExtStyle, Thread, ClsProc, ClsName이 있다. 콘솔 프로그램이 아닌 윈도우 프로그램 분석 시 필요한 정보들이다.


6. Threads

  현재 스레드들을 보여준다. 순서, Ident, 윈도우 이름, Last error, Entry, TIB, Suspend, Priority, User time, System time이 있다. 멀티스레드일 경우 여길 보고 찾을 수 있다.


7. Handles

  현재 핸들들을 보여준다. 핸들, Type, Refs, Access, Tag, Info, Translated name이 있다. 문제는 파일 같은 경우 생성된 핸들을 잘 보여주는데 CreateProcess로 프로세스를 생성한 경우에는 보여주지 않는다. x64dbg의 경우 자세한 내용은 보여주지 않아도 이 경우 프로세스와 쓰레드는 보여주는데 OllyDbg는 다른 경우도 그렇고 많이 보여주는 편은 아닌것 같다. 분석 시에 핸들을 따로 적어놓을 필요가 있다. Windbg의 경우 불편하긴 하지만 프로세스 핸들의 PID를 보여줌으로써 추적이 가능하는 등 기능 자체는 많이 제공한다.


8. Watches

  설정한 Expression과 그 값을 보여준다. Expression을 추가한 후 각 라인 실행 후마다 결과를 볼 수 있다(예를들면 expression에 “EAX+ESI”라는 값을 설정해 놓으면 결과 값이 각 라인 실행 후마다 보여진다).


9. Search Results

  여러 검색 사용 시에 결과들을 보여주는 윈도우이다.


10. Run trace

  Run trace 결과를 보여준다. Back, Thread, Module, Address, Command, Referenced memory (decoded), Registers modified by command가 있다.


11. Patches

  수정한 기록을 보여준다.


12. INT3 breakpoints

  설정한 소프트웨어 브레이크 포인트(INT3) 즉, 단축키 F2를 통해 만든 BP들을 보여준다.


13. Memory breakpoints

  설정한 메모리 브레이크 포인트들을 보여준다.


14. Hardware breakpoints

  설정한 하드웨어 브레이크 포인트를 보여준다.


15. VEH/SEH chain

  VEH와 SEH 체인을 보여준다.


16. Call stack

  콜스택을 보여준다. 즉 호출한 서브루틴을 차곡차곡 쌓아서 보여준다.


17. Source files

  Module, Source, Path.






B. 메뉴


1. File

- Open : 리버싱할 파일 오픈. 드래그로 대신할 수도 있다. 파일을 선택하면서 argument도 같이 추가할 수 있다.

- Set new arguments… : 시작할 때 넣은 arguments 대신 다른 것을 넣을 수 있다.

- Attach... : 현재 실행중인 프로세스를 디버깅하고 싶을 때 사용.

- Detach

- Exit : 종료

- GUI language : 올리디버거가 위치한 디렉토리에 확장자가 .lng인 파일(올리디버거 2부터는 다른 언어를 지원한다)이 존재할 때 그 .lng 파일에서 지원하는 언어를 선택할 수 있다.


2. View

- Log : 올리디버거 실행 이후 로그를 보여준다. 

- Executable Modules : 메모리에 로드된 실행 파일과 DLL들을 보여준다.

- Memory map : 현재 애플리케이션의 메모리 맵을 보여준다.

- List of windows : 윈도우 목록

- Threads : 쓰레드 목록. 멀티스레드일 경우 여길 보고 찾을 수 있다.

- CPU : 현재 기본 윈도우

- Handles : 핸들 목록

- Watches : Expression을 추가한 후 각 라인 실행 후마다 결과를 볼 수 있다(예를들면 expression에 “EAX+ESI”라는 값을 설정해 놓으면 결과 값이 각 라인 실행 후마다 보여진다).

- Search results : 마우스 오른쪽 버튼으로 search한 결과들이 보여지는 창.

- Run trace : trace한 부분들을 볼 수 있다.

- Patches : 수정한 부분들. 예를들어 어셈블리를 수정한 경우 여기에 추가된다.

- INT3 breakpoints : 설정된 BP 리스트

- Memory breakpoints : 메모리에 BP 설정한 경우

- Hardware breakpoints : 하드웨어 BP 설정한 경우

- VEH/SEH chain : VEH, SEH 체인을 보여준다.

- Call stack : “Call stack”을 보여준다. 즉, 호출한 서브루틴을 차곡차곡 쌓아서 보여준다.

- Source files 

- File… : 파일 창. 예를들면 어셈블리를 수정하고 저장하고 싶을 때 (수정만 하면 메모리 상에서만 수정된 것이므로), 마우스 우클릭 -> Edit -> Copy to executable을 하면 이 창이 뜨고 이 창에서 마우스 우클릭 -> Save file 하면 저장된다.

- Drive… : 드라이브를 보여준다.


3. Debug

- Run [F9] : 실행 (BP가 걸려 있으면 그곳에서 실행이 정지된다.)

- Run thread [F11] : 현재 쓰레드만 실행한다.

- Step into [F7] : 한 줄씩 실행. CALL 명령 실행 시 그 함수로 따라 들어간다.

- Step over [F8] : CALL 명령 실행 시 그 함수를 실행한다. REP의 경우 만족할 때까지 계속 실행. 

- Execute till return [Ctrl+F9] : 함수 코드 내에서 RETN 명령까지 실행 (함수 탈출)

- Restart [Ctrl+F2] : 재시작

- Close [ALT+F2] : 종료

- Set affinity : 멀티프로세서인 경우 태스크를 수행할 CPU를 고른다.

- Create function library : 아래에 [참고]를 보자. 올리디버거는 이미 알고 있는 것들 외에도 표준 라이브러리 함수들을 추가할 수 있다. 이 기능을 통해서 라이브러리를 불러온 후에 .udl 파일로 저장하고 Directories 옵션에서 설정한 위치에서 이 .udl 파일을 불러와서 분석에 사용한다. 또한 Advanced 옵션에 나와있는 항목을 체크해야 사용할 수 있다.


참고] .udl

  올리디버거는 아래의 라이브러리들에 있는 2300개 이상의 API 함수들에 대한 정보를 갖는다. 또한 10000개 이상의 심볼릭 상수들을 알고 있다. 그렇기 때문에 리버싱을 하다 보면 GetModuleHandleA() 같은 함수들을 분석해서 이름과 파라미터 등에 대한 정보가 나와서 편하게 분석할 수 있는 것이다. 하지만 이것들 외에도 여러 라이브러리가 사용될 수 있기 때문에 위에서 설명하였 듯이 표준 라이브러리 함수들을 추가하는 방식 또한 제공한다.

kerne32.dll, gdi32.dll, user32.dll, ntdll.dll, version.dll, advapi32.dll, shlwapi.dll, comdlg32.dll, msvcrt.dll


4. Trace

- Open run trace : Run trace 윈도우를 연다.

- Clear run trace : Run trace를 모두 지운다.

- Close run trace : Run trace 윈도우를 닫는다.

- Animate into, Animate over : Step into, Step over와 비슷하지만 아래에 나올 condition을 건 곳까지 계속 실행한다. 중간에 멈추려면 F12. Run trace 윈도우를 보면 실행한 명령어와 추가 정보들이 기록되어 있다. 아래에 나오는 condition을 보면 알겠지만 일반적인 BP보다 훨씬 다양한 조건들을 지정할 수 있다.

- Trace into, Trace over : Animate into, Animate over와 거의 같지만 Animate가 명령어를 실행하면서 그것을 따라가는것과는 달리 이것은 각 명령어를 실행할 때마다 일일이 따라가지 않는다는 차이점이 있다. 즉 현재 디스어셈블러창을 그대로 두고 실행된다. 그것 외에는 Run trace 윈도우에 기록된다는 점이나 condition을 지정할 수 있다는 점 등 모두 같다.

- Run hit trace, Discard hit trace : Run hit trace를 선택하면 condition이 걸린 곳까지 실행되는데 이 때 실행한 경로가 빨간색 점으로 어셈블리어 왼쪽에 표시된다. 즉, 어디서부터 어디까지 어떤 경로로 실행되었는지를 CPU 윈도우에서 명시적으로 볼 수 있다. 이 기록을 지우고 싶다면 Discard hit trace를 누르면 된다.

- Set condition… : Run trace와 Hit trace를 중지할 조건을 지정한다.

- Set protocol… : Run trace 윈도우에 저장할 내용 지정(call만 저장한다든지 등등).


5. Plugins

플러그인을 추가하면 이곳에 등록된다.


6. Options

- Options...

- Load options… : 옵션을 불러온다.

- Save options… : 옵션을 저장한다.

- Edit shortcuts… : 단축키 설정


7. Windows

- Always on top : 항상 맨 위로

- Cascade : View들을 정렬해서 보여준다.

- Tile horizontal : View들을 수평으로 정렬한다.

- Tile vertical : View들을 수직으로 정렬한다.

- Arrange icons : 아이콘 정렬

- Close all : 모든 View들을 끈다.

- Restore window : View를 원상복귀

- Maximize window : VIew 최대화

- Previous : 이전 View를 보여준다.

- Next : 다음 View를 보여준다.


8. Help

- About

- License






C. 우클릭


1. 디스어셈블러, 덤프 패널에서 우클릭


1.1 Backup

- Create backup : 백업 파일을 만든다.

- Read executable file

- Load backup from file… : 백업 파일을 로드한다.

- Save data to file… : 백업 파일로 저장한다.


1.2 Edit

- Copy as table : 선택한 영역 테이블 형식으로 복사. 바이너리를 복사하고 붙여넣기할 때 사용되는 방식이 아니라 텍스트로서 복사하는 방식이다.

- Copy address : 선택한 영역 주소 복사

- Binary copy : 바이너리 복사. Copy as table과는 달리 오직 바이너리 부분만 복사한다. 

- Binary paste : 바이너리 붙여넣기 Binary copy로 복사한 후 붙여넣기를 하거나 HxD에서 복사한 후에 붙여넣기를 할 수 있다.

- Binary edit… : 바이너리 수정

- Fill with zeros : zero(00)들로 채워 넣는다.

- Fill with NOPs : NOP(90)들로 채워 넣는다.

- Select all : 전체 선택

- Select procedure : 현재 커서가 위치한 프로시저 선택

- Copy to executable : 위의 “File…” 윈도우에서 설명했다.


1.3 Add label… [ : ]

라벨을 단다. 콜론(:)을 사용해도 된다. 아래의 Label 항목 참조.


1.4 Assemble… 

어셈블리어를 수정한다.


1.5 Add comment… [ ; ]

주석을 단다. 세미콜론(;)을 사용해도 된다. CPU 윈도우의 디스어셈블러 패널의 오른쪽 부분인 Comment 창에서 주석을 볼 수 있다.


1.6 Breakoint

- Toggle : BP 설정, 제거

- Conditional… : BP 조건 설정. 예를들면 루프문에서 [ ECX == 1 ] 같이 사용할 수 있다. 이 경우에 실행시키면 ECX가 1이될 때 까지 실행하게된다.

- Conditional log… : conditional의 로그를 보여준다.

- Run to selection [F4] : 선택된 곳까지 실행.

- Memory… : 메모리 BP(메모리에 BP 설정). Read access, Write access, Execution이 있다.

- Momory log… : 메모리 BP 로그

- Hardware… : 하드웨어 BP. Execution, Access(R/W), Write가 있다.

- Hardware log… : 하드웨어 BP 로그

- Limit run trace protocol to selection : 선택한 부분만 Run trace에 저장.

- Limit run trace protocol to current procedure : 현재 프로시저만 Run trace에 저장.


1.7 New origin here

EIP의 값을 선택한 명령어의 주소로 바꾼다. 즉 다음으로 실행할 명령어를 이곳으로 설정한다.


1.8 Folow [Enter]

  직접 Step into할 필요 없이 다음 실행할 명령어로 이동한다. 예를들어서 CALL 명령어라면 어느 부분을 호출하는지 디버깅하거나 주소로 직접 찾아가는 방법 대신 Enter를 누르면 보여준다. 다시 -를 눌러서 되돌아 와서 Step into를 할지 Step over를 할지 고를 수 있다.


1.9 Follow in Dump

- Memory Address : 현재 지정한 주소를 아래의 덤프 패널에서 보여준다.

- Immediate constants : 명령어의 상수 값이 나타내는 위치를 덤프 패널에서 보여준다. 

- Selection : 이 명령어의 위치를 덤프 패널에서 보여준다.


1.10 Go to

- Origin : EP로 이동

- Expression… : 특정 위치로 이동. 여기에는 직접 주소를 쓸수도 있고 모듈의 함수(예를들면 API)를 쓸 수도 있다. 

- Previous location : 이전 위치로 이동

- Next location : 다음 위치로 이동 (Previous location 한 후에 가능)

- Previous procedure : 이전 프로시저로 이동

- Next procedure : 다음 프로시저로 이동

- Executable file : 메모리가 아닌 실행 파일에서 선택한 명령어를 보여준다.


1.11 Select module

현재 올라온 모듈들 중에서 선택한다.


1.12 Select thread

현재 쓰레드 중에서 선택한다.


1.13 Open in a separate dump window

다른 덤프 윈도우에서 선택한 부분을 보여준다.


1.14 Search for

- Names : 존재하는 모든 Name들을 보여준다.

- Command… : 명령어 검색 (예를들면 “call 00401E2B”)

- Sequence of commands… : 명령어들 검색 

- Constant… : 상수 검색

- Binary string… : 문자열 검색

- All intermodular calls : Import 된 함수들의 목록을 본다. (대부분 API)

- All commands…: 찾는 모든 명령어의 목록을 보여준다.

- All command sequences… : 찾는 모든 명령어들의 목록을 보여준다.

- All constants… : 찾는 모든 상수들을 보여준다.

- All modifications : 모든 수정 사항들을 보여준다.

- All referenced strings : 모든 문자열들을 보여준다.

- All referenced GUIDs : 모든 GUID들을 보여준다. 

- All user comments : 사용자가 설정한 모든 주석들을 보여준다.

- All found procedures : 모든 프로시저들을 보여준다.

- All found switches : 스위치 구문도 찾아준다.

- All floating constants : 모든 부동 소수점 상수들을 보여준다.


1.15 Find references to

- Selected command : 역참조. 어디서 이곳을 호출하는지 보여준다. 예를들면 일반적으로 프로그램은 스텁 코드를 지나 main() 함수로 진입한다. 즉 스텁 코드에서 main()을 호출하는 부분, 다시 말해서 main()의 처음 명령어를 호출하는 부분이 있을 것이다. 이 경우 main() 함수의 첫 명령어에 대해 Selected command를 수행하면 스텁 영역에서 main()을 호출한 명령어가 나올 것이다. 또한 검색 결과는 같은 모듈의 경우에만 검색하여 보여준다. 예를들어 대상이 API 함수인 경우 어디 어디에서 해당 API 함수를 호출하는지 알고 싶어서 API 함수의 첫 명령어에서 이것을 호출한 경우에는 원하는 답을 얻을 수 없다. API 함수가 구현된 모듈은 각각의 해당 라이브러리일 것이기 때문이다. 이 경우에는 아래의 항목을 사용할 수 있다. 또한 call 명령어 뿐만 아니라 jmp 류의 명령어도 해당 위치로 분기한다면 이것도 찾아준다.

- Call destination : CALL한 목적지가 같은 곳들을 보여준다. 즉 같은 곳을 호출하는 명령어들을 찾아준다. 당연히 call 명령어를 대상으로 수행할 경우에만 볼 수 있다. Selected command와 다른 점은 호출되는 명령어에서 사용하는 대신 호출하는 call 명령어에서 이것을 수행한다는 점이다. 그래서 위에서 언급하였듯이 특정 API 함수를 어디 어디에서 호출하는지 알고 싶은 경우 해당 API를 호출하는 명령어에 대해 Call destination을 수행하면 어디 어디에서 해당 API 함수를 호출하는지 알 수 있다. 이것도 같은 모듈의 경우에만 해당된다.

- Jump destination : Jump한 목적지가 같은 곳들을 보여준다. Call destination과 같으며 차이점은 jmp 류의 분기문을 대상으로 수행할 경우에만 볼 수 있다. 이것도 분기하는 jmp 문들에서 사용될 때 같은 위치로 분기하는 jmp 문들을 찾아준다.

- Address constant : 같은 상수를 사용하는 명령어들을 찾아준다. 주소로 상수를 갖는 명령어를 대상으로 수행한 경우에 볼 수 있는 항목이다. 예를들어 call 명령어 중에서 옵코드가 FF15인 것은 분기할 주소를 상수로 가지고 있다. 조금 더 자세히 설명하자면 호출할 함수의 주소가 IAT에 존재하게 되는데 호출할 함수에 대한 IAT의 주소를 상수로 가지고 있는 것이다. 어쨌든 이 경우와 같이 주소를 상수로 가지고 있는 경우 항목이 보여지며 수행할 경우 이것처럼 해당 IAT 주소를 참조하여 분기하는 call 들을 볼 수 있다.

- Immediate constant : 해당 인자와 같은 인자를 사용하는 명령어들을 찾아준다. 상수를 인자로 갖는 명령어를 대상으로 수행할 경우에만 볼 수 있다. 예를들어 "push 1" 명령어에 Immediate constant를 수행하면 같은 모듈 안에서 "mov al, 1", "cmp esi, 1" 등 1을 인자로 사용하는 명령어들을 모두 찾아준다.


1.16 Highlight register

- Stop highlighting

- EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI

선택한 레지스터를 강조 한다.


1.17 Addressing

- Absolute, Relative to selection, Relative to module base

디스어셈블리 윈도우에서 주소를 어떻게 보여줄지 정한다.


1.18 Comments

- Show comments : 코멘트를 보여준다.

- Show source : 소스를 보여준다.

- Show profile : 코멘트와 프로필을 보여준다. 프로필은 trace했을 때 몇 번이나 지나갔는지를 나타내는 숫자를 보여준다.


1.19 Analysis

- Analyse code [Ctrl+A] : 어셈블리 분석

- Remove analysis from selection : 선택한 부분 분석 제거

- Remove analysis from module : 모듈에서 분석 제거. 올리디버거의 분석이 실패했을 때. 특정 코드 부분을 데이터로 해석한 경우에 분석을 제거하면 원래 코드로 보일 때가 있다.


1.20 Help on command

명령어에 대한 설명


1.21 Appearance

참고로 옵션에서 설정한 이후 이것을 통해 직접 선택해야 적용시킬 수 있다. 적용은 디스어셈블리 패널에 한정한다.

- Always on top : View들 사이에서 항상 맨위로

- Show bar : 위에 Address, Hex dump 같은 bar 표시

- Show horizontal scroll : 수평 스크롤 표시

- Default columns

- Font

- Colours

- Highlighting - No highlighting, Christmas tree, Jumps and calls, Memory access, Hilite 4, Hilite 5, Hilite 6, Hilite 7






2. 레지스터 패널에서 우클릭

- Increment : 특정 레지스터의 값을 1 올린다.

- Decrement

- Zero

- Set to 1

- Modify ...

- Copy to clipboard

- Copy all registers : 내용을 복사한다.

- Follow in disassembler

- Follow in dump

- View MMX registers

- View 3DNow! registers

- View SSE as 32-bit floats

- View SSE as 64-bit doubles

- Appearance : 이것도 디스어셈블리 패널과 같다.





3. 스택 패널에서 우클릭

- Lock address : 디버깅을 할 때마다 PUSH, POP 등을 수행하며 ESP 값에 따라 위아래로 움직이는데 이것을 움직이지 않게 고정해 놓는다.

- Backup

- Edit

- Push DWORD… : DWORD 크기의 값을 PUSH한다.

- Pop DWORD : DWORD 크기의 값을 POP한다.

- Breakpoint

- Follow in Disassembler, Follow in Dump : 디스어셈블러나 덤프에서 여기에 대응하는 위치를 보여준다.

- Go to

- Select module

- Decode as structure…, Decode as pointer to structure… : 아래의 구조체 항목 참조.

- Search for

- Addressing

- Columns

- Select ASCII code page

- Appearance : 이것도 디스어셈블리 패널과 같다.





참고] 명령어 검색


  가끔씩 어셈블리 명령어를 검색할 일이 생긴다. 만약 다음과 같이 확실한 명령어를 찾는다면 직접 검색해도 될 것이다.


push 18

mov ebx, dword ptr ss:[ebp-48]


  [ Ctrl + F ]로 Search 윈도우를 켠 후 위의 명령어를 입력하면 결과를 얻을 수 있다. 하지만 이 방식은 불편하기 때문에 마우스 오른쪽 키를 클릭하고 [ Search for - All commands .. ] 또는 [ Search for - All commands sequences .. ]를 이용하여 전체 결과를 얻는 것이 훨씬 편한 방법으로 보인다. 


  어쨌든 위와 같이 확실한 명령어를 검색할 일도 있지만 단지 패턴만 알고 있는 경우가 대부분일 것이다. OllyDbg는 이러한 경우도 지원해 준다. 가장 넓은 범위는 ANY라는 키워드이다. 다음을 검색하면 push ebp부터 시작해서 push 18까지 모든 결과를 볼 수 있다.


push any


  만약 위와 같이 상수만을 보고 싶다면 const 키워드를 이용한다.


push const


  레지스터의 경우도 지원된다. 여러가지가 있겠지만 대부분 r32일 것이며 이외에도 r16, r8도 지원된다. push ebp 같은 명령어를 찾고 싶다면 다음을 검색에 사용한다.


push r32


  또한 메모리 주소도 사용할 수 있다. 위의 mov ebx, dword ptr ss:[ebp-48]를 검색하는데 다음을 사용할 수 있다.


mov r32, [any]


  또는 다음과 같이 사용할 수도 있다.


mov r32, [r32-const]


  가장 많이 활용되는 방식 중 하나로 다음과 같이 call 명령어와 관련된 것이 있다.


call [any]

call [const]


  그리고 xor eax, eax 같이 두 레지스터가 같이 사용되는 경우를 찾는 것도 존재한다.


xor ra, rb

xor r32a, r32b


  마지막으로 다음의 키워드들도 제공된다.


JCC : (JB, JNE, JE 등)

SETCC : (SETB, SETNE 등)

CMOVCC : (CMOVB, CMOVNE 등)

FCMOVCC : (FCMOVB, FCMOVE 등)





4. 덤프 패널에서 우클릭

- Backup

- Edit

- Add label...

- Assemble...

- Breakpoint

- Follow DWORD in Dump

- Go to : 덤프 패널도 디스어셈블리 패널처럼 (-), (+) 키를 통해 이전과 이후로 전환할 수 있다.

- Decode as structure ... : 아래의 구조체 항목 참조

- Decode as pointer to structure ... : 아래의 구조체 항목 참조

- Open in a separate dump window

- Search for

- Addressing

- Hex

- Text

- Integer

- Float

- Disassemble : 데이터나 스택에 코드를 써놓은 경우 Follow Dump를 통해 덤프 창에서 보여지게 한 후 이것을 선택하면 코드를 간략하게 볼 수 있다.

- Select ASCII code page

- Appearance : 이것도 디스어셈블리 패널과 같다.





참고] 구조체

  레지스터, 스택 덤프 패널에서 해당 값 또는 해당 주소가 가리키는 포인터를 구조체로 참조하게 만들 수 있다. 이를 선택하면 어떤 구조체인지 선택할 수 있는데 대표적으로 TEB, PEB, Context, 예외 관련 등 많이 볼 수 있다. 인터넷에서 직접 찾을 수 있지만 이렇게 일목요연하게 보여준다는 것이 괜찮은 기능인 것 같다.


  [ Decode as structure ... ]의 경우 덤프 패널에서 선택한 경우 선택된 해당 주소를 구조체로 지정할 수 있다. 스택 패널의 경우 해당 ESP를 구조체로 여기게 된다. [ Decode as pointer to structure ... ]는 해당 주소까지 갈 필요 없이 특정 메모리 주소의 값이 해당 구조체일 경우 선택 가능하다. 스택 패널의 경우 해당 ESP에 들어있는 값을 구조체로 여기게 된다.


  찾아보니 이 구조체를 사용자가 직접 추가할 수도 있다. https://reverseengineering.stackexchange.com/questions/11893/creating-my-own-custom-structure-in-ollydbg ]


  어떤 면에서는 유용해 보이지 않을 수도 있지만 자동으로 Label을 달아주는 기능이 있다면 동적으로 분석할 때에도 괜찮아 보인다. 사실 정적 분석 시에는 한계가 있으며 Ida pro를 이용해 정적으로 몇 개 찾은 것도 .map 파일을 만들어서 올리디버거로 올리면 이 부분이 보이지 않으므로 (대부분 지역 변수 즉 스택을 이용하기 때문으로 추측) 해당 주소에 대해 구조체 형태로 보여주는 기능이 있으니 자동으로 Label까지 달아준다면 분석에 더 용이해 보인다. 특히 델파이나 C++의 경우 분석이 까다로운 경우가 있는데 어느 정도는 도움을 받을 수 있다고 생각한다.





참고] Label

  Ollydbg는 Windbg나 Gdb와 다르게 .udd 파일에 분석 결과를 저장함으로써 디스어셈블러의 기능을 가지고 있다. 이 기능을 통해 디스어셈블러처럼 함수나 변수에 이름을 달 수 있다. (스택 영역 즉 지역변수는 불가능하다)

  함수의 시작 주소에 Label을 달면 Comments 창에 보이지는 않지만 이후 이 함수를 호출할 때 주소 대신 설정한 이름을 보여준다. 또한 덤프 패널에서 사용할 수도 있는데 이를 통해 전역 변수 즉 데이터 영역의 값을 참조할 때도 이름을 붙일 수 있다.









D. 옵션


1. Code

Disassembling syntax : [MASM, IDEAL, HLA, Linux(AT&T)]

; 선택한 어셈블리어 문법 형식으로 보여준다.

Disassemble in lowercase

; 어셈블리어를 소문자로 표시한다.

Tab between mnemonics and arguments

; 니모닉과 인수 사이를 Tab으로 띈다.

Extra space between arguments

; 인자들 사이를 더 띈다.

Show default segments

; 기본 세그먼트를 보여준다.

Always show size of memory operands

; 메모리 오퍼랜드의 크기를 보여준다. (DWORD PTR 같은) 하지만 뒤에 따라 붙는 상수의 크기 해석이 모호한 경우 즉 DWORD, DWORD BYTE 모두 가능한 경우에는 계속 붙어있는다.

Show NEAR jump modifiers

; NEAR jump의 경우 NEAR를 표시한다.

Show local module name

; 주소 앞에 모듈 이름도 같이 표시한다.

Show symbolic addresses

; 심볼릭 주소 표시 (00400000 -> OFFSET <STRUCT IMAGE_DOS_HEADER>로 표시)

Demangle symbolic names

; Mangling 된 C++ Name을 Demangling 해서 보여준다.


1.1 Mnemonics

Guess alternative forms of conditional commands

; 조건 명령어의 경우 ollydbg가 분석을 해서 상황에 맞게 JE를 JZ로, JAE를 JC로 같이 더 나은 명령어로 바꿔준다.

Form of string commands : [Long, Short]

; String operand를 가정해서 명시적으로 표현하거나 하지 않는다. 예를들면 그냥 MOVSB로 표현하든지 아니면 "MOVS [DWORD EDI], [DWORD ESI]" 같이 표현한다.

Decode near returns as : [RETN, RET]

; NEAR Return인 경우 RETN으로 표시해서 near를 강조하거나 그냥 RET로 표시

Decode size-sensitive 16/32-bit mnemonics like : [PUSHA/PUSHAD, MOVS/MOVSD…, PUSHAW/PUSHAD, MOVSW/MOVSD... , PUSHAW/PUSHA, MOVSW/MOVS...]

; 첫 번째는 32비트인 경우 접미사로 D를 붙이고, 두 번째는 16비트는 W를 32비트는 D를 붙이고, 세 번째는 16비트만 W를 붙인다. 

Decode jump hints as

; 점프 힌트와 관련된 옵션.


1.2 Operands

Decode top of FPU stack as

Decode size of 16/32-byte SSE operands as


1.3 Dump

Underline fixups

; CPU 윈도우의 Hex dump 칼럼에서 fixup 주소(로더가 재설정한 주소)인 경우 밑줄을 긋는다.

Use wide characters in UNICODE & multibyte dumps

; UNICODE와 multibyte의 경우 wide character를 사용한다.

Disable GDI scripting support

Replace non-printable ASCII characters with dots

; 덤프 패널에서 보여줄 수 없는 문자는 점으로 표시한다.

Display address in address column as : [(Hex, Symbol), (Symbol, Hex), (Symbol or Hex)]

; CPU 윈도우의 디스어셈블러 패널의 Address 칼럼을 늘려 보면 Hex 값의 주소 뿐만 아니라 Symbolic name도 보여지는 것을 알 수 있다. 이것의 순서를 바꿀 수 있다.

Highlight symbolic names in address column

; Symbolic name을 강조한다.

Doubleclick on address : [Sets relative addressing, Labels address]

; 주소를 더블클릭할 시에 상대주소로 바꾸거나 사용자 정의 라벨을 붙인다.

ASCII code page, Multibyte code page

; ASCII 코드와 Multibyte 코드의 경우 사용되는 코드 페이지


1.4 Strings

Decode Pascal-style string constants

Allow diacritical symbols [...]

; 다양한 문자까지 인식해서 보여준다.

To recognize UNICODE strings []

; UNICODE 문자열을 ASCII와 같은 부분집합만 인식하거나, 윈도우가 결정하게 한다. 

Mode of string decoding [Plain, Assembler, C]

; 문자열을 Plain의 경우 [“abc|def”], Assembler의 경우 [“abc”,LF”def”], C의 경우 [“abc\ndef”] 형식으로 보여준다.



2. Debugging

Assume flat selectors

; CS, DS, SS, ES가 항상 zero 오프셋을 갖는다고 가정한다. 즉, 레지스터 패널에서 값이 사라진다.

After Execute till return, step over RET

; 원래 Ctrl+F9 즉, “Execute till return”를 하면 RET에서 멈추는데 이걸 선택하면 리턴까지 실행하고 멈춘다.

Allow fast command emulation

; 자주 사용되는 CPU 명령어들을 내부적으로 emulate하게 해서 디버깅을 빠르게 해준다.

Auto backup user code

; 시스템 코드 섹션이 아닌 사용자 코드는 자동으로 백업한다.

Use HW breakpoints for stepping

; 디버깅 시 INT3 대신 HW BP를 사용한다. 사실 디버거는 소프트웨어 브레이크포인트(INT3)를 통해서 디버깅을 진행하는데 우리 눈에는 보이지 않지만 Step into의 경우 다음 명령어의 뒤에 브레이크포인트를 걸어 놓아서 한 명령어만 실행하고 멈출 수 있게 한다.

Hide unimportant handles

; 중요하지 않은 핸들은 Handle 윈도우에서 숨긴다.

Set permanent breakpoints on system calls

; KERNEL32.UnhandledExceptionFilter(), NTDLL.KiUserExceptionDispatcher(), NTDLL.ZwContinue(),  NTDLL.NtQueryInformationProcess() 같은 시스템 호출에 INT3, 즉 브레이크포인트를 설정한다.

To pause running application : [Set breakpoint in every thread, Call DebugBreakProcess]

; 실행 중인 애플리케이션을 중지하기 위해 모든 스레드에 메모리 트랩이나 싱글 스텝 브레이크를 건다. 또는 OS가 지원한다면 DebugBreakProcess()라는 특별한 시스템 호출을 사용한다.

When terminating the running application : [Immediately call TerminateProcess(), Try to use ExitProcess() first]

; 실행 중인 애플리케이션 종료 시 사용 옵션. 첫 번째는 빠르고, 두 번째는 더 안전하다.

Command used as a soft breakpoint

; 소프트 브레이크포인트로 사용할 명령어. 기본은 INT3이다.


2.1 Debugging data

Use debugging data

; DBGHELP.DLL을 허용한다. 이 파일이 올리디버거가 있는 디렉토리에 같이 있어야 한다.

Use dbghelp.dll for stack walk

; 스택 탐색을 위해 DBGHELP.StackWalk64()를 사용한다.

Directories containing debugging data (.pdb, .dbg...). Dbghelp.dll will also recurse into subdirectories.

; .pdb 같은 디버깅 데이터가 존재하는 디렉토리 경로. 참고로 안에 있는 서브 디렉토리도 검사한다. 그리고 그곳에 소스 코드도 있다면 그것도 분석할 때 소스 코드 윈도우에서 참고할 수 있다.

Allow access to Microsoft Symbol Server

; SymSrv.dll 파일을 이 디렉토리에 복사해 넣어야 한다.

Don’t list missing source files

Don’t list internal compiler labels

Skip leading spaces from source lines in comments


참고] DbgHelp.dll

  디버깅을 도와주는 여러 API들을 제공한다. 예를들면 dbghelp.stackwalk64() API는 콜스택을 보여준다. [ http://www.codeproject.com/Articles/11132/Walking-the-callstack ]


참고]

  이미 생성된 .udd 파일 때문에 헷갈릴 수 있으므로 즉 한 번 분석된 경우 .udd 파일에 분석 내용이 저장되므로 이것을 지워야 pdb와 관련된 조사를 할 수 있다. 올리디버거는 실행 파일이 있는 폴더에서 pdb 파일을 찾아서 자동으로 사용한다. 저 위의 디렉토리 옵션은 pdb가 존재하는 추가적인 디렉토리를 설정해 줄 수 있다. 참고로 비주얼 스튜디오로 컴파일 시 /DEBUG 옵션을 사용해서 디버그 섹션이 추가되면 이 섹션 내부에 디렉토리 정보가 추가되어 있기 때문에 디렉토리 설정을 하지 않아도 자동으로 pdb가 있는 디렉토리를 찾아 읽어서 분석해 준다. 



2.2 Start

When starting application, make first pause at : [System breakpoint, TLS callback (if defined), Entry point of main module, WinMain (if location is known), No pause]

; 맨 처음 디버깅 시에 어디서 시작할 것인지. Entry point of main module로 설정하는 것이 좋다.

When attaching to application, make first pause at : [System breakpoint, Application code, No pause]

; 실행중인 프로그램 Attach할 시

When loading DLL, make first pause at : [Entry point of LOADDLL.EXE, DLL entry point (if defined), After call to LoadLibrary(), No pause]

; DLL 로드 시


2.3 Events

Warn on frequent events

Pause on new module (DLL)

; 새로운 DLL이 로드되면, EP에서 중지한다. 즉, 이것을 설정하고 실행하면 새로운 DLL을 로드할 때마다 자동으로 BP가 걸린다.

Pause on module (DLL) unloading

; DLL이 메모리에서 제거되면 중지한다.

Only on the following modules

; 오직 여기서 추가한 모듈만 중지한다.

Pause on new thread

; 새로운 스레드가 시작되면 EP에서 중지한다.

Pause on thread end

; 스레드가 끝나면 중지한다.

Pause on debug string

; 애플리케이션이 디버그 문자열을 내보내면 중지한다.

Debug child processes

; 디버기가 자식 프로세스를 만들면 새로운 ollydbg를 시작해서 디버깅한다.


2.4 Exceptions

Ignore memory access violations in KERNEL32

; kernel32.dll 모듈에서 발생하는 access violation 예외를 무시한다.

Step over INT3 breaks in MSCORWKS

; .NET 엔진이 디버거에게 이벤트를 알린다.

Ignore (pass to debugged program) following exceptions : [INT3 breaks, Single-step breaks, Memory access violations, Integer division by 0, Invalid or privileged instructions, All FPU exceptions, All service exceptions]

; 해당하는 예외를 무시한다. 이것은 디버거로 넘어온 예외를 Shift+Run/Step을 하지 않고 자동으로 다시 디버기에게 넘기겠다는 것을 의미한다.

Ignore also the following custom exceptions or ranges

; 나머지 예외들을 직접 설정할 수 있다.

Pass unprocessed exceptions to Unhandled Exception Filter

; 처리하지 않은 예외들을 Unhandled Exception Filter에 넘긴다.

  일반적으로 SetUnhandledExceptionFilter() 함수를 사용해 Unhandled Exception을 처리하는 경우에는 디버깅 시에 등록된 Unhandled Exception Handler가 실행되지 않고 중간에 프로세스가 종료되 어 버린다. 이것은 예외 발생 시 KiUserExceptionDispatcher() 및 RtlDispatchException()를 지나 등록한 Unhandled Exception Handler를 실행하기 이전에 ProcessDebugPort를 인자로 넣는 NtQueryInformationProcess()가 호출되는데 이 때 결과가 FFFFFFFF이기 때문이다. 그래서 이 값을 0으로 설정해 주어야 디버거에서도 정상적으로 실행될 수 있다. 이 옵션을 설정하면 NtQueryInformationProcess()에 BP를 걸고 확인하는 수고로움 없이 정상적으로 디버깅을 수행할 수 있게 된다.

  간단히 설명해서 디폴트로 이 옵션이 선택되어 있지 않다. 이 경우 Unhandled Exception Filter 함수를 등록할 때 등록한 이 함수에 BP를 걸고 예외 발생 시에 Ctrl+F9를 통해 BP로 가려고 해도 가지지 않는다. 그래서 이 함수가 사용되는 경우에는 이 옵션을 선택해야 앞에서 말한 방식으로 간단하게 해당 예외 필터 함수로 갈 수 있다.

Report ignored exceptions to log

; 무시한 예외들을 로그에 기록한다.


참고] 예외

  명령어를 실행시키는 중 예외가 발생할 경우 맨 아래를 보면 "Shift+Run/Step to pass exception to the program"이라는 내용이 보인다. 이 때 Shift+F7/F8/F9를 누름으로써 예외 처리 루틴으로 넘어갈 수 있다. 이것은 원래 디버거라는 것이 디버기에 대한 제어를 갖기 때 문에 당연히 예외 발생 시에도 디버거에게 제어가 넘어와 일어나는 일인데 위의 키를 누름으 로써 예외를 다시 프로그램으로 넘겨주는 것이다. 

  이것을 리버싱하는 방법은 SEH의 경우에는 등록된 핸들러의 주소에 BP를 거는 방법이 있겠고 내부까지 들어가서 직접 분석하기 위해서는 ntdll.KiUserExceptionDispatcher()의 진입점에 BP를 걸면 예외 발생 후 커널로 넘겨진 제어가 커널로부터 복귀한 그 시점부터 바로 분석할 수 있다.

  그리고 위에 나온 예외를 무시한다는 옵션은 위에서 말했듯이 디버거로 넘어온 예외에 대해 Shift+Run/Step 등을 선택하지 않고 자동으로 다시 디버기에게 넘기겠다는 것을 의미한다.



2.5 Run trace

Size of run trace buffer

; Run trace 버퍼의 크기 설정

When tracing or animating into : [Don’t enter system DLLs] [Always trace over string commands]

; Trace나 Animate할 때 system DLLs 함수 즉, API 내부로도 들어갈 지. 그리고 REP MOVSB 같은 string command는 항상 Trace over할지.

Remember commands

; 트레이스된 명령어의 사본을 trace 버퍼에 저장한다. 프로그램이 자가 변조 코드를 사용할 때(패커나 프로텍터 처럼) 유용하다.

Remember memory

; 메모리 값의 실제 내용도 저장한다.

Remember FPU registers

; 부동소수점 레지스터도 저장한다.

Synchronize CPU and run trace

; CPU display와 Run trace를 동기화한다.

Animation delay


2.6 Hit trace

When starting hit test : [Set breakpoints on known callbacks]

; 모든 알려진 콜백 함수들에 trace BP를 설치해서, SendMessage() 같은 윈도우 API 함수들도 trace될 수 있게 한다.

When indirect or table-based jump or call is hit : [Check destination each time, Use analysis data to guess destinations]

; 간접 점프와 호출의 경우 첫번째는 신뢰할 만한 trace를 수행하며, 두번째는 추정해서 

사용하므로 속도가 더 빠르다.

When next destination is analysed as data : [Continue hit trace, Pause hit trace]

; 다음 목적지가 데이터로 여겨지는 경우 계속 할지

When next destination is outside the code section : [Continue hit trace, Pause hit trace, Trace code command by command]

; 다음 목적지가 코드 섹션이 아닐 경우 계속 할지

Keep hit trace between sessions

; hit trace가 .udd 파일에 저장되고, 애플리케이션을 다시 시작할 때 복구된다.


참고] .udd

  올리디버거가 자동으로 저장하는 프로그램과 모듈의 정보로서 다시 로드할 떄 이것의 내용을 가지고 복구한다. 이 정보들로는 라벨, 주석, 브레이크포인트, watch, 분석 데이터, condition 등이 있다.


2.7 SFX

Unpack SFX modules automatically : [Use hit trace(fast!), Use run trace (reliable)]

; 자체 압축 풀림 기능을 가진 모듈을 자동으로 언패킹한다.

Use real entry from previous run

; 이전 실행 시 찾은 EP를 사용한다. 즉 실제 EP를 알게된 경우 SFX extract를 가속화한다.

Pass exceptions to SFX extractor

; extract 하는 동안 모든 예외를 extractor에 보냄으로써 무시한다.


2.8 Just-in-time

Current just-in-time debugger

Previous just-in-time debugger

Confirm before attaching

; Just-in-time 디버거란 프로그램 실행 중 Crash 발생 시 원하는 디버거로 연결해서 디버깅을 수행하는 것이다. 즉, 여기서는 ollydbg를 Just-in-time 디버거로 설정할 수 있다.


참고]

  현재 시스템에 설정된 JIT 디버거는 다음의 레지스트리 키에서 확인할 수 있다.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug



3. Analysis

Recognition of procedures : [Strict, Fuzzy]

; 확실한 프로시저만 인식하거나, 연결된 것들은 다 프로시저로 인식한다.

Automatical module analysis : [Off, Main module, Non-system modules, All modules]

; 자동 모듈 분석을 끄거나, Main 모듈만, 시스템 외부 모듈 모두, 로드된 모든 모듈

Show predicted register values

; 디스어셈블러 패널의 comments 창에 예상되는 레지스터 값을 보여준다.

Don’t predict register contents for system DLLs

; 시스템 DLL의 경우 레지스터의 내용을 예상하지 않는다.

Show recognized ARGs and LOCALs in disassembly, Show recognized ARGs and LOCALs in comments

; EBP로 표시되던 로컬 변수와 파라미터가 각각 LOCAL.1 같은 형식과 ARG.1 같은 형식으로 변환되서 보여진다. 이것은 가독성을 매우 높여준다.

Use symbolic names for ARGs, if known

; ARG.1 대신 ARG.hCurrInstance 처럼 보여준다.


3.1 Advanced

Decode tricky code sequences

; (주로 직쩝 짜인) tricky한 코드를 해독한다.

Decode cascaded IFs as switches

; ‘IF i==1 … ELSEIF i==2 … ELSE … ‘ 같은 형식을 switch로 여긴다.

Allow arguments renaming for known functions

; 알려진 함수의 경우 argument들의 이름을 다시 짓는다.

Guess number of arguments of unknown functions

; 알려지지 않은 함수들의 경우 argument들의 수를 추정한다.

Extract arguments from mangled names

; arguments를 추측하기 위해 mangled name들에 숨겨진 정보를 이용한다.

Guess meaning of unknown arguments

; 알려지지 않은 argument들의 의미를 추정한다.

Show arguments even if their number varies

; 다른 호출에서 인식된 argument들의 수가 다르다고 해도 argument들을 보여준다.

Detect standard library functions (*.udl)

; 만들어진 .udl 파일들을 통해 표준 라이브러리 함수들을 탐색한다.

Comment constant operands of known functions : [All known, Only those marked as important]

; 알려진 함수들의 상수 오퍼랜드에 Comment 한다. 

Unknown functions preserve registers : [None, EBP, (EBX, EBP, ESI and EDI)]

; 알려지지 않은 함수가 모든 레지스터를 수정할 수 있는지, 프레임 포인터인 EBP는 보존해야 하는지, stdcall을 따라야 하는지 선택한다.

Ignore braces in .udd path

; .udd 파일을 열 때 {}로 감싸진 부분을 무시한다.


3.2 Invalid commands

Accept following potentially invalid commands

; 다음처럼 잠재적으로 유효하지 않은 명령어들을 허용한다.

Far calls and returns

Modifications of segment registers

Privileged commands

I/O commands

Commands equivalent to NOP

Shifts out of range 1..31

Superfluous prefixes

LOCK prefixes

Default selectors

Unaligned stack operations

Suspicious ESP modifications

Undocumented commands

Access to nonexisting memory

Interrupt commands



4. Search

Use predictions in search

; 검색 수행 시 레지스터들의 예상된 contents을 사용한다.

Include indirect call/jump destinations in references

; 참조 시 간접 call/jump 목적지도 포함한다. 

Add origin to the list of found commands

Preferable language of resource data



5. CPU

Gray inactive panes

; 활성화되지 않은 패널 창은 회색으로 표시

Gray register names

; 레지스터 패널 창에서 레지스터를 회색으로 표시

Show direction of jumps

; 점프 방향을 빨간색 화살표로 표시

Show jump path

; 점프 경로 표시

Show grayed path if jump is not taken

; Jump가 아닐 시(조건이 맞지 않아서) 점프 경로를 회색으로 표시

Enable SSE registers

; 레지스터 패널에 SSE 레지스터를 보인다.

Decode contents of registers : [Only for current EIP, For EIP and selected command, For any command]

; 레지스터들의 내용을 해석한다.

Hide ‘current registers’ warning

Automatic FPU/MMX/3DNow! registers : [Never, On events, Always]


5.1 More CPU

When letter key is pressed in Disassembler : [Add label, Assemble command, Add comment, Repeat last action]

; 디스어셈블러 패널에서 글자가 눌러지면 선택된 위치의 명령어에서 할 일. 즉, Assemble command라면 a키를 누르면 Space 키를 누른 것처럼 Assemble 창이 뜬다.



6. Directories

Directory for .udd files

; .udd 파일이 저장될 위치. udd는 백업 파일 형식이다. 즉 올리디버거가 분석을 하고난 후에 이 파일이 생성되며 이후 다시 실행 파일을 로드할 때 이미 분석된 정보가 있는 이 파일을 가지고 빨리 사용할 수 있다.

  올리디버거가 자동으로 분석한 내용들 외에도 사용자가 지정한 주석이나 라벨 정보도 저장된다. 이를 통해 주석이나 라벨을 달면서 분석할 수 있는 등 디스어셈블러 기능도 유용하여 IDA Pro를 이용해 분석하는 것과 비슷하게 사용될 수 있다. 문제는 이 정보가 .udd에 항상 저장이 되지만 이 파일에는 경로명 또한 저장되기 때문에 다른 환경으로 .udd 파일을 옮겨서 그곳에서 분석하고자 한다면 제대로 인식하지 못할 것이다.

Directory for standard function libraries (.udl)

; 위에서 보았듯이 만들어진 .udl 파일들이 저장된 위치.

Plugin directory

; 플러그인들이 위치하는 디렉토리 설정

Location of API help file (.hlp or .chm)



7. Errors and warnings

Warn if not administrator

; 관리자 계정으로 실행하지 않았을 때 경고창을 띄운다. 참고로 디버거의 경우 애플리케이션과 마찬가지로 관리자 권한 유무에 따라 권한이 달라진다. 애초에 관리자 권한으로 실행되는 애플리케이션에 대한 디버깅(Attach 뿐만 아니라 Open도)이 불가능하기도 하며, 애플리케이션의 루틴이 그렇다면 관리자 권한 유무에 따라 분기가 달라질 수도 있다.

Restore all errors and warnings

Restore all actions



8. Appearance

8.1 Defaults

8.2 Startup

8.3 Fonts

8.4 Colours

8.5 Code highlighting

8.6 Text-to-speech



9. Miscellaneous





III. 결론

  아직 정리할 것들이 많이 남아있으므로 틀린 내용이나 오타, 추가하고 싶은 내용이 있다면 위의 이메일 주소로 피드백을 보낼 수 있다.




IV. 참고문헌

1. OllyDbg 프로그램

2. OllyDbg 2.01 Brief Help 문서



'악성코드 분석' 카테고리의 다른 글

윈도우의 드라이버 개발과 루트킷 그리고 AV  (0) 2017.04.23
간단한 패커 개발  (0) 2017.04.23
Yoda's Protector 분석  (0) 2017.04.23
패커들 분석  (5) 2017.04.23
윈도우의 자료형 정리  (1) 2017.04.23
Posted by SanseoLab

블로그 이미지
Malware Analyst
SanseoLab

태그목록

공지사항

Yesterday
Today
Total

달력

 « |  » 2024.4
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

최근에 올라온 글

최근에 달린 댓글

글 보관함