Chapter 49 IA-32 Instruction
Instruction이란 쉽게 말해서 CPU가 알아들을 수 있는 '기계어(Machine Language)'이다. IA-32 Instruction은 IA-32(Intel Architecture 32비트) 계열의 CPU에서 사용되는 Instruction을 말하는 것이다.
다음은 리버싱에서 자주 사용되는 용어이다.
C/C++(또는 어셈블리) 언어를 이용하여 PE(Portable Executable) 파일을 생성하면 소스코드는 기계어를 변환된다. 리버서는 이러한 기계어를 해석하여 동작원리를 파악하는 사람이다. 하지만 2진수로 표현된 기계어를 사람이 그냥 보는 것은 너무 힘든 작업이다. 그래서 보통 16진수로 변환해서 본다. 16진수로 보면 가독성은 좋아지지만, 아직 사람이 코드를 인식하기에는 무리가 있다. 그래서 최종적으로 (디버거에 탑재된) Disassembler를 이용하여 기계어를 디스어셈블리 코드로 변환한다.
다음은 여태 익히 보아오던 Ollydbg의 화면이다. Ollydbg에는 IA-32용 Disassembler가 탑재 되어있다.
위 그림을 보면 한줄에 하나의 명령어(Instruction)가 표시되어 있다. (A) 영역이 기계어로 표시된 IA-32 Instruction이다. 그리고 그에 해당하는 각각의 디스어셈블리 코드가 (B)에 나타나있다. 메모리(혹은 파일)에서는 실제로 (C)처럼 되어있다.
이런식으로 디버거에 탑재된 Disassembler는 (C) 영역의 Hex code를 해석하여 Instruction 단위로 쪼개서 표시(A)하고, 각 Instruction별로 디스어셈블리 코드(B)를 표시한다. 사람 눈으로 보기에는 C<A<B 순으로 보기 좋으며, 리버서들은 보통 (B) 형태의 디스어셈블리 코드를 보면서 분석을 수행한다.
Decompiler는 기본적으로 Disassembler와 같은 개념이다. 다만 Disassembler는 무조건 디스어셈블리 코드로 변환 해 주는데 반해, Decompiler는 원본 소스코드 형태로 변환 시켜주는 차이가 있다.(해당 언어제 맞는 Decompiler를 사용해야함). 물론 원본 소스코드와는 차이가 있으나 기술이 발전하면서 그 차이가 좁혀지고 있다.
위는 IDA Pro의 Hex-Rays Decompiler 플러그인을 사용하여 기계어 코드를 C언어로 해석한 것이다. 기계어 코드가 C언어 소스코드로 해석 되었음을 알 수 있다.
IA-32 Instruction 포맷은 다음과 같다.
위 그림처럼 총 6개의 항목으로 구성 되어있다. 여기서 Opcode 항목은 반드시 존재해야하며, 나머지 항목은 옵션이다. 이제 위 6가지 항목에 대하여 간단히 알아 볼 것이다.
1.Instruction Prefixes
Instruction Prefixes는 옵션 항목으로, 뒤에 특정한 Opcode가 나올 때 사용되어 Opcede의 의미를 보조하는 역할을 합니다. 간단한 예는 다음과 같다.
Prefix 항목은 1바이트 크기를 가진다.
2.Opcode
Opcode는 필수 항목이며 실제적인 명령어를 나타낸다.
Opcode는 1~3바이트 크기를 가진다. 일반적인 응용프로그램 디버깅에서 주로 1바이트 크기의 Opcode가 대부분이고 가끔 2바이트 크기의 Opcode들이 있다. 3바이트 크기의 Opcode도 있으나 접하는 경우가 거의 없다. Opcode는 보통 Operand를 갖는 경우가 많다. Operand의 종류는 Register, Memory Address, Constant 이다. 이러한 Opcode의 Operand를 결정하기 위해 보통 ModR/M과 SIB가 뒤따라오는 경우가 있다. Opcode는 그 종류가 매우 많이 때문에 일반적으로는 Intel Manual의 Opcode Map을 보면서 해석을 해야 한다.
3.ModR/M
ModR/M은 옵션 항목으로, 주로 Opcode를 도와서 Operand를 설명(Operand의 개수, 종류[Registers, Address, Contant])하는 수단으로 사용된다.
ModR/M은 1바이트 크기를 가지며 다음 그림과 같이 비트 단위로 분리되어 사용된다.
4.SIB
SIB(Scale-Index-Base)는 옵션 항목으로, ModR/M을 보조할 때 사용된다. Opcode의 Operand가 Memory Address인 경우 ModR/M과 함께 사용된다.
SIB는 1바이트 크기를 가지며 ModR/M과 같이 비트 단위로 분리되어 사용된다.
5. Displacement
Displacement는 옵션 항목으로, Opcode의 Operand가 Memory Address인 경우 Displacement(변위)를 나타낼 때 사용된다.
Displacement의 크기는 1,2,4바이트로 다양하다.
6.Immediate
Immediate는 옵션항목으로, Opcode의 Operand가 Constant인 경우에 그 Constant를 Immediate라고 말한다.
Immediate의 크기는 1,2,4바이트로 다양하다.
이제 본격적으로 바이너리 코드를 어셈블리로 해석하는 실습을 할 것이다. 실습에 앞서 바이너리 코드를 어셈블리로 해석하기 위해서는 IA-32 Instruction에 대한 정확한 이해가 필요하다. IA-32에 대한 설명은 제조사인 Intel에서 제공한 공식 매뉴얼에 자세히 설명되어있다.
http://www.intel.com/products/processor/manuals
위 링크로 접속하여 아래 두 파일을 다운 받으면 된다.
Intel@ 64 and IA-32 Architectures Software Developer’ s Manuals Volume 2A.pdf
Intel@ 64 and IA-32 Architectures Software Developer’ s Manuals Volume 2B.pdf
이제 본격적으로 IA-32 Instruction을 해석 하는 방법에 대해 학습 할 것이다.
1.Opcode Map
첫 실습 예제로 1바이트 Opcode를 골랐다.
41 INC ECX
앞에서 다운 받으라고 한 Opcode 매뉴얼(혹은 Intel Manual Vol. 2B)의 'Table A-2. One-byte Opcode Map'을 보면 된다.
Instruction을 해석 할 대 가장 먼저 확인해야 할 것이 바로 Table A-2 One-byte Opcode Map이다. 찾으려 하는 Opcode 41을 4와 1로 쪼갠 후 Opcode Map에서 각각 행과 열로 하여 찾으면 된다. 이 경우 명령어는 INC이며, Operand는 ECX로 고정된다.(REX.B는 64비트 전용이므로 무시한다.) 따라서 Instruction 41은 INC ECX 명령어를 의미한다. 이것을 위에서 설명했던 IA-32 Instruction Format으로 표시하면 다음과 같다.
2. Operand
이번에는 Operand의 형태를 파악하는 연습을 해 볼 것이다.
68 A0B44000 PUSH 0040B4A0
앞에서와 같은 방법으로 Instruction의 첫바이트 68을 Table A-2 Opcode Map에서 찾는다.
위 그림을 보면 Opcode 68은 PUSH Iz라고 표시되어 있다. 즉 Operand를 하나 가지는 PUSH 명령어이다.
Operand 타입을 나타내는 Iz의 의미를 알아야 정확한 해석이 가능하다. 대문자 I는 Addressing Method를 의미하고 소문자 z는 Operand Type을 의미한다. 이들은 각각 앞에서 만든 Opcode 매뉴얼의 A.2.1 Codes for Addressing Method과 A.2.2 Codes for Operand Type에 설명되어있다. 다음은 자주 사용되는 Addressing Method를 정리한 것이다.
Addressing Method를 의미하는 대문자 I는 Immediate이다. 상수의 크기를 알려면 Operand Type을 참고해야 한다. 다음은 자주 사용되는 Operand Type을 정리 한 것이다.
Operand Type을 의미하는 소문자 z는 32bit 모드에서 DWORD(32bit) 크기이다. 따라서 이 모든 정보를 종합하면 Opcode 68은 PUSH Iz 명령어 형식이고, Operand 형식을 나타내는 Iz 기호는 4바이트(32비트) 상수를 의미하므로 68 뒤의 4바이트(0040B440)를 더 읽어서 최종적으로 PUSH 0040B4A0으로 해석이 된다. IA-32 Instruction Format으로 표시하면 다음과 같다.
'리버싱핵심원리' 카테고리의 다른 글
Reverse Engineering Chap 48 (0) | 2016.02.03 |
---|---|
Reverse Engineering Chap 47 (0) | 2016.02.03 |
Reverse Engineering Chap 46 (0) | 2016.02.03 |
Reverse Engineering Chap 50-51 (0) | 2016.02.03 |
Reverse Engineering Chap 21-22 (0) | 2016.02.03 |