바이트 오더링은 데이터를 저장하는 방식이다. 바이트 오더링 방식에는 빅 엔디언(Big Endian)과 리틀 엔디언(Little Endian) 방식이 있다. 아래 예제를 확인해 보자.
BYTE b = 0x12;
WORD w = 0x1234;
DWORD dw = 0x12345678;
char str[] = "abc";
TYPE | Name | SIZE | 빅 엔디언 | 리틀 엔디언 |
BYTE | b | 1 | [12] | [12] |
WORD | w | 2 | [12][34] | [34][12] |
DWORD | dw | 4 | [12][34][56][78] | [78][56][34][12] |
char [] | str | 6 | [61][62][63][00] | [61][62][63][00] |
BYTE 타입인 b 변수를 저장하는 방법에는 차이가 없다. 그러나 2바이트 이상 저장하는 WORD, DWORD에는 차이가 생긴다. 보통 사람이 보는 방식인 빅 엔디언, 뒤집혀서 저장되는 리틀 엔디언을 확인할 수 있다. 그러나 str이 저장된 문자열을 보면 차이가 없는 것을 볼 수 있다. 그 이유는 문자열은 결국 char의 배열이기 때문에 바이트 하나씩 연결되어 저장된 것이다.
3.1.1 리틀 엔디언 & 빅 엔디언
빅 엔디언
빅 엔디언의 장점은 사람들이 보기에 직관적인 것이다. 빅 엔디언은 대형 UNIX 서버에 사용되는 RISC 계열의 CPU에서 많이 사용된다. 그리고 네트워크 프로토콜에 빅 엔디언이 사용된다. 이것이 중요한 이유는 x86 응용프로그램 개발자와 리버서가 개발에 사용된 데이터를 네트워크로 전송할 때 엔디언 타입을 변환하는 과정이 필요하기 때문이다
리틀 엔디언
Intel의 x86 CPU에서 리틀 엔디언 방식이 사용된다. "왜 굳이 역순으로 데이터를 저장하는 거야?" 라고 생각할 수 있다. 하지만 컴퓨터 입장에서 산술연산, 데이터의 타입 확장 및 축소에 더 효율적이기 때문이다.
3.1.2 OllyDbg에서 리틀 엔디언 확인
#include "windows.h"
BYTE b = 0x12;
WORD w = 0x1234;
DWORD dw = 0x12345678;
char str[] = "abcde";
int main(int argc, char *argv[])
{
byte = lb = b;
WORD lw = w;
DWORD ldw = dw;
char @lstr = str;
return 0;
}
위의 코드를 빌드하여 Olly Dbg로 디버깅을 하자. ("리버싱핵심원리" 저자의 깃헙에서 exe 파일을 받을 수 있음)
b는 40AC40, w는 40AC44, dw > 40AC48, str > 40AC4C 에 저장되어 있는 것을 볼 수 있다. [ctrl + G]를 눌러 데이터가 저장된 주소로 가보자.
40AC44를 확인해 보면 1234가 아닌 3412로 저장된 것을 볼 수 있다.
"리버싱 핵심원리" 의 내용을 담고 있습니다.
'study > 리버싱' 카테고리의 다른 글
2.5 "Hello World!" 문자열 패치 (0) | 2021.12.01 |
---|---|
2-2 HelloWorld.exe 디버깅 (0) | 2021.11.11 |
2-1. HelloWorld.exe 디버깅 (0) | 2021.11.06 |
정적 분석, 동적 분석, Source Code, Hex Code, Assembly Code (0) | 2021.11.05 |
1. 프로그램 실행 구조 (0) | 2021.03.16 |
댓글