1. MBR (Master Boot Record)?

MBRMaster Boot Record의 약자로 컴퓨터에 전원이 공급되고 부팅이 가능한 운영체제를 찾아 해당 운영체제의 boot code를 실행할 수 있도록 Partition들의 위치 정보를 갖는다.



회색으로 색칠된 부분이 Boot code이고 아래에 여러 색으로 색칠된 부분이 Partition table이다

Boot codePartition Table 중 부팅이 가능한 Partition을 찾아 부팅을 할 수 있게 해주는 코드이며 마지막 2bytes(0xAA55) MBRSignature이다

MBR Partition table 형식이다. Partition Table의 첫 바이트인 Boot Flag는 해당 Partition이 부팅이 가능한지 여부를 나타내는 플래그다

그 다음으로 오는 세 바이트는 CHS(Cylinder-Head-Sector) 방식의 주소를 사용할 경우 해당 Partition 시작 주소를 나타낸다

다음으로 오는 Part Type 필드는 해당 Partition 유형을 나타내며, 값이 가지는 아래 표로 나타낸다.

이후 바이트는 LBA(Logical Block Addressing) 방식의 주소를 사용할 경우의 Partition 시작 주소를 나타낸다

LBA Starting Address 이후에 오는 Number of sectors in partition 필드는 해당 Partition Sector 개수를 나타내며 따라서 LBA 주소 방식을 사용할 경우 전체 파티션 영역은 다음과 같다.

시작 주소 : [Starting LBA address] * [Sector size]

주소  : [Starting LBA address] * [Sector size] * [Num of sectors in Partition]

필드의 의미를 정리하면 다음과 같다.

- Boot flag(1byte)           : 해당 파티션이 부팅이 가능한 파티션인지 여부를 나타냄                          (0x80 : 부팅 가능, 0x00 : 부팅 불가능)

- CHS Start(3bytes)         : 해당 파티션의 시작 주소를 의미함(CHS 방식)

- Part Type(1byte)          : 해당 파티션의 종류를 의미함                                                                 (0x0B : CHS 모드 FAT32, 0x0C : LBA 모드의 FAT32, 0x07 : NTFS 등)

- CHS End(3bytes)          : CHS 방식의 종료 주소

-  LBA Start(4bytes)         : 해당 파티션의 시작 주소(LBA 방식)

-  Size in Sector(4bytes)   : 파티션의 섹터 수

 


Partition Type에 올 수 있는 값들은 위와 같다.

0번지부터 512Bytes까지 MBR이 기록되어 있으며 위 그림과 같이 Partition Table을 확인할 수 있었다.

초록색으로 색칠한 부분이 각 PartitionPartition Type을 나타내며, 네 개의 Partition 모두 해당 값이 0x07이다.

위 그림에서 확인하면 0x07exFAT 또는 NTFS 파일시스템을 나타낸다

4개의 Partition Entry중 색칠한 부분이 각각 [LBA Starting address][Num of sectors in Partition]에 해당한다

따라서 첫 번째 Partition0x3F0x200(512bytes)를 곱한 위치에 존재한다고 볼 수 있다

0x3F0x200을 곱한 값은 0x7E00이므로 해당 위치에 실제 Partition이 저장되어 있는지 확인한다.



앞서 계산한 0x7E00의 위치에 NTFS 파일시스템 형식의 Partition이 있는 것을 확인할 수 있었다

추가적으로 위 그림에서 첫 번째 Partition의 시작 주소인 0x3F와 해당 Partition Sector 수를 나타내는 0x032F8E를 더한 값이 다음 두 번째 Partition의 시작 주소임을 확인할 수 있으며 따라서 첫 번째 Partition이 끝나는 지점의 다음 Sector에 두 번째 Partition이 존재하는 것을 확인할 수 있다

두 번째 Partition의 위치 또한 동일하게 계산해보면 0x032FCD Sector의 크기인 0x200(512bytes)를 곱하면 위치를 구할 수 있다

해당 계산의 결과는 0x65F9A00이며 해당 위치에 실제 Partition이 존재하는지 확인해본다.



위 그림에서 확인할 수 있듯이 0x65F9A00에 해당 Partition이 기록되어 있는 것을 확인할 수 있었다

이후 세 번째 LBA를 계산하면 0x065F9A Sector 크기를 곱한 값은 0x0CBF3400이며 해당 위치에 실제 세 번째 Partition이 존재하는지 확인해본 결과 다음과 같이 실제 Partition이 존재하는 것을 확인할 수 있었다

네 번째 Partition 역시 0x098F67 * 0x2000x131ECE00에 실제 Partition이 위치하는 것을 확인할 수 있었다.

세 번째 파티션


네 번째 파티션


다음으로 CHS(Cylinder-Head-Sector) 방식은 이름 그대로 실제 HDDCylinder, Head, Sector를 이용하여 디스크 영역을 접근하는 방법이다

표현할 수 있는 크기가 크지 않아서 현재는 사용하지 않지만 주소 계산 방법을 살펴보면 다음과 같다.


 색칠된 부분이 CHS Address의 시작 주소를 나타낸다

해당 값을 계산하기 위해선 해당 값으로부터 Cylinder, Head, Sector 부분을 계산해야 하며 계산을 위해선 세 값을 비트로부터 추출해야 한다

Partition Table의 첫 번째 PartitionCHS Address0x000101을 이용하여 세 값을 나타내면 다음과 같다.



해당 값을 리틀엔디안 방식을 고려하지 않고 해석하면 가장 맨 뒤 10비트가 Cylinder를 의미하며 그 앞 6비트는 Sector, 처음 8비트는 Head를 의미한다

따라서 0x000101의 각 세 값은 0, 1, 1이 된다. 해당 값을 이용하여 공식에 따라 LBA 주소로 변환이 가능하며 그 공식은 다음과 같다.



실린더당 헤드의 개수와 트랙당 섹터 개수는 고정적으로 각각 0xFF(255), 0x3F(63)을 사용하며, 해당 값을 대입하여 계산하면 변환된 LBA의 주소는 0x3F(63)이 된다

해당 값은 같은 Partition TableLBA 주소인 0x3F와 일치한다. 두 번째 PartitionCHS 주소인 0x0D0100을 이용하여 LBA 주소 계산을 해보면 마찬가지로 Cylinder의 값은 13, Head의 값은 0, Sector의 값은 1이 되어 LBA 주소 계산 결과 208,845가 도출되며 해당 값을 16진수로 변환하면 0x032FCD가 된다

해당 값은 두 번째 PartitionLBA 값과 일치한다

세 번째 Partition 역시 Cylinder 0x1A(26), Head 0, Sector 1이 되어 계산 결과 417,690이 도출되며 해당 값은 16진수로 0x065F9A로 세 번째 PartitionLBA 주소와 일치한다

네 번째 경우도 0x270100CHS 값은 Cylinder 0x27(39), Sector1, Head0으로 마찬가지로 의 공식에 대입하면 십진수 626,535를 구할 수 있으며 이는 16진수로 0x098F67로 네 번째 PartitionLBA 값과 일치하다.



* 첫 번째 파티션이 63(0x3F)에 있는 이유

과거에 Disk access에 사용된 BIOS APIINT 13hCHS Addressing에 사용되었는데 해당 인테럽트를 사용하여 Disk accessing을 하는 시스템에는 모든 PartitionCylinder Boundary에 위치해야 한다. 따라서 첫 번째 CylinderBoundary에 위치한다. 비록 LBA 주소 계산 방식이 사용되어도 과거 CHS 방식과 호환을 위해 첫 번째 CylinderBoundary에 위치하며 각 Cylinder에는  63개의 섹터가 있어서 0x3F(63) Partition이 위치하게 됐다. 현재는 Logical SectorAdvanced Format으로 인해 한 섹터를 4K로 정렬해야 하며 이러한 시스템에서 0x3F라는 값은 8의 배수가 아니기 때문에 Partition을 위치시키는 과정에서 섹터에 맞지 않는 오배열로 이어질 수 있으며 이는 Performace 문제를 발생시킬 수 있어서 현재 사용되는 OSPartition은 일반적으로 0x800에 위치한다.

 





'Study > Digital Forensic' 카테고리의 다른 글

Memory Forensic  (0) 2019.02.19

1. Petya?

2016년 3월 발견된 랜섬웨어로 디스크의 MBR 영역을 변조하여 PC의 부팅이 불가능하도록 하고 부팅 시 Ascii 코드로 작성된 해골 화면을 띄우며 결제를 유도하는 랜섬웨어다. MBR의 0번 섹터부터 56번 섹터 사이만 접근하여 조작하기 때문에 다른 부팅 디스크를 통해 부팅하여 MBR 영역만 복원해주면 정상적으로 사용이 가능하다.



2. Analysis

  2-1. File information


 윈도우 운영체제에서 실행되는 PE 형식의 파일이며 해당 파일에 대한 해시 정보는 위의 표와 같다


 분석에 앞서 Virustotal 사이트에서 제공하는 기본적인 정보에 대해서 파악하면 다음과 같다.


 

  

  해당 PE 파일은 5개의 섹션으로 이루어졌으며 각 섹션의 엔트로피 값을 통해 섹션의 암호화 여부를 확인할 수 있다

 엔트로피를 통한 패킹 및 암호화 여부는 다음 논문에서 확인할 수 있었다.

 

Using Entropy Analysis to Find Encrypted and Packed Malware / J. Hamrock and R. Lyda / IBM in IEEE Security & Privacy / 2007. 


발췌한 엔트로피를 통한 패킹 및 암호화 여부에 대해 파악할 수 있는 자료이다.

해당 자료를 참고하면 엔트로피 값이 7 이상일 경우 암호화된 데이터로 분류하며 따라서 엔트로피 값이 7.19로 나타난 text 섹션은 암호화된 코드가 삽입되었다고 판단할 수 있다

백신 제품들이 API 호출 탐지 기반 등 고도화된 탐지 기법을 도입함에 따라 해당 기법들에 대해 우회하기 위한 방안으로 프로그램이 실행될 때 암호화된 코드 데이터를 복호화 하여 실행하는 백신 우회 기법을 사용한 것으로 의심해볼 수 있으며 좀 더 자세히 알아보기 위해 동적 분석을 진행해본다.


  2-2. Dynamic Analysis

Petya를 동적 분석하기 위한 환경으로 VMware 가상화 도구를 사용했으며, 프로그램 역분석 도구로는 IDA Pro 6.6 도구를 사용했다. 먼저 Petya를 실행시킨 다음 컴퓨터가 강제종료 된 상황에서 볼 수 있는 화면이다.

 


Petya 실행 후 OS가 재부팅 되면 위와 같이 디스크를 확인하는 과정이 진행된다

위 과정이 끝나면 다음과 같은 랜섬노트가 화면에 출력된다.






 해골 문양이 출력된 이후에 이어서 위와 같은 랜섬노트가 화면에 출력된다

사용자의 디스크가 암호화 됐으며 이를 복구하기 위해선 Tor Browser를 이용하여 가상화폐로 결제를 유도하는 화면이며 부팅을 할 수 없는 상황이다

다음은 Petya 실행 전후의 MBR 영역이다.


    

 Petya 실행 전 정상적인 MBR()과 실행 후의 MBR()


위 사진과 같이 Petya를 실행 전후로 MBR이 변경된 것을 확인할 수 있다

다음으로 동적 분석을 수행하기 전에 MBR이 무엇인지, PC의 부팅과 어떤 관련이 있는지 간략하게 정리한다.



  2-3. MBR (Master Boot Record)?

파티션이 여러 개인 다중 파티션의 경우 각 파티션의 첫 번째 섹터에 존재하는 BR(Boot Record)만으로는 부팅 파티션을 결정할 수 없다

MBR은 파티션 테이블을 참조하여 부팅이 가능한 파티션을 찾고 코드를 실행하여 해당 파티션으로 부팅이 되도록 하는 코드가 있는 메모리 영역이다

저장매체의 첫 번째 섹터에 위치하는 512 bytes의 영역으로 구조는 다음과 같다



PC가 부팅되면 디스크의 첫 번째 섹터를 호출하며 부트 코드가 실행된다

부트 코드는 파티션 테이블에서 부팅이 가능한 파티션을 찾아 해당 파티션의 부트 섹터를 호출해주는 역할을 하며, 파티션 테이블에는 각 파티션들에 대한 정보가 있으며 SignatrueMBR 디스크 영역이 가지는 고유의 바이트(0x55AA)이다.

 



각 파티션 테이블은 위와 같은 구조를 가지며 각 바이트들이 뜻하는 의미는 다음과 같다.

-       Boot flag(1byte)  : 해당 파티션이 부팅이 가능한 파티션인지 여부를 나타냄

(0x80  : 부팅 가능, 0x00 : 부팅 불가능)

 

-       CHS Start(3bytes) : 해당 파티션의 시작 주소를 의미함

 

-       Part Type(1byte) : 해당 파티션의 종류를 의미함

(0x0B : CHS 모드 FAT32, 0x0C : LBA 모드의 FAT32, 0x07 : NTFS )

 

-       CHS End(3bytes) : CHS 방식의 종료 주소

-       LBA Start(4bytes) : LBA 시작 주소, 파티션 시작 섹터 번호

-       Size in Sector(4bytes) : 파티션의 섹터 수

 

MBR 방식을 사용하는 시스템에서는 MBR의 부트 코드는 부팅에 필수적인 코드이며 따라서 Petya와 같이 MBR의 영역의 데이터의 무결성을 해치는 공격이 발생할 경우 사용자의 PC가 부팅이 가능한 파티션을 찾지 못해 부팅을 할 수 없는 상황이 발생할 수 있다

다음으로는 Petya가 어떤 과정으로 MBR을 암호화 하는지 파악하기 위해 IDA Pro disassembly 도구를 이용하여 정적 분석을 시행한다.


  2-4. Static Analysis?

Petya를 정적분석하기 위한 환경으로 IDA Pro 6.6 + Hex-ray Decompiler plugin을 이용하여 역분석을 진행한다

먼저 Petya는 실행 과정에서 특정 데이터 영역을 복호화 하여 코드 영역에 쓰며 해당 코드 영역을 실행시키는 형태로 실행된다

복호화 하여 실행시키는 코드는 MZ 헤더 형식의 실행 파일이었으며 다음 사진은 프로그램 실행 도중에 MZ 헤더로 시작하는 코드를 복호화 하여 코드 영역에 올리는 사진이다.



왼쪽 사진은 프로그램을 실행하기 전의 코드이며 해당 프로그램을 실행할 경우 0041AE72 ~ 0041B358 까지의 코드를 반복하며 0041B35E MZ 헤더로 시작하는 코드를 삽입한다

Petya가 수행하는 암호화 루틴은 해당 코드에서 수행되며 실행 도중에 메모리 덤프를 통해 해당 MZ 헤더의 실행 파일을 얻을 수 있다

Petya가 수행하는 암호화 루틴을 분석하기 위해 해당 DLL을 확보하여 IDA에 올려서 이후 분석을 진행한다



분석 대상 MZ 실행 파일을 IDA로 올리고 DllEntryPoint에서 호출하는 몇 가지의 함수들을 타고 들어가보면 위와 같은 코드를 확인할 수 있다

CreateFileA 함수를 통해 운영체제가 설치된 물리 디스크의 핸들을 받아오며 만약 핸들을 얻지 못하면 프로그램은 종료된다

(line32) 핸들을 얻은 후 프로그램은 MBR이 있는 디스크의 0번지부터 0x7200번지까지 암호화 루틴에 들어간다

다음은 첫 번째로 실행되는 암호화 과정이다.

 


위 코드는 0x200번지부터 512byte씩 블록 단위로 읽고 0x37 xor 연산을 수행한 뒤에 같은 영역에 다시 쓰는 과정이다

이 과정을 0x22번 수행하므로 0x200부터 0x4400 까지는 원본의 데이터와 0x37xor 연산을 한 결과가 저장된다

위 사진에서 보이는 ReadFromFile 함수와 WriteToFile 함수는 함수들의 실행 코드를 분석하여 분석의 편의를 위해 임의로 붙인 이름이다

다음은 각 함수들의 모습이다.



임의로 이름을 붙인 ReadFromFile 함수는 첫 번째 인자로 파일의 이름을 받고, 두 번째 인자로는 파일로부터 읽은 데이터를 저장할 버퍼를 전달받는다

세 번째 인자와 네 번째 인자는 파일 포인터를 계산하는데 사용되며 결과적으로 해당 함수가 호출되면 첫 번째 인자로 전달받은 파일이름에 해당하는 파일을 열고 3번 째 인자로 전달받은 a3512를 곱한 지점부터 512바이트를 읽어서 두 번째 인자로 전달받은 버퍼에 저장한다.



위 함수에서 세 번째 인자로 전달받은 값을 ecx 레지스터에 저장한 후에 shift left9차례 수행하여 setFilePointerEx 함수의 인자로 전달한다. 결과적으로 파일 포인터는 세 번째 인자의 512배에 해당하는 지점을 가리키게 된다.



WriteToFile 함수는 첫 번째 인자로 전달받은 파일의 이름에 해당하는 파일을 열어서 세 번째 인자로 파일 포인터를 계산, 두 번째 인자로 전달받은 버퍼에 있는 데이터를 512바이트 쓰는 함수이다

파일의 포인터 계산하는 방법은 위의 ReadFromFile 함수와 같다. Petya가 디스크로부터 데이터를 읽고 암호화 한 데이터를 쓰는 일련의 과정들은 모두 위의 두 함수를 통해서 진행된다.



디스크의 0x200 ~ 0x4400 영역을 암호화 한 이후에 오는 코드는 0x00번지부터 0x200번지까지 MBR 영역을 읽은 후에 암호화 하는 과정이다

v47 변수에 해당 암호화 코드는 저장되며 이 v47 변수는 프로그램이 종료하기 다른 디스크 영역에 쓰이게 된다.



이후에 호출되는 함수에서는 두 변수에 악성 데이터를 쓰는 루틴이다.

 v51 변수에 문자 ‘7’512 bytes를 쓰며, v50에는 함수로 이루어진 암호화 루틴을 수행하며 랜섬노트에 출력되는 URL 텍스트 중 일부를 저장한다

해당 함수는 의미 있는 암호화 루틴이 아니므로 설명 및 분석을 생략한다.



앞에서 설명한 랜섬노트 일부 텍스트가 담긴 v50 변수를 0x6C00에 쓰고 ‘7’문자로 이루어진 512 bytes의 변수 v510x6E00에 쓰여진다

그 다음에 쓰여지는 데이터가 중요한데, v47 변수는 앞에서 0x00~0x200 MBR 영역을 암호화 한 데이터가 저장된 변수이다

여기까지 Petya가 수행하는 암호화 루틴이며 이를 정리하면 다음과 같다.




실제로 Petya로 암호화된 가상머신의 디스크를 분석 프로그램을 이용하여 열어본 화면이다

랜섬노트로 암호화된 0x4400~0x6E00 까지의 영역 중 일부이며 해골 문양의 일부와 랜섬노트에 출력되는 텍스트들을 확인할 수 있었다.



암호화 루틴이 끝난 후에 호출되는 함수이다

해당 함수 내에서 GetCurrentProcess 함수를 통해 현재 프로세스의 핸들을 얻고 OpenProcessToken, LookupPrivilegeValueA, AdjustTokenPrivileges 함수들을 호출하여 시스템 종료 권한을 얻으며 권한을 상승한다

그 이후에 “NTDLL.DLL”을 로드하고 NtRaiseHardError를 통해 PC를 강제 종료한다.


 

  2-5. Decryption

분석한 Petya 랜섬웨어가 사용한 암호화 루틴은 블록암호 또는 비대칭키 암호와 같이 복잡한 암호화 알고리즘을 사용하지도 않았으며 키가 1 바이트인 스트림 암호라고 볼 수 있다

해당 키는 역분석을 통해 간단히 찾을 수 있었고 암호화 한 MBR 데이터를 숨겨둔 위치 또한 분석을 통해 얻을 수 있었다

따라서 암호화 된 MBR 영역의 hex 값을 복호화 하는 코드를 작성하여 암호화 전의 데이터와 비교해봤다.



MBR 영역의 데이터는 0x37 XOR 연산을 통해 암호화 됐으며 해당 데이터를 0x37과 다시 XOR 연산을 해주면 원본의 데이터를 확보할 수 있다

위와 같은 코드를 작성하여 암호화 된 데이터만 추출하여 해당 코드를 실행시키고 나온 복호화 데이터를 비교하면 다음과 같았다.


    

위 사진에서 왼쪽은 원본의 MBR 데이터이고 오른쪽의 사진은 암호화 된 MBR 데이터를 복호화 한 결과이다. 암호화 과정이 간단했던 만큼 쉽게 복호화 한 데이터를 얻을 수 있었다.






'Study > Reversing' 카테고리의 다른 글

우회 기법  (0) 2019.03.20
FSC_Level1 풀이  (0) 2019.03.20
PE 헤더  (0) 2019.02.18
2. C 문법과 디스어셈블리  (0) 2019.02.14
1. IA-32 assembly  (0) 2019.02.14

1. PE 헤더 (PE Header)?

  Portable Executable File Format의 약자로 이식 가능한 다른 곳에서도 실행이 가능한 포맷이다.


2. PE 파일 생성 과정

 

- 소스코드(cpp)를 컴파일 하면 어셈블리 코드가 만들어지고 어셈블러에 의해 어셈블리 코드들은 오브젝트 코드로 만들어짐

- 이렇게 만들어진 오브젝트 코드들은 정적으로 라이브러리 코드를 모두 포함하여 만들어지지 않는 이상 동적 링킹을 거치게 된다.

- 동적 라이브러리나 각종 리소스 데이터와 Import, Export 테이블을 처리할 수 있는 정보를 어딘가에 적어둠

- 윈도우는 exe 파일을 만들 때 약속된 규약에 따라 정보를 기입하고 이렇게 만들어진 파일이 PE 파일이다.

- EXE 또는 DLL을 실행하면 개발자가 만든 코드가 실행되기 전에 PE 정보부터 읽어와서 바이너리를 메모리에 올리기 위한 각종 데이터를 설정하는 작업을 함



3. PE 파일 구조

- 소스코드(cpp)를 컴파일 하면 어셈블리 코드가 만들어지고 어셈블러에 의해 어셈블리 코드들은 오브젝트 코드로 만들어짐

- PE 헤더는 여러 구조체로 이루어져 있으며 PE viewer를 이용하여 직접 구조체 살펴볼 수 있음 (eg : VX PE-Viewer)
- VX PE-Viewer는 현재 2.0 버전까지 배포됐으나 2.0 버전에서는 런타임 에러가 발생하여 실행이 불가능했음, 따라서 1.1 버전으로 분석을 진행함


  3-1. IMAGE_DOS_HEADER
   - 크기는 0x3D 바이트이며 가장 먼저 위치하여 PE 파일의 맨 처음 부분에 해당한다. Hex 에디터를 이용하여 PE 파일을 열어도 해당 구조체를 가장 먼저 찾아볼 수 있다.         - 가장 첫 번째 필드인 (e_magic)과 마지막 필드(e_lfanew)가 중요하다
 

    


     

   - e_magic 필드는 PE 파일의 시그니처로 최초 개발자의 이름을 딴 "MZ"로 시작한다. 위에 그림에서도 확인해볼 수 있다.

   - e_lfanew 필드는 다음 구조체인 IMAGE_NT_HEADER의 구조체 위치를 알아내는 데 사용되는 값

  

 3-2. IMAGE_NT_HEADER

   - IMAGE_DOS_HEADER의 마지막 필드인 e_lfanew 필드를 이용하여 다음과 같이 주소를 알아낼 수 있음

    

     

  

    - 다음과 같이 구성되어 있으며 Signatrue는 "PE\0\0"을 나타내는 4바이트 값(50 45 00 00)이다.

    - 요즘 윈도우에서는 해당 자리에 50 45 00 00이 아닌 다른 값이 자리하게되면 해당 파일은 윈도우에서 실행되지 않음,

      과거엔 이를 확인하지 않아 바이러스나 악성코드에 의한 감염 표식용으로 사용됨


    



    



  3-3. IMAGE_FILE_HEADER

   - IMAGE_DOS_HEADER의 마지막 필드인 e_lfanew 필드를 이용하여 다음과 같이 주소를 알아낼 수 있음

 

    

   - Machine

     : 어떤 CPU에서 이 파일이 실행될 수 있는지를 알려줌

   - NumberOfSections 

     : 섹션이 몇 개 있는지를 알려줌 (.text, .data 등)

       일반적으로 비주얼 스튜디오에서 MFC로 별다른 옵션 변경 없이 빌드한 경우 .text, .rdata, .data, .rsrc로 4개의 섹션이 존재함

       패킹이나 프로텍팅 등의 이유로 섹션 수가 증가하면 이 값도 같이 증가함

   - TimeDateStamp

     : 해당 파일이 빌드된 날짜 정보

   - SizeOfOptionalHeader

     : IMAGE_OPTIONAL_HEADER32의 구조체 크기, 해당 구조체는 PE를 로딩하기 위한 중요한 정보를 갖고 있는데, 이 구조체는 운영체제마다

       크기가 다를 수 있기 때문에 PE 로더에서는 SizeOfOptionalHeader값을 먼저 확인한 뒤 IMAGE_OPTIONAL_HEADER32 구조체의 크기를 처리함 

   - Characteristics

     : 현재 파일이 어떤 형식인지 알려주며 DLL인지 EXE인지 구분하는 용도로 활용이 가능하다.

    



  3-4. IMAGE_OPTIONAL_HEADER
    - PE 구조체 중 중요한 값을 가장 많이 담긴 헤더

    


    - MAGIC

     : 시그니처, 32비트의 경우 0x10B가 들어오며 64비트의 경우 0x20B가 된다.

    - SizeOfCode

     : 코드 양의 전체 크기를 가리킴, 실제 개발자가 만든 코드의 양이 해당 필드에 들어가며, 바이러스나 악성코드는 이 필드를 읽어서 

       악성 코드를 복제할 위치를 계산하기도 하며, 보안 솔루션에서 코드 섹션의 무결성 검사를 위한 크기도 해당 필드를 통해 정함 

    - MajorLinkerVersion, MinorLinkerVersion

     : 어떤 버전의 컴파일러로 빌드했는지를 알려줌 (비주얼 스튜디오 6.0일 경우 6.0이 자리함)

    - ImageBase

     : 해당 파일이 실행될 경우 실제 가상 메모리에 올라가는 번지를 가리킴, EXE 파일의 경우 번지 지정을 별도로 해주지 않는 이상 0x400000에 올라감.

       DLL의 경우 기본 이미지 베이스 주소가 0x10000000 번지로 정해져 있지만 재배치 속성에 따라 재할당되기도 함

    - AddressOfEntryPoint

     : 실제 파일이 메모리에서 실행되는 시작 지점을 말함. 디버거를 통해 파일을 실행했을 때 디버거는 첫 실행 지점을 이곳과 ImageBase를 합산한 위치에 지정해서 멈춤

    - BaseOfCode

     : 실제 코드가 실행되는 번지, 코드 영역의 시작 주소는 ImageBase에 BaseOfCode를 더한 위치이다. 기본적으로 0x1000의 값을 가짐

    - SectionAlignment, FileAlignment

     : 각 섹션을 정렬하기 위한 저장 단위, 보통 0x1000이 지정되며 섹션의 크기가 0x1000이하일 경우에도 패딩을 통해 0x1000을 채움

    - SizeOfImage

     : EXE나 DLL이 메모리에 로딩됐을 때의 전체 크기, 로더가 해당 필드를 참조하여 메모리 공간을 할당함

    - SizeOfHeaders

     : PE 헤더의 크기를 알려주는 필드

    - Subsystem

     : 해당 프로그램이 GUI(0x02)인지 CLI(0x03)인지를 알려줌

    - DataDirectory

     : IMAGE_DATA_DIRECTORY의 구조체로서, VirtualAddress와 Size라는 필드가 포함돼있음

       Export 디렉토리나 Import 디렉토리, 리소스 디렉토리, IAT 등 각각의 가상 주소와 크기를 이 필드를 통해 알 수 있음

      

      


'Study > Reversing' 카테고리의 다른 글

우회 기법  (0) 2019.03.20
FSC_Level1 풀이  (0) 2019.03.20
Petya Ransomware 분석  (0) 2019.02.19
2. C 문법과 디스어셈블리  (0) 2019.02.14
1. IA-32 assembly  (0) 2019.02.14

+ Recent posts