study/리버싱

3.1 바이트 오더링

Having 2021. 12. 17.

바이트 오더링은 데이터를 저장하는 방식이다. 바이트 오더링 방식에는 빅 엔디언(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로 저장된 것을 볼 수 있다. 

 

"리버싱 핵심원리" 의 내용을 담고 있습니다. 

댓글