Android Forensic/File System

[Digital Forensic] Android Ext4 File System Structure Analysis

DF_m@ster 2024. 3. 5. 14:00

Ext4

Ext4(Extended File System): 리눅스 기반 시스템에서 널리 사용되는 파일 시스템으로, 주로 안드로이드의 파일 시스템으로 사용된다. 안드로이드는 리눅스 커널을 기반으로 하기 때문에, Ext4 안드로이드 장치에서 데이터의 저장, 검색, 관리를 효율적으로 수행하기에 적합하다. 때문에 모바일 포렌식 그중에서 안드로이드 포렌식을 위해서는 Ext4 파일 시스템을 상세하게 이해할 필요가 있다.

 

본 글은 포렌식의 관점에서 Ext4 파일 시스템의 구조를 상세 분석한 글이다.

 

 

 

Ext4 Structure

Ext4 파일 시스템은 파티션을 여러 개의 Block Group(= Group)으로 나누어 관리한다. Ext4는 Block이라는 데이터 저장 최소단위를 가지며, Block의 크기는 보통 1KB, 2KB, 4KB 중 하나의 크기로 설정된다. 때문에 Block Group은 Block의 집합이라고 볼 수 있다.

 

 

 

Block Group

Block Group은 Super Block, Group Descriptor Table (= GDT), Block Bitmap, Inode Bitmap, Inode Table, journal, Data Block 영역으로 나뉜다.

Ext4 Structure

 

 

 

Super Block

Super Block: Ext4 파일 시스템의 정보를 담고 있는 구조체로, 파일 시스템의 크기, 블록 크기, Inode 크기, 블록 그룹의 수와 같은 Ext4 구조의 핵심 정보를 포함한다. 추가로, Super Block은 0x400부터 시작되며, 파일시스템을 시스템을 마운트 할 Super Block 복사본은 여러 블록 그룹에 걸쳐 저장되어 일부 Super Block 손상될 경우 복구가 가능하다는 특징이 있다.

 

아래는 Ext4 파일 시스템 분석에 중요하게 작용하는 Super Block의 일부 Field를 정리한 내용이다.

Super Block Field

Offset Size Info
0x0C ~ 0F 4 Free Block Count
(파일 삭제 시 분석)
0x10 ~ 13 4 Free Inode Count
(파일 삭제 시 분석)
0x18 ~ 1B 4 Block Size
(2 ^ (10 + Value)) Byte
0x20 ~ 23 4 Block Per Group
0x28 ~ 2B 4 Inode Per Group
0x38 ~ 39 2 Magic Signature
(0x53 EF)
0x58 ~ 59 2 Inode Size
(단위: Byte)
0xFE ~ FF 2 GDT Entry Size
(단위: Byte)

 

 

 

Group Descriptor Table (= GDT)

Group Descriptor Table: Group Descriptor Entry의 집합이다.

Group Descriptor Entry: 파일 시스템 내의 Block Group 대한 정보를 저장한다. 하나의 Block Group은 하나의 Group Descriptor Entry에 할당되며, Group Descriptor Entry의 크기는 Super Block에 명시되어 있다. Group Descriptor Entry는 해당 Block Group에 할당된 Block Group의 Block Bitmap, Inode Bitmap, Inode Table의 시작 주소, 가용상태의 Block 수 (Free Block Count), 가용상태의 Inode 수 (Free Inode Count), 사용하지 않은 Inode 수 (Unused Inode Count) 등의 정보를 포함한다

 

Free Inode와 Unused Inode를 혼동할 수 있다. Free Inode는 Inode 할당 이후에 삭제와 같은 이벤트로 파일 시스템이 가용상태(비할당영역)로 인식된 Inode를 의미한다. 반면에 Unused Inode는 파일 시스템 초기화 이후에 한 번이라도 할당받지 않은 Inode를 의미한다.

Group Descriptor Entry Field

Offset Size Info
0x00 ~ 03 4 Block Bitmap Pointer
(단위: Block)
(파일 삭제 시 분석)
0x04 ~ 07 4 Inode Bitmap Pointer
(단위: Block)
(파일 삭제 시 분석)
0x08 ~ 0B 4 Inode Table Pointer
(단위: Block)
0x0C ~ 0D 2 Free Block Count
0x0E ~ 0F 2 Free Inode Count
0x1C ~ 1D 2 Unused Inode Count

 

 

 

Block Bitmap

Block Bitmap: 해당 Block Group의 Data Block 할당 여부를 나타내는 비트 맵이다. 해석할 때에 리틀 엔디언으로 해석해야 한다. 위치는 각 Group Descriptor Entry의 Block Bitmap Pointer 값에 명시되어 있다.

 

 

 

Inode Bitmap

Inode Bitmap: 해당 Block Group의 Inode Number 할당 여부를 나타내는 비트 맵이다. 해석할 때에 리틀 엔디언으로 해석해야 한다. 위치는 각 Group Descriptor Entry의 Inode Bitmap Pointer 값에 명시되어 있다.

 

 

 

Inode Table

Inode Table: Inode Entry의 집합이다.

Inode Entry: 파일 시스템 내부에 저장된 File 혹은 Directory의 메타데이터 정보를 포함하는 Entry이다. Ext4는 파일 시스템 내부에 저장된 File 혹은 Directory 마다 고유 번호인 Inode Number를 부여하며, Inode Number로 Inode Entry에 접근한다. Inode Entry의 크기는 Super Block에 명시되어 있다. Inode Entry는 해당 File 혹은 Directory Inode Mode (유형, 권한),, Data Size, MAC Time, Extent 등의 정보를 포함한다.

 

아래는 Inode Entry의 Data Pointer와 Extent에 대한 추가적인 설명이다.

Inode Entry Field
Inode Mode

Offset Size Info
0x00 ~ 01 2 Inode Mode
0x04 ~ 07 4 Data Size
0x08 ~ 17 4, 4, 4, 4 Time
0x28 ~ 63 C, C, C, C, C Extent
0x64 ~ 67 4 File Version
(Ext4가 파일 시스템 내부에 저장된 Inode Entry에 고유하게 부여하는 값)
0x84 ~ 97 4, 4, 4, 4, 4 Time

 

Inode Entry - Data Pointer

Inode Entry의 Data Pointer는 파일 Inode의 경우 Data Pointer가 파일의 실제 데이터(헤더 시그니처)를 Pointing 하고, 디렉터리 Inode의 경우 Data Pointer가 Directory Table을 Pointing 한다.

 

Directory Table: Directory Entry의 집합이다.

Directory Entry: 해당 Directory 이하의 모든 파일 혹은 디렉터리마다 할당되어 정보를 저장하는 Entry이다. Directory Entry는 해당 디렉터리 이하에 존재하는 파일의 Inode Number, Directory Entry Length, File Name Length, File Type(해당 Directory Entry가 파일인지, 디렉터리인지 구별), File Name 정보를 포함한다. 

 

아래는 Directory Entry Field이다. 참고로, 모든 디렉터리의 Directory Table은 '.' Directory Entry(현재 디렉터리)와 '..' Directory Entry(상위 디렉터리)를 포함하기 때문에, 기본적으로 2개의 Directory Entry를 갖는다.

Directory Entry

Offset Size Info
0x00 ~ 03 4 Inode Number
0x04 ~ 05 2 Directory Entry Length
0x06 1 File Name Length
(4의 배수, 이유: CPU와 Memory 간의 데이터 전송 효율을 높이기 위함.)
0x07 1 File Type
(0x00: Unknown)
(0x01: Regular file)
(0x02: Directory)
(0x03: Character device file)
(0x04: Block device file)
(0x05: FIFO)
(0x06: Socket)
(0x07: Symbolic link)
0x08 ~ (8 + File Name Length) File or Directory Name Length File Name

 

Inode Entry - Extent

Ext4는 Inode Entry의 Data Pointer를 Extent 형식으로 관리하며, 해당 Extent 영역은 Inode Entry의 0x28 ~ 0x63까지의 영역을 차지한다. Extent는 Extent Header와 Extent Table 영역으로 이루어져 있다.

 

Extent Header: Extent의 Header 영역으로 Inode Entry의 0x28 ~ 0x33(크기: 0x0C)까지의 영역을 차지한다. Extent Header는 Magic Signature, Extent 내의 유효한 Extent Entry 수, Extent 내의 최대 Extent Entry 수, Extent 깊이 정보를 포함한다.

Extent Header Field

Offset Size Info
0x28 ~ 29 2 Magic Signature
(0x0A F3)
0x2A ~ 2B 2 Number of Valid Entries
(Inode Entry 내부의 유효한 Extent Entry 수)
(최대 값 = 4)
0x2C ~ 2D 2 Max Number of Entries
(Inode Entry 내부의 최대 Extent Entry 수)
(최대 값 = 4)
0x2E ~ 2F 2 Depth of Extent Tree
(Extent Tree 깊이)

 

Extent Table: Extent Entry의 집합으로,  Inode Entry의 0x34 ~ 0x63(크기: 0x0C x 4)까지의 영역을 차지한다. Extent Entry는 크기가 0x0C이기 때문에 Extent Table은 최대 4개의 Extent Entry 만을 포함할 수 있다. 만약, 5개 이상의 Extent를 포함해야 하는 경우, Depth를 늘려 관리한다.

 

Extent Entry: Inode의 Data Pointer로, 크기가 0x0C이다. Extent Entry는 해당 파일 Data의 Logical Block Number, Data Block Length, Data Block Pointer 정보를 포함한다. 추가적으로 Extent Depth가 '0'인 경우와 '1'이상인 경우 Extent Entry의 크기는 0x0C로 같으나 Filed에서 약간의 차이가 나타난다.

Extent Depth 0

Offset Size Info
0x00 ~ 03 4 Logical Block Number
(Data의 논리 Block 시작 번호)
0x04 ~ 05 2 Data Block Length
(단위: Block)
0x06 ~ 07 2 Data Block Pointer
(Upper)
0x08 ~ 0B 4 Data Block Pointer
(Lower)

 

Extent Depth 1

Offset Size Info
0x00 ~ 03 4 Logical Block Number
(Data의 논리 Block 시작 번호)
0x04 ~ 07 4 Data Block Poiner
(Lower)
0x08 ~ 09 2 Data Block Pointer
(Upper)
0x0A ~ 0B 2 Unused

 

구체적으로, 0x34 ~ 3F (Extent Entry 1), 0x40 ~ 4B (Extent Entry 2), 0x4C ~ 57 (Extent Entry 3), 0x58 ~ 63 (Extent Entry 4) 영역에 대응된다. 해당 Extent Entry는 1부터 사용되며, Extent Entry의 사용개수는 Extent Header에 명시되어 있다. 

Extent Field

 

하나의 Extent Entry는 Data Block 수를 15bit로 제한하여 표현하기 때문에 최대 32,768(2 ^ 15) 개의 Data Block을표현할 수 있다. 만약 Block 크기가 4KB라면, 하나의 Extent Entry가 표현할 수 있는 최대 데이터 크기는 128MB(32,768 * 4KB = 131,072KB = 128MB)이다. 이는 Inode 내부의 Extent 영역에서 표현할 수 있는 최대 데이터 크기가 512MB(128MB * 4) 임을 의미한다. 결과적으로 Ext4 파일 시스템의 Block 크기가 4KB라면, 128MB 이상의 데이터 저장 시 단편화 현상이 필수로 일어나며, 512MB 이상의 데이터 저장 시 Depth가 필수로 증가한다. 이는 포렌식의 측면에서 파일 추출 및 복구 시 중요한 정보로 작용한다.

 

아래는 Extent Depth가 '0'인 경우(Inode 1)와 '1'인 경우(Inode 3)를 도식화한 모습이다. Extent Depth는 필요에 따라 2 이상의 값을 가질 수도 있다.

Extent Depth 0 (Inode 1), Extent Depth 1 (Inode 3)

 

 

 

journal

journal: Ext4 파일 시스템의 데이터 변경 사항을 미리 기록(백업)하여 시스템 충돌, 전원 문제로 인한 파일 시스템 손상을 방지하여 파일 시스템의 무결성을 유지할 수 있게 돕는 역할을 한다.

 

안드로이드의 Ext4 파일 시스템은 메타 데이터만을 journal에 백업한다. 구체적인 journal 백업 방식은 트랜잭션이 발생하면 해당 파일의 변경 예정인 메타데이터를 Blcok 단위로 전부 journal에 백업한다. 이후에 성공적으로 메타 데이터를 수정하면 트랜잭션이 종료되고, 예기치 못한 충돌이 발생한 경우 백업된 journal의 데이터를 참조하여 원래의 상태로 복원한다. 때문에 Ext4 파일 시스템에서 특정 파일의 변경 이전 메타 데이터를 journal 영역에서 확보할 수 있다.

 

journal은 journal super block과 여러 개의 journal log를 포함한다. 하나의 journal log는 하나의 트랜잭션마다 할당되어 생성되며, journal 영역에 순차적으로 기록된다. 만약 journal log를 journal 영역에 전부 기록한 경우, 가장 오래된 journal log 영역을 재할당하여 journal log를 기록한다. 즉, 물리 주소로 가장 뒤에 존재하는 journal log가 가장 최근에 이루어진 트랜잭션이 아니다.

journal Structure

 

journal log: Ext4 파일 시스템에서 발생하는 트랜잭션마다 생성되며 하나의 journal log는 Descriptor Block, Metadata Backup Block, Commit Block 혹은 Revoke Block을 포함한다.

 

journal 영역에서 Metadata Backup Block 영역을 제외한 모든 journal Block은 동일한 Header를 갖으며, Header의 Block Type 값으로 해당 Block이 journal Super Block, Descriptor Block, Commit 혹은 Revoke Block 중 어떠한 Block 영역인지 구분한다.

 

이때 하나의 journal log에서 Descriptor Block과 Commit Block 혹은 Revoke Block은 Block 하나의 크기를 가지며, Metadata Backup Block은 트랜잭션 발생 시에 변경되는 모든 메타데이터를 블록 단위로 백업하기 때문에 여러 개의 Block 크기를 갖는다.

journal log Structure

 

아래는 journal Block Header의 Field이다.

journal Block Header Field

Offset Size Info
0x00 ~ 03 4 Magic Signature
(0xC0 3B 39 98)
0x04 ~ 07 2 Block Type
(0x01 = Descriptor Block)
(0x02 = Commit Block)
(0x03 = Journal Super Block V1)
(0x04 = Journal Super Block V2)
0x08 ~ 0B 4 Transaction ID
(Big Endian)

 

journal 영역에서 수정 이전의 핵심 메타 데이터인 Inode Entry 혹은 Extent의 확보에는 구체적인 방법이 존재하며, 해당 방법은 다음 글인 파일 복원 글에서 상세하게 다루도록 하겠다.

 

 

 

Data Block

Data Block: 실제 파일 데이터나 디렉터리의 목록을 저장하는 사용되는 블록이다

 

 

 

Ext4 Structure

아래는 Ext4 파일 시스템의 전체 구조이다. 한 가지 오류가 있다면 Extent Entry의 Pointer가 Block Group의 Data Block 영역을 Pointing 해야 하지만, 유연한 그림을 위해 Data Block 영역을 따로 분리하여 표현하였다. 도식화하는데 30분이 걸렸다...

Ext4 File System Structure

 

 

 

 

 

메인 글

[Digital Forensic] Android Ext4 File System Detailed Analysis

 

[Digital Forensic] Android Ext4 File System Detailed Analysis

Ext4 Ext4(Extended File System): 리눅스 기반 시스템에서 널리 사용되는 파일 시스템으로, 주로 안드로이드의 파일 시스템으로 사용된다. 안드로이드는 리눅스 커널을 기반으로 하기 때문에, Ext4는 안

digitalforensicmaster.tistory.com

 

다음 글

[Digital Forensic] Android Ext4 File System Recovery Analysis

 

[Digital Forensic] Android Ext4 File System Recovery Analysis

Ext4 File System File Recovery 본 문단은 안드로이드의 Ext4 파일 시스템에서 파일 삭제 정책을 토대로 파일 복구 과정을 정의하고, 삭제된 파일 복구 과정을 정리한 글이다. 파일 복구 실습은 두 가지

digitalforensicmaster.tistory.com

 

 

 

 

Reference

https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout

https://www.dbpia.co.kr/journal/detail?nodeId=T15015734