Reverse Engineering Chap 3-6
Chapter 3 리틀 엔디언 표기법
3.1 바이트 오더링
- 컴퓨터 메모리에 저장하는 순서입니다.
-빅 엔디언과 리틀 엔디언
아래 코드는 4가지 자료형이 있습니다. 다른 엔디언 방식에 따라서 같은 데이터는 저장되는 방식이 다릅니다.
바이트 타입의 변수를 저장할 때는 두 방식의 차이가 없습니다. 하지만 2바이트 이상의 크기를 가진 자료형을 저장할 때부터 차이가 나타납니다. 빅 엔디언 방식은 정상적인 순서로 데이터를 저장하고 리틀 엔디언 방식은 역순으로 데이터를 저장합니다. 또한 문자열은 저장 방식에 상관없이 동일합니다.
예제 소스
이 코드를 빌드하고 생성한 파일을 디버깅합니다.
Main()함수의 주소는 401000입니다. 변수들의 주소는 40AC40, 40AC44, 40AC48, 40AC4C입니다.
데이터 창을 통해 이 메모리 영역으로 갑니다. 변수 w와 dw의 값이 리틀 엔디언 형식으로 저장된 것을 알 수 있습니다.
Chapter 4 IA_32 Register 기본 설명
4.1 IA-32의 Register
아래의 그림은 Basic program execution registers에 대해 나와 있습니다. 4가지의 그룹으로 나눌 수 있습니다.
- General Purpose Registers (32 비트 - 8개)
- Segment Registers (16 비트 - 6개)
- program Status and Control Register (32 비트 - 1개 )
- Instruction Pointer (32비트 - 1개)
4.1.1 General Purpose Registers(범용 레지스터)
General Purpose Registers는 범용적으로 사용되는 레지스터입니다. 데이터를 전송하고 임시 보존할 수 있습니다. 그리고 산술 연산을 할 수 있고 그 연산한 결과를 저장할 수 있습니다. IA-32에서 각각의 범용 레지스터의 크기는 32비트이고 주로 상수와 주소 등을 저장합니다.
위 4개의 레지스터는 주로 산술연산을 하는 것이고 상수와 변수 값을 저장할 때 사용됩니다. 그리고 ECX와 EAX는 특수한 용도가 있습니다. ECX는 반복문 병령어(loop)에서 반복 카운트(loop count)로 사용됩니다. EAX는 일반적으로 함수 리턴 값에 사용됩니다.
위 4개의 레지스터는 주로 메모리 주소를 저장하는 포인터로 사용됩니다. EPS는 스택 메모리 주소를 가리키고 EBP는 함수가 호출되었을 때의 ESP를 저장하고 함수가 리턴하기 전에 다시 ESP에 값을 되돌려 줍니다. 그리고 ESP와 EDI는 어떤 특정어들(LODS, STOS, REP MOVS 등)과 함께 사용되고 주로 메모리 복사에 사용됩니다.
4.1.2 Segment Register
IA-32 보호 모드에서 세그먼트는 메모리를 조각내서 각 조각마다 시작 주소, 범위, 접근 권한 등을 부여해서 메모리를 보호하는 기법입니다.
4.1.3 Program Status and Control Register(프로그램 상태와 컨트롤 레지스터)
이flag 레지스터는 32개의 비트가 있는데 각 비트를 전부 이해하는 것은 어려워서 먼저 애플리케이션 다버깅에 필요한 3가지flag에 대해서 잘 이해하면 됩니다.
- Zero Flag(ZF): 연산 명령 후에 결과 값이 0이 되면 ZF가 true로 세팅됩니디.
- Overflow Flag(OF): 부호 있는 수의 오버플로가 발생했을 때 true로 세팅됩니다. 그리고 MSB(Most significant Bit)가 변경되었을 때 true로 세팅됩니다.
- Carry Flag(CF): 부호 없는 수의 오버플로가 발생했을 때 true로 세팅됩니다.
4.1.4 Instruction Pointer(EIP)
EIP는 CPU가 처리할 명령어의 주소를 나타내는 레지스터입니다. CPU는 EPI에 저장된 메모리 주소의 명영어를 하나 처리하고 난 후 자동으로 그 명령어 길이만큼 EIP를 증가시킵니다.
4.1.4 Instruction Pointer(EIP)
EIP는 CPU가 처리할 명령어의 주소를 나타내는 레지스터입니다. CPU는 EPI에 저장된 메모리 주소의 명영어를 하나 처리하고 난 후 자동으로 그 명령어 길이만큼 EIP를 증가시킵니다.
Chapter 5 스택
5.1. 스택
스택은 다양한 용도가 있는데 주로 함수 내의 로컬 변수를 임시 저장하고 함수 호출 시 파라미터를 전달하고 복귀 주소를 저장할 때 자주 사용합니다. 그리고 스택은First in Last Out 구조가 있습니다. 프로세스에서 스택 포인터는 처음에 제일 아래에 있습니다. Push 명령을 통해서 Stack에 값이 추가되면 스택 포인터는 위에 움직입니다. 그리고 pop명령을 통해서 값이 제거되면 스택 포인트는 아래에 움직입니다.
5.2 스택 동작예제
아래의 그림은 스택 초기 상태이며 스택 포인터(ESP)의 값은 12FF8C입니다.
PUSH명령을 실행한 후 ESP의 값은 12FF88로 바구고 4바이트 줄어들었습니다.
POP명령을 실행한 후 ESP의 값은 다시 12FF88로 바구고 4바이트 증가했습니다.
이 예제를 통해 스택 포인터의 변화를 더 잘 이해할 수 있습니다.
Chapter 6 abex’ crackme #1 분석
먼저 파일을 실행합니다.
[확인]을 눌러서 ‘Error’ 메시지 박스가 나온다
이 파일을 디버깅하고 이런 코드를 볼 있습니다.
401026주소의 JE 명령어를 JMP명령어로 부꾸면 됩니다.
[확인]을 누르면 성공 메시지 박스 나올 수 있습니다.
.