2023. 3. 4. 19:08ㆍ리버스 엔지니어링/1부) 기초 리버싱

리버싱 핵심원리
2022년 1월부터 이 책을 공부하면서 정리를 목적으로 이 글을 작성하게 되었습니다.
이 책에서는 Ollydbg를 통해 디버그를 하며 실습하지만,
IDA를 통해 이번 공부를 실습해볼 생각입니다.
IDA란?

Hex-rays사의 IDA는 디스어셈블러(바이너리>>어셈블리어)와 디버깅 기능을 지원하는 프로그램입니다. 다른 디버거에 비해 기능이 다양하고 난독화 코드에도 강해 현시점 가장 성능이 좋은 디버거입니다. 단, Pro버전은 비용이 비싸기 때문에 IDA freeware을 통해 디버그를 해보도록 하겠습니다.
IDA에서 주로 사용했던 기능들 위주로 설명하겠습니다.
1. 기본화면

IDA를 실행하고 파일을 열면 해당 화면이 나옵니다. 화면 중앙의 창은 어셈블리 코드를 그래픽으로 보여줌으로써 코드의 흐름을 전반적으로 이해하기 쉽게 보여줍니다. 왼쪽의 창은 해당 프로그램 내 함수를 어셈블리 코드로 보여줍니다.
해당 어셈블리 코드의 주소값이 알고싶다면 해당 코드에 space 키를 누르면 됩니다.

2. Pseudo Code 변환
IDA에서 제공하는 기능 중에는 어셈블리 코드를 Pseudo 코드로 변환 시켜주는 디컴파일 기능이 있습니다.
F5를 누르면 어셈블리 코드를 Pseudo 코드로 변환시켜줍니다.

3. 검색하기
Alt + t 를 통해 어셈블리어 구문이나 문자열을 찾을 수 있다.

Ctrl + l 을 사용해 이름을 검색하여 사용한 API나 함수 이름을 찾을 수 있다

검색하는 기능은 디버깅 과정에서 크게 쓰지는 않았던 것 같다.
4. Cross reference 및 Step Into
함수나 변수가 사용되는 영역을 재참조하여 볼 수 있다

함수의 내부 구조를 알고 싶으면 해당 함수를 더블클릭
5. 디버깅
디버깅 이전에 BP(Break Point)를 설정하면 디버깅 중에 BP를 만났을 때부터 디버깅을 중지한다.
커서가 가리키는 라인에 F2를 누르면 된다.

F9: 디버깅
F8: Step over(코드 한 줄 실행, 함수 호출 시 건너뛰고 다음 명령어로 이동)
F7: Step Into(코드 한 줄 실행, 함수 호출 시 건너뛰지 않고 내부 함수로 이동)
6. Code Patch
바이너리 코드를 수정하는 행위, 패치를 하면 기본 파일에는 패치되지 않는다.
Edit >> Patch program >> Change byte

IDA를 통해 디버그시 어셈블리 코드뿐만 아니라 레지스터 값이나 스택 프레임 내 스택의 값을 볼 수 있습니다.
또한 메모리에 저장되어 있는 값을 볼 수 있는데요, 이 때 값들이 역순으로 저장되어 있는 걸 알 수 있습니다.
리틀 엔디언
데이터를 저장할 때 Intel x86 CPU는 리틀 엔디언 방식으로 데이터를 저장한다.
리틀 엔디언: 데이터를 메모리에 저장할 때 뒤에서부터 저장하는 방식
빅 엔디언: 데이터를 메모리에 저장할 때 앞에서부터 저장하는 방식
Intel x86 CPU에서는 리틀 엔디언을 사용하기 때문에 일반적인 사용자 PC에서는 리틀 엔디언을 사용한다.
실습
실습에 사용할 코드는 다음 깃허브 링크를 사용하면 된다.
https://github.com/reversecore/book
GitHub - reversecore/book: 리버싱 핵심원리 - 소스 코드 및 실습 예제
리버싱 핵심원리 - 소스 코드 및 실습 예제. Contribute to reversecore/book development by creating an account on GitHub.
github.com
LittleEndian.cpp

cmd에 >> gcc -o LittleEndian LittleEndian.cpp
LittleEndian.exe 파일 생성 후 IDA로 실행
IDA View

EAX 레지스터에는 12345678으로 저장되지만 메모리에 저장될때 78 56 34 12로 저장되는 걸 알 수 있다.
레지스터 (Register)
레지스터란?
CPU가 빠른 연산을 하기 위해서 사용하는 메모리로써 일시적으로 데이터를 저장한다. CPU와 레지스터는 다른 메모리들 보다 가깝기 때문에 RAM에서 데이터를 엑세스 하는것 보다 빠르다.
레지스터는 다양한 데이터를 저장하는데, 저장하는 데이터의 종류에 따라 기능이 달라진다.
먼저 IA-32에서 사용하는 레지스터를 알아본다. (x86 CPU에서 사용하는 레지스터)
리버싱 과정에서 가장 많이 보게 되는 Basic program execution register는 4개의 그룹으로 나뉘어 진다.
Basic program execution register
- 범용 레지스터
- 세그먼트 레지스터
- 프로그램 상태와 컨트롤 레지스터
- 명령어 포인터

1) 범용 레지스터(General Purpose Registers) 32bit * 8개
이름처럼 범용적으로 사용하는 레지스터로써 EAX, EBX, ECX, EDX 은 데이터를 받아 ALU(산술논리장치)를 통해 연산과정을 거쳐 메모리에 저장되는 용도로 많이 사용된다. 특히 ECX는 반복문에서 EAX는 리턴값으로써 많이 사용된다.
EBP, ESP는 스택 메모리 주소 포인터로 사용된다. EBP, ESP값을 조작함으로써 스택 프레임을 만들기도 한다.
EDI, ESI는 메모리 복사에 사용된다.

IA-32에서는 32bit 레지스터를 사용하지만
이전 IA-16에서는 16bit를 사용했기 때문에
하위호환을 위해 레지스터는 몇가지 구획으로 나눈다.
예를들어 EAX는 32bit , AX는 하위 16it, AH는 상위 8bit, AL은 하위 8bit를 사용한다.
데이터로 DWORD "abcd" (61626364)를 저장하면
EAX는 61626364 AX는 6364
AH는 63 AL은 64를 저장한다.
2) 세그먼트 레지스터(Segment Register) 16bit * 6개
IA-32에서 메모리를 조각내어 조각마다 시작 주소, 범위, 접근 권한 등을 부여해서 메모리를 보호.
또한 각 세그먼트 레지스터는 SDT(Segment Desciptor Table)의 index를 가진다.
CS(Code Segment): 코드 세그먼트의 시작 주소를 포함한다. IP 레지스터 값을 더하면 가져올 명령어의 주소값이 된다.
SS(Stack Segment): 스택 세그먼트의 시작 주소를 저장한다. 시작 주소에 ESP값을 더하면 현재 스택의 참조위치가 된다.
DS(Data Segment): 데이터 세그먼트의 시작주소를 포함한다. 명령어 offset값을 더하면 특정 바이트 위치가 참조된다.
ES(Extra Segment), FS(Data Segment), GS(Data Segment): 추가적인 데이터 세그먼트를 포함한다.

3) 프로그램 상태와 컨트롤 레지스터(Program Status and Control Register) 32bit *1개
EFLAGS(Flag Register)

이 중에서 디버깅에 필요한 3가지 플래그는 ZF, OF, CF이다
ZF: 연산 후 결과가 0이면 ZF가 1로 세팅된다. CMP 명령어와 같이 값을 비교하는 명령어에서 사용
OF: 부호 있는 수가 오버플로 발생 시 1로 세팅된다.
CF: 부호 없는 수가 오버플로 발생 시 1로 세팅된다.
4) 명령어 포인터 (Instruction Pointer)
IA-32에서는 EIP로 되어있다. CPU가 처리해야 하는 명령어의 주소를 가리키는 레지스터이다.
CS의 코드 세그먼트 시작주소와 EIP값을 더하면 메모리에서 참조할 명령어의 주소값이 된다.
명령어를 처리하면 처리한 명령어의 길이만큼 늘어난다.
x64 프로세서에서의 레지스터
x86에서는 레지스터의 이름이 E로 시작됐다면, x64에서는 R로 시작합니다. 당연히 레지스터의 용량도 64비트로
늘어나므로 하위호환을 위해 32비트 레지스터는 64비트 레지스터의 하위 32bit를 차지합니다.
또한 R8 ~ R15 까지 범용 레지스터가 추가되었습니다.

자세한 내용은 5부 64비트 & Windows Kernel 6 에서 설명하겠습니다.
참고서적
이승원, 「리버싱 핵심원리」, 인사이트, 2012, 13p ~ 62p
http://www.yes24.com/Product/Goods/7529742
리버싱 핵심 원리 - YES24
리버서라면 꼭 알아야 할 핵심 원리를 모두 담았다리버싱이란 프로그램의 내부를 깊이 들여다보고 조작할 수 있는 기법이다. 이는 우리가 흔히 사용하는 상용 프로그램 등에도 가능하기 때문에
www.yes24.com
'리버스 엔지니어링 > 1부) 기초 리버싱' 카테고리의 다른 글
[rev] 리버싱 핵심원리 1부) 기초 리버싱 8장~11장 (2) | 2023.03.06 |
---|---|
[rev] 리버싱 핵심원리 1부) 기초 리버싱 5장~7장 (0) | 2023.03.05 |