File Forensic/File Analysis

[Digital Forensic] SQLite Recovery Analysis (Non-Secure Delete)

DF_m@ster 2024. 1. 18. 14:00

Event Analysis

먼저 SQLite의 Record 생성, 삭제, 복구 이벤트 분석에 사용할 SQLite를 생성하였다. 아래는 SQLite 내부 테이블의 모습으로, 테이블은 하나만 존재한다.

Test SQLite Table

 

 

 

SQLite의 Record 이벤트 분석 과정은 다음과 같다. Record의 생성, 삭제, 복구 이벤트 발생 이전의 SQLite 파일을 저장하고, 추가로 이벤트 발생 이후의 파일을 추가 저장하여 두 파일을 비교분석하였다.

1. Record 생성

기존의 1, 2, 3번 3개의 Record에 추가적으로 Record('Choi', '2023004', 'Software')를 생성하였다.

Record 생성

 

아래는 각각 Record 생성 전, 후의 Header Page 모습이다. 변화한 데이터는 색으로 표시하였다.

 

주요 확인 가능 정보

File Change Counter: 0x03  0x04

  SQLite 파일 수정 횟수 '1' 증가.

Record 생성 전
Record 생성 후

 

아래는 각각 Record 생성 전, 후의 Page Header 모습이다.

주요 확인 가능 정보

Number of Record: 0x03  0x04

 → Table의 Record 개수가 3개에서 4개로 증가.

Offset of First Bytes of Record: 0x0FB7  0x0F9E

 → B-Tree 정렬에 의한 첫 레코드 변화.

Cell Pointer: '0x0F9E' 추가

 → 새롭게 생성한 레코드를 저장하는 Cell이 생성되면서 해당 Cell의 Pointer가 새롭게 생성됨.

Record 생성 전
Record 생성 후

 

아래는 각각 Record 생성 전, 후의 Cell Data 모습이다.

주요 확인 가능 정보

Cell: '0x0F9E' 추가

 새롭게 생성한 레코드를 저장하는 Cell이 새롭게 생성됨.

Record 생성 전
Record 생성 후

 

 

 

2. Record 삭제

기존의 1, 2, 3, 4번 4개의 Record에 3번 Record('Lee', '2023003', 'Security')를 삭제하고 저장 이후에, 추가적으로 1번 Record('Kim', '2023001', 'Software')를 삭제하였다.

3번 Record 삭제
1번 Record 삭제

 

아래는 각각 Record 삭제 전, 3번 Record 삭제 후, 1번 Record 삭제 후의 Header Page 모습이다. 변화한 데이터는 색으로 표시하였다.

 

주요 확인 가능 정보

File Change Counter: 0x04  0x05 0x06

  SQLite 파일 수정 횟수 '1' 증가.

Record 삭제 전
3번 Record 삭제 후
1번 Record 삭제 후

 

아래는 각각 Record 삭제 전, 3번 Record 삭제 후, 1번 Record 삭제 후의 Page Header 모습이다.

주요 확인 가능 정보

Number of Record: 0x04  0x03 0x02

 → Table의 Record 개수가 4개에서 3개로, 3개에서 2개로 감소.

Offset of First Free Sapce: 0x0000  0x0FB7

 → 삭제한 Record를 포함하는 Cell이 가용상태로 변하게 되는데, 이때 Row ID가 높은 Cell의 시작 주소를 저장.

  '0x0FB7'는 3번 Record('Lee', '2023003', 'Security')의 Cell 시작 주소이다.

Cell Pointer: '0x0FB7' 삭제 '0x0FE8' 삭제

 → 새롭게 삭제한 레코드를 저장하는 Cell의 Pointer를 제거하고, 유효한 Cell의 Cell Pointer 들로 다시 정렬함.

  때문에 Number of Record의 범위를 넘어가는 Cell Pointer가 남아있는 모습을 확인할 수 있다.

Record 삭제 전
3번 Record 삭제 후
1번 Record 삭제 후

 

아래는 각각 Record 삭제 전, 3번 Record 삭제 후, 1번 Record 삭제 후의 Cell Data 모습이다.

 

특정 Record를 삭제하면, 해당 Record를 포함하는 Cell의 첫 4 Byte가 다른 데이터로 변경되고, 나머지 값은 그대로 유지된다. 이때 첫 2 Byte는 가용상태가 된 다음 Cell의 Cell Pointer 정보이고, 두 번째 2 Byte는 해당 Cell의 전체 길이 정보이다. 

 

주요 확인 가능 정보

3번 Cell: '0x16 03 04 13'  '0x00 00 00 18'  '0x0F E8 00 18'

  첫 2 Byte가 0x00 00으로 변함. 또 다른 가용상태(삭제된) Cell의 정보가 없기 때문.

  두 번째 2 Byte가 0x00 18로 변함. 해당 Cell의 길이가 0x18 임을 의미. 이전의 Record Size가 0x16인 점을 고려하면 추가 검증이 된다.

  첫 2 Byte가 0x0F E8으로 변함. 또 다른 가용상태(삭제된) Cell의 Cell Pointer가 '0x0F E8'임을 의미. 1번 Record를 포함하는 Cell의 Cell Pointer 임을 확인할 수 있다.

1번 Cell: '0x16 01 04 13'  '0x00 00 00 18'

  첫 2 Byte가 0x00 00으로 변함. 또 다른 가용상태(삭제된) Cell의 정보가 없기 때문.

  두 번째 2 Byte가 0x00 18로 변함. 해당 Cell의 길이가 0x18 임을 의미. 이전의 Record Size가 0x16인 점을 고려하면 추가 검증이 된다.

Record 삭제 전
3번 Record 삭제 후
1번 Record 삭제 후

 

 

 

3. Record 복구

기존의 1, 2번 2개의 Record에서 삭제된 Record를 복구하였다. 아래의 복구 과정은 삭제된 레코드가 해당 테이블에 존재했는지 여부를 알지 못하는 상태를 전제로 복구하는 과정을 서술하였다.

Record 복구

 

아래는 삭제된 Record를 수동복구하는 과정이다.

 

1. 첫 번째 가용상태인 Cell의 Cell Pointer 값을 확인

Page Header에서 Offset of First Bytes of Record은 해당 Table의 첫 번째 가용상태인 Cell의 Cell Pointer 값이기 때문에 가용상태인 Cell에 접근할 수 있다.

 

주요 확인 가능 정보

Offset of First Free Sapce: '0x0FB7'

  가용상태인 Cell이 존재하며 그중 첫 번째 Cell의 시작 주소는 '0x1FB7'이다.

Number of Record: 0x02

 Number of Record 값이 0x02인데, Cell Pointer가 4개 존재하는 것으로 보아, 4개의 Cell이 있었으나 2개의 Cell이 삭제되었음을 유추할 수 있다.

Page Header의 Offset of First Free Sapce

 

2. 첫 번째 가용상태인 Cell에 접근하여 첫 2 Byte 값을 확인

Offset of First Bytes of Record로 접근한 첫 번째 가용상태 Cell의 첫 2 Byte는 추가적인 가용상태의 Cell Pointer 값이기 때문에 추가적인 가용상태의 Cell에 접근할 수 있다. 만약 2 Byte의 값이 '0x00 00'라면 해당 테이블에 더 이상의 가용상태인 Cell이 없음을 의미한다.

 

주요 확인 가능 정보

첫 번째 가용상태 Cell의 첫 2 Byte: '0x0FE8'

  추가적인 가용상태인 Cell(두 번째 가용상태 Cell)이 존재하며, 해당 Cell의 시작 주소는 '0x1FE8'이다.

두 번째 가용상태 Cell의 첫 2 Byte: '0x0000'

  추가적인 가용상태인 Cell이 존재하지 않음.

가용상태 Cell Pointer

 

3. 확인 한 정보로 Page header의 값을 복구

 

주요 확인 가능 정보

Offset of First Bytes of Record: 0x00 00

 Offset of First Bytes of Record 값을 '0x00 00'으로 변경하여, 가용상태인 Cell이 없는 상태로 변경한다.

Number of Record: 0x02  0x04

 → 발견된 가용상태의 Cell의 개수가 2개이므로, Table의 Record 개수를 2개에서 4개로 변경한다.

Cell Pointer: 순차적으로 '0x0FB7', '0x0FE8'을 추가한다.

 발견된 가용상태의 Cell의 시작 주소가 각각 '0x0FB7', '0x0FE8'이기 때문이다.

Record Page Header 복구 전
1, 3번 Record Page Header 복구 후

 

4. Cell의 첫 4 Byte 값을 복구

 

주요 확인 가능 정보

첫 번째 가용상태인 Cell의 첫 4 Byte: '0x0F E8 00 18'  '0x16 03 04 13'

  1 Byte (Record Size): 0x16 = 0x18(Cell Size) - '0x02'(Record Size Byte + Row ID Byte)

  1 Byte (Row ID): 0x03

  1 Byte (Size of Data Header): 0x04 = '0x1FBD'(Cell Data 1의 주소) - '0x1FB9'(Cell Pointer + 0x02)

  1 Byte (Size of Cell 1): 0x13 = ('0x03'(Cell Data 1의 Size) x 2) + 0x0D (odd) (역산)

두 번째 가용상태인 Cell의 첫 4 Byte: '0x00 00 00 18'  '0x16 01 04 13'

  1 Byte (Record Size): 0x16 = 0x18(Cell Size) - '0x02'(Record Size Byte + Row ID Byte)

  1 Byte (Row ID): 0x01

  1 Byte (Size of Data Header): 0x04 = '0x1FEE'(Cell Data 1의 주소) - '0x1FEA'(Cell Pointer + 0x02)

  1 Byte (Size of Cell 1): 0x13 = ('0x03'(Cell Data 1의 Size) x 2) + 0x0D (odd) (역산)

Cell 복구 전
1, 3번 Cell 복구 후

 

 

 

이전 글

[Digital Forensic] SQLite Structure Analysis

 

[Digital Forensic] SQLite Structure Analysis

SQLite SQLite: 서버 없이도 동작하는 로컬 데이터베이스 관리 시스템으로, 다양한 환경에서 널리 사용된다. 본 글은 SQLite의 구조를 디지털 포렌식의 관점(삭제, 복구, 복구 가능 여부)에서 바이너리

digitalforensicmaster.tistory.com

 

 

 

 

 

 

 

Reference

https://www.dbpia.co.kr/journal/articleDetail?nodeId=NODE01646088

 

SQLite 데이터베이스의 비 할당 영역에 잔존하는 삭제된 레코드 복구 기법 | DBpia

전상준, 변근덕, 방제완, 이근기, 이상진 | 정보보호학회논문지 | 2011.06

www.dbpia.co.kr