1 Little Endian 실습
바이트 오더링의 방식에는 Big Endian과 Little Endian이 있다. Big Endian 데이터를 앞에서부터 순차적으로 저장하는 방식인 반면, Little Endian은 데이터를 저장할 때 역순으로 저장하는 방식이다. 하지만 str 문자열의 경우에는 바이트 오더링 방식에 관계없이 동일하게 앞에서부터 순차적으로 저장된다.
1. 위와 같은 소스코드의 실행파일을 Immunity Debugger에서 분석하였다.
2. 코드에서 main()함수를 call 하는 부분을 찾아 main() 함수의 시작점으로 이동하였다.
3. Dump window 부분을 보면 저장된 값이 Hex dump에 드러난다. 빨강색 부분은 BYTE b = 0x12;가 저장된 부분이다. 2byte 단위로 저장하므로 12 자체가 역순이 되는 것은 아니다.
주황색 부분은 WORD w = 0x1234;가 저장된 부분으로 [12][34]가 역순인 [34][12]로 나타난다. 노랑색은 DWORD dw = 0x12345678;가 저장된 부분으로 [12][34][56][78]이 2byte씩 묶여 역순인 [78][56][34][12]로 나타난다. 초록색은 char str[] = "abcde";가 저장된 부분으로 앞서 이야기했던 것 처럼 str 타입은 bin andian과 동일하게 저장되므로 아스키코드 값인 [61][62][63][64][65][00]가 그대로 저장된 것을 볼 수 있다.
2 CRACKME #1 실습
1. CRACKME는 어셈블리어로 작성된 파일로 첫 줄이 시작주소이고 간단하고 명확하게 작성된 코드이다. 첫 번째 메시지 MessageBoxA는 “make me think your HE is a CD-Rom”을 출력하는 것으로 0040100E에서 메시지박스 API를 call 하는 것을 볼 수 있다.
2. 00401018에서 GetDriveTypeA API를 CALL하고 EAX 레지스터의 값이 3으로 설정된다. INC ESI를 통해 ESI의 값이 0이 되고, DEC EAX를 통해 EAX 레지스터의 값이 2가 된다. 00401021과 00401022를 지나며 ESI 레지스터의 값은 최종적으로 2가 되고 00401023를 지나며 EAX 레지스터의 값은 1이 된다. 00401024에서 CMP를 통해 EAX, ESI 두 레지스터의 값을 비교하고 00401026에서 두 값이 같을 경우 0040103D로 이동하라고 명령한다 JE는 Jump if equal로 두 값이 같을 때 이동하는 명령어이다. 현재의 경우 EAX, ESI의 레지스터의 값이 각각 1, 2 이므로 동일하지 않다.
3. 두 레지스터의 값이 동일하지 않을 때 0040103D로 이동하게 하기 위해 00401026의 JE 명령어를 JNE로 수정했다. JNE는 Jump if not equal로 비교하는 두 값이 같지 않을 경우 해당 명령을 수행하는 것이다. 현재 두 값이 동일하지 않으므로 0040103D로 이동하게 된다. [강의 명령어는 JMP]
4. Copy to excutable로 저장하면 실행결과 첫 번째 메시지 박스 이후 두번째 메시지 박스를 건너뛰고 세번째 메시지 박스가 출력되는 것을 볼 수 있다.
3 PEfile 분석 실습
1. PEFile
Portable Excutable로 실행 가능한 파일을 뜻한다. PEFile을 생성하기 위해 비쥬얼 스튜디오에서 간단한 소스코드를 작성하였고 실행하여 PEFile.exe파일을 생성하였다.
2. 실행파일을 PEView로 열어 헤더 확인
3. IMAGE_DOS_HEADER
- e_magic: 4D 5A → PE 파일 구조
- e_Ifanew: 00 00 00 F0 → IMAGE_NT_HEADER 시작주소, 이 주소를 찾아가면 value에 PE가 뜸
4. MS-DOS Stub Program
MS-DOS Stub Program: Dos/window 프로그램인지를 확인할 수 있는 부분으로 value 창에 “This is program cannot be run in Dos mode” 내용을 출력한다.
5. IMAGE_NT_HEADERS
1) signature: 4byte 공간 PE구조 파일임을 명시하며, 50 45는 아스키코드 값으로 PE를 나타낸다.
2) File_Header
- Machine(CPU): 0x014C 이므로 Intel CPU이다.
- 섹션의 개수: 0x0004
- Time Data: 0x6240A1D4 -> 2022년 3월 27일 17시 41분 40초를 의미한다.
- Pointer To Symbol Table, Number of symbol -> NULL 패딩 된 부분이다.
- Size of Optional Header: 0x00E0이므로 32bit이다.
- Characteristics: 0x0103은 0x0100(32bit machine)과 0x0001(Relocation info stripped from file), 0x0002(Executable)를 OR연산하여 구한 값으로 “파일 재배치 정보가 제거되었고 실행이 가능한 32bit 운영체제 파일”이라는 파일형식 정보를 나타낸다.
3) Optional_Header
- Magic: 0x10B이므로 32bit 구조체를 쓴다.
- Size Of code: 0x0E00이므로 코드영역 크기는 0xE00이다.
- Address Of Entry Porint: 0x1277이므로 파일 실행시 Image Base + 0x1277부터 시작한다.
- Base Of Code: 코드영역이 시작되는 상대주소는 0x1000
- Image Base: PE 파일이 메모리에 로드되는 시작주소는 0x400000이다.
- Section Alignment: 섹션의 크기는 0X1000의 배수가 되고 빈 공간은 0으로 채운다.
- File Alignment: 파일에서 섹션의 최소 단위는 0x200이다.
- Size of Image: 파일 로딩시 전체 크기는 0x5000이며 이는 0x200의 배수이다.
- Size of Header: 모든 헤더의 크기는 0x400이다.
- Sub System: CUI(0x3)이다.
- Number of RvaAndSizes: Data Directory 구조체의 개수는 0x10개이다.
6. IMAGE_SECTION_HEADERS
- Name: 0x747865742E는 섹션이름.txt로 실행코드임을 나타낸다.
- Virtual Size: 메모리 섹션의 크기는 0x0CB1이다.
- Virtual Address: 메모리 섹션의 시작주소는 0x1000이다.
- Size Of Raw Data: 파일에서 섹션의 크기는 0xE00이다.
- Pointer To Raw Data: 파일에서 섹션의 시작 위치는 0x400이다.
- Characteristics: 섹션의 정보를 표기하는 부분으로 0x60000020이므로 실행(20000000), 읽기(40000000)가 가능한 코드(20)임을 OR 연산을 통해 나타낸 것이다.