본문 바로가기
파이썬 스터디 과제/파이썬 해킹 프로그래밍

2장-디버거

by laoching 2015. 1. 12.
728x90
반응형

디버거

디버거는 해커에게 매우 중요함

디버거는 실행 중인 프로세스를 트레이스하거나 동적 분석을 한다.

동적 분석은 악성 코드 조사나 퍼저 적용에 있어 필수적인 요소다.

디버거는 프로세스를 실행시키거나 일시 정지시킬 수 있으며, 브레이크 포인트를 설정하거나 레지스터와 메모리 값을 수정할 수 있다.

디버거는 두 가지 종류로 나뉜다.

화이트박스 디버거 : 대부분의 개발 플랫폼이나 IDE는 개발자가 자신이 작성한 소스코드를 트레이스 할 수 있게 디버거를 자체적으로 내장하고 있는데 이를 화이트 박스 디버거라 부른다.

개발 과정에서 유용하게 사용된다고 한다.

블랙박스 디버거 : 소스코드가 없는 환경에서 사용되는 디버거를 블랙박스 디버거라 부른다.

어셈블리 코드만을 알 수 있을때에 사용되는 디버거란다. 숙련된 리버스 엔지니어링 고수에게는 쉽겠구나...

또 블랙박스 디버거는 두가지 모드로 나뉜다.

유저 모드 디버거 // 커널 모드 디버거

유저모드는 사용자 애플리케이션이 동작하는 프로세서 모드다. 최소한의 특권을 갖는다.

커널모든는 최고수준의 권한을 갖는다. 운영체제의 핵심 부분이 동작하는 모드란다.


범용 CPU 레지스터

x86 명령 셋에서 CPU는 8개의 범용 레지스터를 사용함
EAX, EDX, ECX, ESI, EBP, ESP, EBX

EAX 레지스터(accumulator register라고도 부름)
산술 연산을 수행하기 위해 사용되거나 함수의 리턴값을 전달하기 위해 사용
기본적인 연산을 EAX를 사용하게 설계됐다고 한다.

EAX에 저장된 값을 조사하면 호출한 함수의 성공 여부를 알 수 있다.
리턴값도 알 수 있다.

EDX 레지스터(data register)
EAX의 확장 개념 -> 복잡한 연산을 위해 데이터를 추가적으로 저장할 때 사용
범용 목적의 저장소로도 사용된다.
대부분 EAX 레지스터와 함께 연동해서 수행되는 연산에 사용됨

ECX 레지스터(count register)
반복적으로 수행되는 연산에 주로 사용
ECX는 값을 증가시키면서 세는 것이 아니라 감소시키면서 카운트를 센다.

데이터를 처리하는 반복문에서는 ESI레지스터와 EDI레지스터를 사용
ESI레지스터 source index를 나타내거나 입력 데이터의 스트림의 위치
EDI레지스터 destination index를 나타내거나 연산 결과가 저장되는 위치
[ESI : 읽기 | EDI : 쓰기]
인덱스 레지스터를 사용함으로써 프로그램의 실행 성능 향상!

ESP레지스터(stack pointer)
EBP레지스터(base pointer)
함수 호출과 스택 연산에 사용됨
파라미터가 스택에 push >> 리턴 주소가 스택에 push
ESP 레지스터는 스택의 가장 높은 위치를 가리킨다.
그래서 함수 호출 시 ESP 레지스터는 리턴 주소를 가리킨다.
EBP는 가장 낮은 위치를 가리킨다.

EBX 레지스터는 수가적인 저장소로 사용

EIP레지스터는 실행 중인 명령의 주소를 가리킨다.
CPU가 바이너리 코드를 실행시킴에 따라 EIP 레지스터는 CPU가 현재 어느 코드를
실행시키는 중인지 나타내기 위해 실행되는 코드의 주소를 갱신함


스택


스택은 디버거를 개발할 때 반드시 이해해야 하는 중요한 구조체
스택은 FILO(first in last out)구조
함수를 호출할때 파라미터를 스택에 push, 함수가 리턴할 때는 POP한다.
상위 메모리 주소에서 하위 메모리 주소 방향으로 커진다.



그림을 보면 스택은 매우 직관적이라는 것을 알 수 있다.


디버그 이벤트

이벤트가 발생할 때까지 계속적으로 루프를 돌면서 대기한다.

디버거가 반드시 처리해야 하는 일반적인 이벤트들

-브레이크 포인트

-메모리 충돌(메모리 접근 에러 또는 세그먼트 폴트라고 부른다.)

-디버깅되는 프로그램에 의해서 발생한 예외

운영체제가 디버거에 이벤트를 전달하는 방식은 모두 다르다.

스크립트 가능한 디버거의 장점은 특정 디버그 이벤트에 대한 해들러를 변경할 수 있다는것!!

예를 들면 버퍼 오버플로우로 인해 메모리 충돌 에러가 발생 했을때 스크립트 가능한 디버거를 이용해 자동으로 필요한 정볼르 수집하게하는 핸들러를 작성해 사용한다면 정말 편하고 좋을것이다!!


브레이크 포인트

실행 중인 디버깅 대상 프로세스를 멈추게 하려면 브레이크 포인트를 설정 해야 한다.

브레이크 포인트에 의해 프로세스가 일시 중지되면 알 수 있는점

-중지된 시점의 변수

-스택 파라미터

-특정 메모리 위치의 값들

브레이크 포인트의 세 가지 종류

-소프트 브레이크포인트

-하드웨어 브레이크포인트

-메모리 브레이크포인트

세 가지 모두 유사한 동작을 하지만 구현되는 방법은 완전 다르다.


소프트 브레이크포인트

명령을 실행하는 CPU를 일시 중지 시키는 데 사용됨

애플리케이션을 디버깅할 때 가장 흔하게 사용되는 형태의 브레이크포인트다.

한 바이트의 명령을 사용해 디버깅 대상 프로세스를 중지시킴

프로세스의 실행이 중지되면 디버거의 브레이크포인트 예외 핸들러가 제어권을 전달받음.

디버거는 특정 주소에 브레이크 포인터를 설정하라는 명령을 받음

해당 주소의 첫 뻔째 opcode바이트를 읽어 그것을 저장하고 그 위치에 cc 바이트를 써 넣음

cc opcode로 인해 CPU가 브레이크포인트나 INT 3 이벤트를 발생시키면 디버거는 그 이벤트를 전달 받는다.

디버거는 EIP 레지스터가 자신이 이전에 설정한 브레이크포인트 주소를 가리키고 있는지 확인한다.

EIP레지스터가 가리키는 주소가 디버거 내부의 브레이크포인트 리스트에 존재하면 디버거는 실행이 다시 재개될 때 올바르게 실행되게 하기 위해 이전에 저장해 두었던 원래의 opcode 바이트를 해당 주소 위치에 써 넣는다.

위 그림이 자세히 보여준다.

소프트 브레이크포인트는 두 가지 종류가 있다.

- 일회성 브레이크포인트 - 한번 이벤트가 발생하면 리스트에서 브레이크포인트 정보 제거

- 지속적인 브레이크포인트 - 브레이크포인트 발생 후 CPU가 원래의 opcode를 실행한 다음에 다시 브레이크포인트 설정을 수행하는 것이다.

소프트 브레이크의 단점

메모리 상의 실행 바이너리의 바이트를 변경하기 때문에 CRC(cyclic redundancy check)체크섬 값이 변경되느나는 것이다.

CRC는 데이터가 변경됐는지 확인하기 위해 사용되는 방법이다.

CRC는 특정 범위의 데이터 영역으로 부터 그것의 해시 값을 산출한다.

해시값?? => 데이터를 짧게 나타내는 것(정확한지는 모르겠다...)

그리고 데이터가 변경됐는지 확인 하기 위해 해당 데이터 영역의 원래 CRC 체크섬 값과 비교한다.

체크섬 값이 서로 다르다 => 데이터가 변경되었다!!

하지만 소프트 브레이크포인트에는 한계점이 있다. 그건 악성코드의 행위만 동적 분석 할 수 있다. 이 점을 극복하려면 하드웨어 브레이크 포인트를 사용해야 한다.


하드웨어 브레이크포인트

설정할 브레이크포인트의 개수가 적을 때

디버깅할 소프트웨어의 코드가 변경되면 안될 때

아주 유용하게 사용된다.

디버그 레지스터라고 불리는 특별한 레지스터를 이용한다.

디버그 레지스터 8개중 DR7은 하드웨어 브레이크포인트의 스위치로 사용된다.

DR7의 특정 값을 설정하면 다음과 같은 조건의 브레이크포인트를 만들어낼 수 있다.

- 지정된 주소의 명령이 실행될 때

- 데이터가 어느 주소에 써질 때

- 어느 주소에 대한 읽기 또는 쓰기 작업이 수행될 때

위의 그림은 DR7 레지스터의 각 필드가 하드웨어 브레이크포인트의 종류, 길이, 주소와 어떻게 연관되는지 보여준다.

0-7비트는 설정된 브레이크포인트에 대한 on/off 스위치 역할을 수행한다.

0-7비트의 L과 G 필드는 범위를 나타내는데, 각기 지역과 전역을 의미한다.

하드웨어 브레이크포인트의 제약

- 브레이크포인트를 설정할 수 있는 데이터의 최대 크기가 4바이트라는 점이다.

큰 메모리 영역에 대한 접근을 추적하려면 메모리 브레이크포인트를 사용하자!!


메모리 브레이크포인트

메모리 브레이크포인트는 사실 브레이크포인트가 아니랜다. 장난하는건가...

메모리 페이지는 운영체제가 처리하는 가장 작은 단위의 메모리 크기다.

메모리 페이지가 할당되면 그곳에 대한 접근 권한이 부여된다.

메모리 페이지에 부여되는 접근 권한은 밑과 같다.

- 페이지 실행 = 이 권한이 할당된 메모리 페이지는 실행시킬 수 있다. 하지만 데이터를 읽거나 쓰려고하면 접근 위반 예외가 발생한다.

- 페이지 읽기 = 프로세스는 이 권한이 할당된 메모리 내용을 읽을 수 있다. 하지만 데이터를쓰거나 실행시키려 하면 접근 위반 예외가 발생한다.

- 페이지 쓰기 = 프로세스가 해당 메모리 페이지에 데이터를 쓰는 것만 허용한다.

- 보호 페이지 = 이 권한이 할당된 페이지에 대해 어떤 종류의 접근이라도 발생하면 예외를 발생시킨다. 예외 발생후 페이지의 원래 상태로 복귀된다.

스택에서 힙을 분리해내거나 특정 메모리 영역이 어떤 범위 이상으로 커지는지 확인하는 데

특정 메모리 영역에 대한 접근이 발생할 때 프로세스를 중지시키고자 할 때 매우 유용하다.

메모리 브레이크포인트는 실행되는 어떤 코드도 변경하지 않기 때문에 소프트 브레이크포인트가 갖고 있는 코드 변경으로 인한 제약을 극복할 수 있다.





728x90
반응형

댓글