리버싱/책 스터디

Immunity Debugger , OllyDbg 1.10 기본기능

clcl 2022. 5. 3. 22:38

리버싱 입문 책을 공부하고 있다고 말하고 시작하겠다.

책에서 다루는 버전과 내가 사용하고 있는 올리디버거의 버전이 달라서 내가 현재 사용하고 있는 버전으로 최대한 설명하겠다.

 

 

1.디버거 개요

프레임: 현재 어떤 프로그램의 무슨 모듈을 디버깅하고 있는지 표시

메뉴 바: 디버거에서 제공하는 기능을 모두 담고있음

퀵 링크: 자주 사용되는 기능을 아이콘 형태로 제공. 분석에 필요한 기능 대부분 해결가능 

뷰 영역: 분석화면을 보여주는 영역

상태 바: 왼쪽에는 현재 디버거가 어떤 동작을 수행하는지 보여주고

(디버거는 DLL정보를 분석해서 udd파일로 저장하고 다음에 분석할때 재사용한다)

오른쪽에는 디버거의 실행상태를 보여준다. 

    디버깅하는 상태:Paused

    사용자의 입력을 기다리는 상태: Running

 

1.1 디버거 기본설정 

분석한 실행파일 정보를 udd 확장자를 가진 파일에 저장하고 있다.

실행파일과 udd파일을 같이 저장하게 되면 깔끔하지 않을 수 있으므로 따로 분리하면 좋다는 팁이다.

책에는 Options > Options..를 선택하면 뜬다고 돼있지만 버전이 달라서 그런지

내가 쓰는 버전에서는 Options>Appearance >Directories 에서 UDD 저장폴더를 별도로 지정할 수 있다.

 

2.뷰

다양한 정보에 접근해야 하므로 디버거에서는 뷰라는 개념을 도입해서 다양한 정보를 뷰로 나누었다.

 

2.1 CPU

실행파일을 메모리에 로딩하고 

프로세스로 만들어서 CPU가 동작을 수행하도록 명령하는 것이다.

CPU가 동작할 때는 기본적으로 메모리에 있는 정보를 레지스터로 가지고 와서 제어장치와 연산장치에서 이를 처리한다.

따라서 디버거로 소프트웨어의 동작을 분석하려면 CPU가 어떤 정보를 사용하고 어디에 정보를 저장하는지 살펴보는것이 가장중요하다.

디버거를 켰을 때 기본으로뜨는 화면이 CPU 뷰다.

 

CPU뷰에는 5가지 영역이 있다. 

 (1)코드영역 -실행파일의 어러 여셈블러 코드를 보여주는 영역이다.

왼쪽에는 기계어, 오른쪽에는 대응하는 어셈블러를 보여준다.

 

주소,기계어,어셈블러,주석으로 구성된다.

  • 주소는 절대주소다.  실행파일 상태에서는 상대주소를 가지고 있다가 메모리에 로드되면서 이미지 베이스에 더해져서 절대주소로 계산된다.
  • 기계어는 운영체제가 인식할 수 있는 연속적인 바이너리의 조합이다.바이너리를 16비트로 변환해서 헥사코드 형태로 보여주고 있다.
  • 어셈블러는 기계어를 사람이 알아볼 수 있는 매크로로 변환한 것이다. 각각 으미있는 바이너리의 조합을 영무심볼을 붙여서 화면에 보여준다. 영문 심볼은 일대일로 기계어로 바로 변환할 수 있다.
  • 주석은 어셈블러를 디버거가 분석해서 해석을 달아둔 것이다.
  • ㄴ>코드영역과 메모리 영역을 결합해서 해석할 때 :코드영역 기계어에 적힌 주소는 리틀엔디안 방식으로 적혀있고 사람이 이해하는 빅엔디안 형식으로 이를 읽은 것은 메모리에서 찾을 수 있다. 헥사코드와 일치하는 ASCII 문자가 들어있는 것을 확인할 수 있고 널문자 00이 나올 때까지 읽는다.

(2)힌트영역-상대주소와 아스키코드,16진수 등을 알기쉬운 형태로 표현해주는 영역이다.

 

코드만 가지고 의미를 해석하는것은 단순하지않은 작업이므로 디버거에서 우리가 해석하는 긴 과정을 자동화해서 힌트영역을 보여주고있다.

 

 (3)메모리 영역 - 기본적으로 PE 헤더에서 데이터 영역으로 지정된 부분을 보여준다.

대체로 코드영역 다음에 데이터 영역이 와서 코드영역과 데이터 영역의 주소를 살펴보면 연속적인 것을 확인 할 수 있다.

PE파일에 있는 섹션영역을 하나씩 보여준다.

기본적으로 코드영역 뒤에오는 데이터영역을 보여주고 다른섹션영역으로 넘어가려면 [Go to] > [Expression] 메뉴를 선택해서 주소를 입력하면 된다.

메모리영역은 'Address','Hex dump','ASCII' 영역으로 나누어진다

  • Address:메모리에 실제로 저장된 주소. 상대주소 +image base로 구할 수 있다.
  • Hex dump:바이너리 스트링을 16진수로 보기 쉽게 바꾸준다
  • ASCII: 16진수에 해당하는 아스키 코드값을 보여준다. 화면에서 보여주는 메세지 등을 이 영역에서 많이 발견할 수 있어서 리버싱과정에서 유용하게 사용됨
  • 문자열은 연속된 값으로 저장되고 맨마지막에 문자열의 끝을 의미하는 널 문자(00)가 저장된다

 

(4)레지스터 영역- CPU연산을 위해 메모리로부터 레지스터로 데이터를 가지고 오며 프로그램 흐름을 제어하기 위한 정보를 레지스터에 저장한다.

CPU는 여러프로세스가 공유하기 떄문에 하나의 프로세스에 할당된 시간이 끝나면 레지스터 정보를 메모리 특정영역에 복사한다.

우리가 디버거에서 보는 레지스터 영역은 메모리에 복사된 물리적인 레지스터 정보다.

 

리버싱 과정에서 많이 사용하는 레지스터는 EAX, EBP, ESP, EIP, zero flag 레지스터 가 있다

EAX레지스터는 연산의 결과를 저장하고 있고 , EBP레지스터는 프레임포인터를 저장하고 있고, ESP레지스터는 스택의 맨위를 가리키고 있고, EIP레지스터는 다음에 실행할 명령어 주소를 저장하고 있다

제로 플래그는 비교연산의 결과가 저장되어 JMP명령어의 기준값으로 사용된다.

 

 (5)스택영역- 메모리에 위치한 스택을 보여주고 있다.

메인함수에서 서브루틴으로 들어갈때 ,돌아올때 필요한 정보 등이 스택에 저장된다

 

스택은 서브루틴호출구조에서 중요한 역할을 담당한다.

스택의 현재위치를 가리키는 주소는 ESP 레지스터에 저장된다

  • 1)함수 호출에 필요한 인수를 전달한다.인수는 순서대로 스택에 PUSH된다.
  • 2)서브투린을 호출한다. 서브루틴이 호출되면 복귀주소를 스택에 PUSH한다.(서브루틴의 동작이 완료되면 원래 루틴으로 돌아올 수 있는 위치를 가리키고 있다)
  • 3) 서브루틴을 호출하기 전에 사용했던 EBP 레지스터를 PUSH한다.원래 루틴으로 돌아왔을 때 스택프레임의 시작 주소를 저장하는 레지스터를 백업하기 위해 사용한다

 

 

2.2 메모리 맵 

디버거 창 퀵링크에서 M을 클릭하면 뜬다.

메모리 영역의 전체적인 윤곽을 보여준다. 스택 구조, 히프메모리,현재 PE파일이 메모리에 로딩된 주소영역을 알 수 있다.PE파일이 사용하는 외부 모듈이 메모리 어디에 로딩되었는지도 확인할 수 있다.

 

 

2.3 실행 모듈

디버거의 퀵링크에서 e를 클릭하면 뜬다.

프로그램에서 사용ㅎ는 실행모듈의 세부정보를 볼 수 있다.

분석대상인 프로그램도 하나의 실행파일로 간주한다.

 

 

2.4 콜 스택

디버거의 퀵링크에서 K를 클릭하면 뜬다

콜스택은 서브루틴 호출구조를 보여준다. 서브루틴을 어디서 호출했고, 해당서브루틴의 스택베이스는 어디인지에 대한 정보를 자세하게 보여준다.

stack,data에는 스택에 있는 내용을 그대로 보여준다. Procedure에는 호출되는 서브루틴의 이름이 들어있다.

Called From에는 서브루틴을 호출하는 주소가 들어있고 Frame에는 스택프레임을 구성하는 베이스 주소가 들어있다.

 

 

 

3.브레이크포인트

 1)소프트웨어 브레이크포인트

브레이크포인트를 설정한 명령어의 맨앞에 있는 1바이트가 CC(INT3)로 대체된다.

프로세스가 명령어를 실행하다가 명령어 맨앞에 있는 바이트가 CC로 되어있으면 인터럽트를 발생시킨다. 소프트웨어 브레이크 포인트는 실행동작에 대해서만 설정할 수있다.

 

하지만 디버거는 실제로 명령어 맨앞의 바이트를 변경하는 것이 아니라 소프트웨어 브레이크 포인트에 대한 정보를 udd파일에 기록한다.

디버거가 udd파일에 기록된 주소를 실행하면 디버깅을 잠시 멈추는 것이다.

즉,올리디버거는 소프트웨어 브레이크 포인트의 개념을 차용해서 디버깅에 활용하는 것이다.

리버서가 특정코드에 브레이크 포인트를 설정하는 이유는 프로그램이 멈춘 시점에 레지스터와 스택상태를 살펴보거나 그 코드 주변이 중요하기 때문에 분석을 위해 코드의 실행을 잠시 정지할 필요가 있기때문이다.

 

 2)하드웨어 브레이크포인트

명령어가 바뀌는 것이 아니라 프로세서에서 디버거를 위해 제공하는 레지스터인 디버거 레지스터에 브레이크 포인트를 설정하고 관련 주소를 입력한다.

32비트 아키텍쳐에서는 8개의 디버거 레지스터가 제공되는데 이 중 4개의 레지스터가 브레이크 포인트를 위해 사용된다.즉 4개의 하드웨어 브레이크 포인트를 설정할 수 있다.

하드웨어 브레이크 포인트의 장점은 명령어 뿐아니라 메모리에도 브레이크 포인트 설정할 수 있다는 것이다.

실행되지 않는 메모리에 저장된 데이터에도 브레이크 포인트를 설정할 수 있다.

 

 

5.코드영역 메뉴

5.1 수정

마우스 오른쪽 클릭 > Binary  에서 바이너리 copy paste , edit 이 있다. 바이너리 카피는 바이너리만 복사할 수 있다. (페이스트는 바이너리를 붙여넣을 수 있다)

바이너리 에딧은 코드를 직접 수정할 때 많이 사용된다.

책과는 버전이 달라서 그런지 주소 바이너리 어셈블러 전체 복사하는 부분은 찾지 못했다.

Copy to executable 기능은 수정된 코드를 실행파일로 저장하는 역할을 한다.

 

5.2 주석달기 

[Comments]는 주석을 다는 부분이다. 리버싱과정에서 분석한 내용을 코드 옆에 기록해두면 편리하다.

 

5.3 어셈블

어셈블 기능은 디버거 화면에서 어셈블러 코드를 직접 입력할 수 있게해준다.

PE파일을 수정하거나 테스트를 위해 어셈블러 코드를 입력할 때 많이 사용한다.

이렇게 어셈블러 코드를 직접입력하고 싶은 부분을 클릭해서 마우스 오른쪽 >Assemble을 누르면 수정할 수 있다.

 

5.4 New origin here 메뉴

다음에 실행할 명령어 주소를 현재 선택된 명령어 주소로 강제적으로 변경하는 기능을 제공한다

 

5.5 Follow in Dump 메뉴 

immediate constant는 명령어에 인수로 오는 메모리 주소로 이동하는 것이다.

selection은 선택된 명령어가 저장된 주소로 바로 이동하는 것이다.

selection 을 했을 때 이동하는 위치이다.

immediate constant를 했을 때 이동하는 위치이다.

 

5.6 이동하기 

Origin은 EIP 레지스터에 들어있는 주소로 바로 이동할 수 있다(다음 실행할 주소로 분석커서를 바로 옮길 수 있다는것)

Expression은 주소를 검색해서 해당위치로 바로 이동하는 기능을 제공한다

Previous는 이전에 분서간 코드를 다시보고싶을때 사용한다. 명령어 한줄 뒤로가는 것이 아니라 내가 분석했던 지점만 뒤로 거슬러 올라간다.

Next는 Previous 기능을 사용해서 뒤로이동했던 분석커서를 다시 앞으로 옮길 때 사용한다

올리디버거
이뮤니티 디버거

5.7 Search for 메뉴

  • [Names] :PE파일에 있는 헤더 이름과 IAT 테이블에 있는 함수와 DLL이름을 보여준다
  • [Binary string]: 바이너리 코드를 검색할 수 있는 기능을 제공한다 .
  • [All intermodular calls]:프로그램에서 사용하는 외부 모듈을 호출하는 코드를 직접보여준다.
  • [All referenced text strings] : 프로그램에서 사용하는 문자열을 보여준다. 오류메시지나 레이블 등에 나오는 문자를 검색할 수 있다.

 

5.8 참조 위치 찾기 

현재 선택한 명령어를 호출하는 부분을 찾는다.

[Find references to] > [Selected command] 해당 함수를 호출하는 코드 목록을 볼 수 있다.

 

 

 

 

 



 

 

 

'리버싱 > 책 스터디' 카테고리의 다른 글

abex crackme 4번째 예제  (0) 2022.05.06
abex crackme 3번째 예제  (0) 2022.05.06
abex crackme 1번째 예제 풀이  (0) 2022.04.03
어셈블러  (0) 2022.04.03
리버싱 기초지식  (0) 2022.03.27