study/iOS

05 SQLite

우저미 2025. 4. 10. 18:28
Review

 

1. Instant Messenger에서 SQLite의 메타데이터를 이용한 메시지 복구 기법 

1) SQLite

SQLite는 일반적인 관계형 데이터베이스와 비교했을 때 크기가 작고 가볍고, 하나의 파일로 모든 데이터를 저장한다는 특징이 있다. 서버 없이도 작동하며, 이로 인해 모바일 기기의 애플리케이션에서 매우 적합한 구조를 가지고 있다. 그러나 보안 측면에서는 제약이 존재하며, 포렌식 분석에서는 이러한 특성이 중요한 단서가 되기도 한다.

- 파일 구성 개요 : SQLite 파일은 페이지 단위(page-based)로 구성되며, 각 페이지는 특정 역할을 수행한다. 파일 크기16번째 바이트의 오프셋에서 2바이트 값을 읽어 계산할 수 있다. 파일의 처음 100바이트헤더 영역(Header) 으로, 데이터베이스의 버전, 페이지 크기, 파일 포맷 등을 정의한다. 헤더 이후에는 테이블 구조, 인덱스, 트리거 등의 메타데이터가 SQL 쿼리 형식으로 저장되어 있다.

- 주요 페이지 : Lock-byte page: 잠금 상태를 저장하는 페이지 / Freelist page: 삭제된 페이지 목록을 관리 / Payload overflow page: 하나의 셀에 담을 수 없는 데이터를 이어서 저장 / B-tree page: 실제 데이터를 저장하거나 정렬 구조를 유지

- B-tree Page 구조 : SQLite에서 대부분의 데이터는 B-tree 구조를 통해 저장된다. Interior page: 하위 페이지의 위치 정보만 저장 (데이터 직접 저장 안 함). Leaf page: 실제 데이터 레코드를 저장. 페이지의 첫 번째 바이트(offset) 를 통해 페이지 유형을 확인할 수 있다. 페이지 내부에는 Cell Offset Array가 존재하며, 각각의 cell이 저장된 위치를 2바이트 단위로 저장한다. Free space는 cell 사이 또는 offset array와 cell 사이에 존재할 수 있으며, 데이터가 삭제되면 해당 영역에 빈 공간이 남게 된다.

- Cell 구조 (SQLite 최소 저장 단위) : Cell Header: 레코드의 전체 길이, row ID 등의 정보 / Data Header: 데이터 타입 및 필드 수를 정의 / Data Area: 실제 데이터가 저장되는 공간. 데이터가 삭제되면 해당 cell의 헤더 일부가 사라지고, data 영역은 free space로 처리된다. 

 

2) RollBack 저널 

트랜잭션 진행 중 데이터베이스 파일을 초기 상태로 복원하는데 사용되는 정보를 저장한다. 항상 DB와 같은 경로에 생성된다. DB의 트랜잭션이 commit 되면, delete 모드는 journal 파일을 삭제한다. truncate 모드는 journal 파일에 사이즈를 0으로 만들고, persist 모드는 journal 파일의 헤더 부분을 0으로 초기화한다. 

트랜잭션 : 데이터베이스에서 하나의 논리적 작업 단위를 의미한다. 예시로 카카오톡에서 메시지를 보냈을 때 해당 메시지가 DB에 저장되는 전 과정이 트랙잭션이다. 

- 트랜잭션의 4대 특성 : ACID - 원자성(작업이 모두 실행되거나 하나도 실행되지 않아야 함), 일관성(트랜잭션 전후 데이터는 항상 일관성 유지), 격리성(동시에 여러 트랜잭션이 실행돼도 서로 간섭하지 않음), 지속성(트랜잭션 완료 후 시스템 오류가 나도 결과는 보존됨)

 

3) WAL 저널 

write-ahead log

SQLite의 일관성을 유지하기 위해 journal 파일을 생성하는 모드

DB 연결 시 생성되고, 연결이 끊어질 때 삭제된다. WAL 모드는 데이터 조작 명령이 발생하면 원본 데이터는 기존 DB에 보존되고 변경 사항을 WAL 파일에 저장한다. 

 

2. Journaling of Journal 기반 SQLite 파일 복구 기법 

1) 카빙 

전수조사 : 대상 영역, 집합 전체를 하나하나 전부 조사하는 조사방법

파일 시스템 정보 없이도 디지털 저장장치에서 파일 조각들을 찾아내는 기법을 말한다. 삭제되었거나 손상된 파일을 복구할 때 자주 사용된다. 

 

2) Journalign of journal 이상

안드로이드 운영체제에서 발생

Journaling 작업 과정에서 데이터가 중복되는 현상 

 

3) ext4 

안드로이드 ext4 : ‘Journaling of journal’ 같은 현상은 보통 복수의 저널이 겹쳐 기록되거나 복구 과정 중 문제가 생겨 시스템 로그가 꼬이는 현상

 

iOS 

APFS : CoW 기법 (데이터 수정 시 새 블록에 복사한 후 수정해서 메타데이터 업뎃)

iOS 앱 데이터는 Sandbox 내부에 저장되며 대부분 SQLite DB로 구성된다. 

삭제된 데이터는 DB 내부에서 흔적이 남을 수 있고, WAL(Write-Ahead Logging) 파일이나 SHM(Shared Memory) 파일도 함께 분석하면 복구 가능성이 올라간다. 

sandbox 구조 : iOS 보안의 핵심 개념. 각 앱이 서로 완전히 독립된 환경에서만 동작하도록 격리하는 구조.

- 앱은 자신만의 디렉토리 구조 안에서만 파일을 읽고 쓸 수 있다. 다른 앱의 파일, 데이터, 메모리 등에 접근 절대 불가. 시스템 영역에서도 접근할 수 없다(비탈옥시).

 

1. SQLite 기본 구조 

main DB file : .sqlite, .db

WAL : 트랜잭션 중인 데이터가 임시 저장되는 로그

SHM : WAL 관련 shared cache 정보

Journal file : SQLite의 전통적 저널링 방식

페이지 기반 구조를 가짐 - Header(DB 파일의 식별 정보 및 페이지 크기 등), Page(1페이지 = 테이블 b-tree 또는 인덱스 등), Record(실질적인 row 데이터 저장), Free List(삭제된 페이지의 참조 정보)

 

2. Snapshot

Snapshot : APFS의 핵심 기능. 파일 시스템의 특정 시점 상태를 논리적으로 보존. 내부적으로 변경 전 블록을 참조하므로 과거 데이터가 살아있다.

iOS의 APFS는 CoW 특성 상 Snapshot을 통해 과거 시점의 DB 파일을 복구할 수 있다 (.snapshots 폴더)

안드로이드처럼 명시적인 저널 파일은 생성되지 않는다. 유사한 보호 효과는 존재하고 snapshot이나 복제된 블록 형태로 남는 데이터가 forensic 분석 대상이 될 수 있다.

Orphaned blocks/unreferenced data : 파일을 수정했지만 다른 구조에 의해 간접적으로 참조되는 블록. raw 분석을 통해 카빙 가능.

VMEM/Memory 이미지 활용 : CoW 중간 상태나 아직 커밋되지 않은 I/O 작업은 메모리나 swap 공간에 존재할 수 있다.