어셈블리(레지스터 이해)
@ 어셈블리(레지스터 이해)
1. 어셈블리어
- 기계어가 사용하는 2진수/16진수 숫자들을 사람들이 이해할 수 있게 만든 언어이다.
- C 언어는 몇개 안되는 명령어로 프로그램을 제작하는 반면에, 어셈블리어는 같은 프로그램을 제작할 때 몇십줄 이상 코드를 사용한다.
2. 레지스터
- CPU에 존재하는 저장소(메모리, 변수 개념)이며, 작은 데이터를 임시로 저장할 때 사용한다.
- 실행 중인 명령어 제어, 산술 연산 처리, 메모리 주소 지정을 실시한다.
1) EAX(Extended Accumulator Register)
- 32bit
- 16bit 환경에서 AX라고 하며, 상위 8bit를 AH, 하위 8bit AL 이라고 한다.
- 산술 연산, 논리 연산을 수행할 때 사용한다.
- 함수의 리턴값이 저장되므로 함수 호출 성공/실패 여부를 확인할 수 있다.
2) EDX(Extended Data Register)
- 32bit
- 16bit 환경에서 DX라고 하며, 상위 8bit를 DH, 하위 8bit DL 이라고 한다.
- 산술 연산을 담당하며 연산 결과 값이 32bit가 초과할 경우 EAX 용량이 부족하기 때문에 추가적인
공간 할당을 담당한다.
- 나눗셈인 경우에는 몫은 EAX에 저장되고, 나머지값은 EDX에 저장한다.
- 또한, 일반 자료를 저장할 수 있으며, 각종 연산에 사용하는 변수 개념으로도 사용이 가능하다.
3) ECX(Extended Counter Register)
- 32bit
- 16bit 환경에서 CX라고 하며, 상위 8bit를 CH, 하위 8bit CL 이라고 한다.
- 반복문(for, while)을 사용할 경우 반복 카운트 값일 저장한다.
4) EBX(Extended Base Register)
- 32bit
- 16bit 환경에서 BX라고 하며, 상위 8bit를 CH, 하위 8bit BL 이라고 한다.
- 메모리 주소를 저정하거나, 공간이 필요한 경우 추가적으로 사용하는 여분의 레지스터이다.
5) ESI(Extended Source Index) & EDI(Extended Destination Index)
- 메모리의 한 영역(Source)에서 다른 영역(Destination)으로 데이터를 연속적으로 복사 할 때 사용한다.
- ESI는 데이터를 조작하거나, 복사할때 데이터의 출발지 주소가 저장되며, EDI는 목적지 주소가 저장된다.
6) ESP(Extended Stack Pointer)
- 현재 스택 영역에서 가장 낮은 주소를 저장하여, 스택의 끝 위치를 알려준다.
- 즉, 변수 선언시 지정되는 주소의 값이 저장되다.
7) EBP(Extended Base Pointer)
- 스택에서 함수의 시작 주소 값을 저장한다.
- 즉, 함수 선언시 지정되는 주소의 값이 저장된다.
8) EIP
- 다음 실행될 명령어가 있는 주소를 저장한다.
- 즉, EIP 안에 저장된 주소 값을 확인하여 다음 명령어를 확인할 수 있다.
3. 메모리 기본 구조
- Stack 영역 지역 변수 선언시 할당하는 메모리 영역
- Data 영역 전역 변수 및 정적 변수 선언시 할당하는 메모리 영역
- Heap 영역 동적 변수 선언시 할당하는 메모리 영역
- Code 영역 소스 코드가 저장되는 메모리 영역
4. 스택
- 스택에는 함수 호출과 관련 있는 지역 변수, 함수 파라미터, 리턴 주소가 저장된다.
- 스택은 함수 호출과 동시에 생성되고 함수 처리가 완료되면 소멸된다.
- 스택에 값이 저장될 때에는 높은 주소에서 낮은 주소로 저장되며, 나중에 저장된 값이 먼저 나가게되는
FILO(First In Last Out) 구조이다.
- 스택에 값이 저장되면 ESP는 현재 위치에서 낮은 주소 위치 값으로 이동되며, EBP는 변경되지 않는다.
5. 스택 프레임 구조
- 스택 프레임은 함수 프롤로그, 함수 본체, 함수 에필로그로 구성되어 있다.
1) 함수 프롤로그
- EBP를 스택에 저장하고 ESP를 EBP에 저장하여 동일선상에 있게하는 함수의 시작 과정이다.
00401000 /$ 55 PUSH EBP // 스택에 EBP를 저장한다.
00401001 |. 8BEC MOV EBP,ESP // ESP를 EBP로 대입한다.
2) 함수 본체
- 변수 선언을 위한 공간 확보, 파라미터 값을 레지스터에 복사, 산술 연산, 비교/분기, 리턴값 저장하는 동작을 실시한다.
- EBP 값은 변경되지 않으며 ESP 값만 낮은 주소 또는 높은 주소로 이동하기 때문에 안전하게 지역 변수 및 파라미터 값을 연결할 수 있다.
00401003 |. 83EC 0C SUB ESP,0C
00401006 |. C745 F4 06000>MOV DWORD PTR SS:[EBP-C],6
0040100D |. C745 F8 02000>MOV DWORD PTR SS:[EBP-8],2
00401014 |. 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
00401017 |. 0345 F8 ADD EAX,DWORD PTR SS:[EBP-8]
0040101A |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
0040101D |. 33C0 XOR EAX,EAX
3) 함수 에필로그
0040101F |. 8BE5 MOV ESP,EBP // EBP를 ESP에 대입한다.
00401021 |. 5D POP EBP // EBP를 스택에서 제거한다.
00401022 \. C3 RETN // 다음 실행 명령어로 복귀한다.
6. 데이터 메모리 저장 방식
1) 바이트 오더링
- 데이터를 메모리에 저장할 때 1byte 단위로 저장하는 방식이며, '빅 엔디언'과 '리틀 엔디언'이 있다.
2) 빅 엔디언
- 데이터를 메모리에 저장할 때 앞에서부터 순서대로 저장하는 방식이다.
- UNIX RISC 계열 CPU에서 사용하며, 네트워크 프로토콜에서 사용한다.
3) 리틀 엔디언
- 데이터를 메모리에 저장할 때 뒤에서부터 저장하는 방식이다.
- Inter CPU 계열에서 사용한다.
7. 리틀 엔디언 처리 방식
1) 리틀 엔디언 데이터 저장 방식
BYTE b = 0x12;
WORD w = 0x1234;
DWORD dw = 0x12345678;
char str[6] = "abcde";
type Name Size 빅 엔디언 리틀 엔디언
BYTE b 1bye 12 12
WORD w 2byte 12 34 34 12
DWORD dw 4byte 12 34 56 78 78 56 34 12
char str[6] 6byte 61 62 63 64 65 00 61 62 63 64 65 00
2) VB 2008을 이용하여 'little_endian' 파일을 제작한다.
- 파일 -> 새로 만들기 -> 프로젝트 -> 빈 프로젝트 -> 위치(04_테스트) & 이름(little_endian) -> 확인
- '소스 파일' 우클릭 -> 추가 -> 새 항목 -> 'C++ 파일(.cpp)' 선택 -> 이름(little_endian) -> 추가
#include
BYTE b = 0x12;
WORD w = 0x1234;
DWORD dw = 0x12345678;
char str[6] = "abcde";
int main(int argc, char * argv[]) {
BYTE lb = b;
WORD lw = w;
DWORD ldw = dw;
char *lstr = str;
}
- 파일 -> 모두 저장 -> VS2008 닫기
3) 최적화 컴파일을 실시한다.
C:\리버싱\04_테스트\little_endian\little_endian>cl little_endian.cpp /link /debug /opt:icf,ref
Microsoft (R) 32비트 C/C++ 최적화 컴파일러 버전 15.00.30729.01(80x86)
Copyright (c) Microsoft Corporation. All rights reserved.
little_endian.cpp
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:little_endian.exe
/debug
/opt:icf,ref
little_endian.obj
4) 'little_endian.exe' 파일 생성 확인
- C:\리버싱\04_테스트\little_endian\little_endian
5) 'little_endian.exe' 파일을 올리디버거로 오픈하여 메모리 덤프창을 확인한다.
0040A000 12 00 00 00 34 12 00 00 ...4..
0040A008 78 56 34 12 61 62 63 64 xV4abcd
0040A010 65 00 00 00 01 00 00 00 e......