2016년 11월 22일 화요일

일반적인 분석으로 못 얻는 증거 획득


[Tech Report] 일반적인 분석으로 못 얻는 증거 획득



  • AhnLab


  • 2013-05-07

[안드로이드 포렌식3] 삭제 파일 분석부터 비할당 영역 카빙까지

 


디지털 포렌식 영역에서 점차 중요성이 커지고 있는 스마트폰 포렌식. 그 중에서도 안드로이드 운영체제(OS) 포렌식에 대해 월간 안 3월호를 시작으로 자세히 다루고 있다.



지난 4월호에선 안드로이드 포렌식 분석을 위한 디지털 정보의 ‘물리적’ 수집 방법에 대해 살펴보았다. 또 획득한 증거에 대한 분석법도 알아보았다. 이번 호에서는 안드로이드 기기에서 사용하는 NAND 플래시 메모리(Flash Memory)에 대한 이미지 생성과 분석 방법을 살펴보도록 하겠다.



 <연재 목차>

1부 : 안드로이드 OS, 숨겨진 속살을 파고들다(월간 안 3월호)

2부 : ‘디지털’ 증거의 ‘물리적’ 수집(월간 안 4월호)

3부 : 일반적인 분석으로 못 얻는 증거 획득(이번 호)

 

안드로이드의 운영체제는 기기의 NAND Flash메모리(이하 NAND Flash)에 설치돼 동작한다. 운영체제와 응용프로그램이 생성한 데이터도 NAND Flash에 저장된다. 이 때문에 기존 디지털 포렌식 조사 과정에서 쓰인 하드 디스크의 이미지를 생성해 분석하는 것과 마찬가지 개념으로, 안드로이드 NAND Flash 이미지를 생성해 분석하는 과정이 필요하다. 분석가들은 이렇게 생성한 이미지를 활용해 삭제 파일에 대한 분석과 비할당 영역에서 카빙 작업을 수행할 수 있으며 일반적인 분석으로는 얻을 수 없는 증거를 획득하게 된다.



안드로이드 기기로부터 NAND Flash 이미지를 생성하는 방법은 크게 두 가지다. JTAG(하드웨어 장비)를 통하는 하드웨어적 방법과 운영체제의 장치 파일에 접근하는 소프트웨어적 방법이 그것이다. 이번 호에서는 소프트웨어적 방법을 다루고자 한다.

 



안드로이드 파트션 구성은?

 

안드로이드 운영체제는 기본적으로 기기의 NAND Flash를 파티션 단위로 나누어 사용한다. 아래 표는 안드로이드 운영체제의 기본 파티션들에 대한 설명이다.

 

 

[표 1] 안드로이드의 기본 파티션

 

먼저 misc 파티션은 안드로이드 운영체제가 디바이스 관리를 위해 사용하는 플래그들을 저장한다. 부트(boot) 파티션은 일반적인 운영체제 부팅에 사용되는 파티션으로 부트 코드와 커널이 존재한다. 리커버리(recovery) 파티션에는 리커버리 모드로 부팅할 경우 사용되는 코드와 함께 백업 및 복구에 사용되는 코드가 존재한다. 이들 세 파티션은 마운트가 돼 있지 않아 일반적인 방법으로는 접근이 어렵다.



시스템(system) 파티션에는 시스템 파일과 기본적인 응용프로그램 등 모든 시스템 정보들이 저장되며 읽기 전용으로 마운트돼 있다. 기본 파일 시스템은 OS 2.3 이전엔 YAFFS2였고 2.3부터 Ext4 파일 시스템을 사용한다. 또 userdata 파티션에는 ‘사용자 데이터’가 저장되며 시스템 파티션과 동일한 파일 시스템을 사용한다. 사용자 데이터란, 사용자가 기본 응용프로그램을 비롯해 모든 응용프로그램을 사용하면서 생성하는 데이터다.



이에 따라 디지털 포렌식 관점에서 중요한 데이터는 모두 userdata 파티션에 저장된다고 볼 수 있으며, 이번 호에서도 바로 이 파티션에 대해 이미지 생성과 분석을 진행하려 한다.

 



안드로이드 기기 저장매체 NAND Flash 구성



안드로이드 기기의 저장매체로 사용되는 NAND Flash는 기본적으로 페이지, 스페어, 블록 단위로 구성된다. 페이지는 실제 데이터가 저장되는 영역을 말한다. 또한 페이지 영역과 쌍으로 스페어 영역이 존재하는데, 스페어 영역에는 쌍을 이룬 페이지의 메타 데이터가 저장된다.



스페어 영역에 저장되는 메타 데이터는 NAND Flash 전용 파일 시스템이나 하드웨어 컨트롤러가 페이지를 조합할 때 필요한 정보를 뜻한다. NAND Flash는 읽기/쓰기의 수명이 정해져 있어 NAND Flash 전체를 최대한 균등하게 사용하도록 파일 시스템과 컨트롤러가 조정하는 역할을 한다. 이런 작업을 ‘Wear Leveling’이라고 부른다.



따라서 하나의 데이터는 NAND Flash 안에 여러 조각으로 나눠져 균등하게 저장되고 해당 데이터를 다시 가져올 때, 하나로 조합하는 작업이 필요하다. 이때, 컨트롤러가 스페어 영역에 있는 메타 데이터를 바탕으로 조각난 데이터들을 조합해 하나의 데이터를 만든다. 블록은 페이지들의 집합이다. 블록을 이루는 페이지의 개수는 제조사마다 다르다. 읽기/쓰기 작업은 페이지 단위로 수행되며 삭제는 블록 단위로 수행된다.



안드로이드 운영체제가 NAND Flash에 접근하는 것은 두 가지 방식이 있다. MTD(Memory Technology Device)를 통한 직접 접근 방식과 FTL(Fash Translation Layer)을 거쳐 접근하는 방식이다.

 



NAND Flash 접근 방식 MTD



MTD는 기존 하드디스크와 같은 블록 장치와 다른 NAND Flash 장치에 접근하기 위해 사용하는 장치 드라이버다. 때문에 MTD를 통해 NAND Flash에 직접 접근이 가능하다.



YAFFS2와 같은 NAND Flash 전용 파일 시스템은 NAND Flash의 스페어 영역에 파일 시스템의 메타 데이터를 기록해야 한다. 이 경우, 파일 시스템은 MTD를 통해서 스페어 영역에 직접 접근해 메타 데이터를 기록하고 파일 시스템을 구성한다. 다음 [그림 1]은 YAFFS2와 같은 NAND Flash 전용 파일 시스템을 사용할 경우 파일 시스템과 NAND Flash 간의 데이터 흐름을 나타낸다.

 



[그림 1] YAFFS2의 데이터 흐름도

 

 

또 다른 접근 방식 FTL



FTL은 NAND Flash 장치에서 기존의 블록 장치 전용 파일 시스템이 동작하도록 지원하는 계층이다. 안드로이드 2.3의 표준 파일 시스템인 Ext4나 삼성의 RFS 파일 시스템과 같은 블록 장치 전용 파일 시스템들은 모두 FTL과 통신을 한다.

 

이에 따라 FTL을 사용하면 NAND Flash의 Wear Leveling이나 스페어 영역 관리는 FTL에서 수행되며 파일 시스템은 FTL하고만 통신을 한다. 이 경우, 파일 시스템은 NAND Flash의 스페어 영역에 직접 접근할 수 없다. [그림 2]는 Ext4나 RFS를 사용할 때의 파일 시스템과 NAND Flash 간의 데이터 흐름이다.



 

[그림 2] 블록 장치 전용 파일 시스템의 데이터 흐름

 

 

본격적인 이미지 생성



안드로이드 기기의 userdata 파티션 이미지를 생성하기 위해 루팅을 통해 관리자 권한을 확보하고 장치 파일에 접근해야 한다. 루팅은 앞서 월간 안 4월호에서 설명했듯, 포렌식에서 불가피하게 이용하는 것으로, 무분별한 루팅은 모바일 기기의 보안 등을 위해 바람직하지 않다. 관리자 권한을 확보했다면 다음으로 해당 파티션이 사용하는 파일 시스템을 확인해야 한다.

YAFFS2와 같은 NAND Flash 전용 파일 시스템을 사용한다면 MTD를 통한 이미지 방식을 사용한다. Ext4나 RFS와 같은 블록 장치 전용 파일 시스템일 경우엔 FTL을 통한 이미지 생성 방식을 택한다.

 



NAND Flash 전용 파일 시스템의 이미지 생성



Userdata 파티션의 파일 시스템이 YAFFS2라면 MTD를 사용해 NAND Flash와 통신하는 것으로 판단할 수 있다. 또한 이미지로부터 파일 시스템을 재구성하려면 이미지 안에 NAND Flash의 스페어 영역이 포함돼야 한다.



먼저 데이터(data) 파티션의 파일 시스템을 확인한다. ‘adb’ 명령의 ‘Shell’ 옵션을 통해서 기기에 접근한 뒤, ‘mount’ 명령을 통해 마운트 정보를 확인한다.

 



[그림 3] 마운트 정보 확인

 

위 [그림 3]에서 보듯 data 파티션이 YAFFS2를 사용하는 것을 볼 수 있다. 다음은 MTD 장치 파일을 통해 이미지 생성에 들어갈 차례다. 안드로이드 운영체제에서 MTD 장치 파일은 아래 그림처럼 ‘/dev/mtd/mtd[N]’ 형태로 저장된다.

 



[그림 4] ‘/dev/mtd/’ 경로 아래의 파일 구성

 

‘mtd[N]’은 읽기/쓰기가 가능한 장치 파일이며 ‘mtd[N]ro’는 읽기 전용 장치 파일이다. 해당 MTD 장치 파일을 어떤 파티션이 사용하는지 알기 위해선 ‘cat/proc/mtd’ 명령을 사용한다.

 



[그림 5] MTD 사용 파티션 확인



위 [그림 5]를 통해 userdata 파티션이 ‘mtd5’ 장치 파일을 사용함을 확인할 수 있다. 따라서 이미지를 생성하려면 ‘mtd5’ 장치 파일을 사용해야 한다.



일반적으로 리눅스 환경에서는 ‘DD 명령’을 통해서 장치 파일에 접근해 이미지를 생성한다. DD 명령은 블록 장치 전용 파일 시스템의 논리 이미지를 생성하는 명령으로, 파일 시스템의 논리적인 데이터 부분만 접근이 가능하다. NAND Flash에서 실제 논리 데이터가 저장되는 부분은 페이지이므로 DD 명령을 통해 생성한 이미지는 아래 [그림 6]에서처럼 페이지 영역만을 포함한다. 괄호 안 첫 번째 숫자는 블록 번호이며 두 번째 숫자는 페이지 번호다.



 

[그림 6] DD 명령을 통해 생성한 이미지

 

DD 명령으로 YAFFS2의 이미지를 위와 같이 생성하면 페이지 영역만 포함한 이미지가 생성된다. 이 이미지는 스페어 영역을 포함하고 있지 않기 때문에 파일 시스템을 재구축할 수 없다. 이 같은 상황에서 해당 이미지로 취할 수 있는 분석은 단순 문자열 검색 혹은 카빙 작업뿐이다. 스페어 영역을 포함한 YAFFS2 이미지를 생성하려면 MTD를 통해 직접 스페어 영역을 읽어오는 방식을 사용해야 한다.



실제 MTD에서 제공하는 인터페이스를 통해서 NAND Flash의 스페어 영역까지 읽어오는 여러 바이너리들이 존재한다. 대표적으로 ‘dump_image-arm’과 ‘nanddump’ 등이 있다. 이들 바이너리들은 MTD에서 제공하는 인터페이스를 통해 NAND Flash의 스페어 영역까지 모두 읽을 수 있어 페이지와 스페어 영역 모두를 포함한 이미지를 생성할 수 있다. 아래 [그림 7]은 바이너리 nanddump를 사용해 userdata 파티션의 이미지를 생성하는 예시이다.

 



[그림 7] nanddump 바이너리를 통한 이미지 생성

 

nanddump 바이너리를 통해 생성한 YAFFS2 이미지는 아래 [그림 8]과 같이 페이지와 스페어 영역 모두를 포함해 이미지로부터 파일 시스템 재구성이 가능하다.



 

[그림 8] nanddump를 통해 생성한 이미지

 

 

블록 장치 전용 파일 시스템의 이미지 생성

 

Userdata 파티션이 블록 장치 전용 파일 시스템(예: Ext3/4, RFS)을 사용한다면 해당 파일 파일 시스템은 FTL을 통해 NAND Flash와 통신한다고 볼 수 있다.



FTL은 NAND Flash의 스페어 영역을 해석해 페이지들을 조합한 뒤, 파일 시스템이 NAND Flash를 블록 장치처럼 보게 만든다. 이로 인해 FTL을 거쳐서 파일 시스템과 운영체제에 보이는 부분은 논리적인 부분이 된다. 이런 논리적인 부분 위에 블록 장치 전용 파일 시스템이 구성되기 때문에 DD 명령을 통해 파일 시스템 이미지를 생성하면, 파일 시스템 재구성이 가능해진다.



아래 [그림 9]는 국산 안드로이드 스마트폰의 userdata 파티션 이미지를 생성하는 과정이다. 이 기기의 마운트 정보를 확인해보면 dbdata 파티션의 파일 시스템이 RFS인 것을 확인할 수 있다. RFS는 블록 장치 전용 파일 시스템이므로, 장치 파일 경로인 ‘/dev/blcok/stl10’을 인자로 사용해 DD 이미지를 생성한다.

 



[그림 9] DD 명령어를 통해 RFS 이미지 생성

 

지금까지 NAND Flash 접근 방식에 따른 이미지 생성 방법을 알아보았다. 현재 대부분의 안드로이드 기기의 버전은 2.3 이상으로, Ext4를 기본 파일 시스템으로 쓰고 있어 DD 명령을 통한 이미지 생성이 가능하다. 그러나 2.3 이전 버전도 여전히 사용되고 있기 때문에 분석가들은 해당 버전 기기에 대한 이미지 생성 방법도 알고 있어야 한다.



이제부터는 NAND Flash 전용 파일 시스템인 YAFFS2에 대해 알아보려 한다. YAFFS2의 구조는 실제 NAND Flash 구조와 거의 동일해서 NAND Flash를 이해하는 데에 많은 도움이 된다.

 



NAND Flash 전용 파일 시스템 YAFFS2 특징



YAFFS2는 YAFFS(Yet Another Flash File System)의 다음 버전이다. 기본적인 특징은 YAFFS와 동일하며 속도가 개선됐다.

 

YAFFS2는 NAND Flash를 사용하기 위해 디자인된 유일한 파일 시스템으로, 시스템 안정을 향상시키기 위해 journaling, 에러 정정, NAND가 잘 일으키는 오동작을 알아내는 방법 등을 사용했다. 따라서 NAND Flash 위에서 빠르고 안정적으로 동작한다. 또한 YAFFS2는 높은 이식으로 인해 Linux, uClinux, Windows CE에서 동작이 가능하며 오픈소스 프로젝트다.



YAFFS2는 마운트 시 플래시 메모리 전체를 스캔해 파일 시스템 구조를 모두 메모리에 올려놓는 방식을 사용한다. 이러한 방식을 LFS(log-structured file system)라고 한다. 이 방식을 사용하면 플래시 메모리가 클수록 마운트 시간이 길어진다.



또 YAFFS2는 Inverse Mapping 방식을 사용한다. Inverse Mapping이란 파일 시스템을 구성하는 메타데이터들을 별도로 한곳에 모아 관리하는 게 아니라, 메타데이터들이 각 파일 안의 데이터에 포함하도록 하는 방식을 말한다. 이 방식을 사용할 경우 플래시 메모리에 유지해야 하는 정보의 양이 적은 데다가 데이터가 갱신되거나 파일과 디렉터리 간의 관계가 변경됐을 때, 플래시 메모리에서 갱신하는 정보의 양이 적다는 장점이 있다.

 

그러나 원하는 정보를 검색하기 위해서는 모든 플래시 영역을 검색해야 하는 단점이 있다. 이 같은 단점을 보완하기 위해 YAFFS2에서는 처음 마운트 시, 플래시에 있는 모든 메타데이터 정보를 메인 메모리에 로드해 파일을 검색함으로써 검색 속도를 높인다.

 



YAFFS2의 구조



YAFFS2는 Chunk와 태그(Tag)로 조합된 구조의 연속적인 나열로 구성돼 있다. 일반적인 Chunk의 크기는 2048바이트이고 태그의 크기는 64바이트다. 아래 [그림 10]은 YAFFS2의 구조를 나타낸 것이다.

 



[그림 10] YAFFS2 파일 시스템의 구조

 

Chunk는 NAND Flash의 페이지와 동일한 개념으로, 파일의 데이터와 파일/디렉터리 속성 정보를 저장한다. 파일 데이터를 저장할 Chunk를 데이터 Chunk라고 하고 파일/디렉터리 속성을 저장하는 Chunk를 헤더 Chunk라고 한다. 각 Chunk는 Object ID와 Chunk ID로 구분이 가능하다. Object ID는 해당 Chunk가 어느 파일에 속해 있는지 구분하는 정보이며, Chunk ID는 해당 Chunk가 파일 내에서 어디에 위치하는지에 대한 정보다. 두 정보 모두 뒤에 설명할 태그 안에 저장된다.



데이터 Chunk의 경우 Chunk ID가 ‘1’번부터 시작해 파일 끝까지 증가하며 파일의 데이터를 담고 있다. 헤더 Chnuk는 Chunk ID가 ‘0’번이고 Object Type, Parent Object ID, 파일 명 등 파일/디렉터리 속성을 저장한다. 다음 [표 2]는 헤더 Chnnk의 상세 정보다.

 

[표 2] 헤더 Chunk 정보

 

위의 표에 적힌 Parent Object ID는 해당 헤더 Chunk가 가리키는 파일이나, 디렉터리 객체의 부모(상위) 디렉터리 객체가 가지는 Object ID를 말한다. 또 여기서의 Object ID는 파일 시스템 내에서 파일이나 디렉터리 객체를 구분하기 위해 사용하는 유일한 식별 ID다. [그림 11]은 위 표를 바탕으로 분석한 ‘EmailProvider.db’ 파일의 헤더 Chunk다.

 



[그림 11] EmailProvider.db 파일의 헤더 Chunk

 

태그는 NAND Flash의 스페어와 동일한 개념으로, 해당 Chunk의 메타 데이터를 저장하며 Chunk 바로 아래에 위치한다. 또한 태그의 구조는 확장 태그(Extended Tag)와 일반 태그 구조로 나뉜다.



확장 태그는 기존 YAFFS의 태그 구조가 YAFFS2의 태그 정보를 모두 저장하지 못해 YAFFS2에서 추가된 구조다. Chunk ID가 '0'인 헤더 Chunk, 즉 파일 헤더와 디렉터리 헤더의 태그로 사용된다. 다음 [표 3]은 확장 태그의 상세 내용이다.

 

[표 3] 확장 태그 정보

 

다음 [그림 12]는 위의 표를 바탕으로 분석한 파일 헤더의 확장 태그의 예다.

 



[그림 12] 파일 헤더의 확장 태그의 예

 

위의 태그는 확장 태그이기 때문에 오프셋 12에 위치하는 확장 태그가 0x80인 것을 확인할 수 있다. 또 Object Type 값이 0x10이기 때문에 헤더 Chunk의 Parent Object ID 값을 확인할 필요가 없다. 일반 태그는 데이터 Chunk의 태그를 말한다. 다음 [표 3]은 일반 태그의 상세 정보다.

 

[표 4] 일반 태그의 상세 정보

 

[그림 13]은 [표 4]를 바탕으로 분석한 파일의 일반 태그의 예다.

 



[그림 13] 일반 태그의 예

 

[그림 13]의 일반 태그를 분석해 보면 태그가 가리키는 데이터 Chunk는 파일 내에서 0x1F번째 위치에 있으며 바이트 Chunk가 0x800(2048)이므로 Chunk의 최대 크기인 2048바이트를 모두 사용하고 있다는 것을 알 수 있다. 한 가지 주의할 점은 nanddump를 통해 덤프할 경우 위 태그 데이터들의 처음 2바이트 이후에 기록된다. 즉, 태그의 64바이트 내용을 분석할 시, 3바이트 위치부터 파싱을 시작해야 한다.



따라서 YAFFS2에서 파일 시스템을 구성할 때, NAND Flash 메모리에 있는 모든 헤더 Chunk와 태그들을 읽어 메인 메모리에 트리 형태로 구성하는 방식을 사용한다. 확장 태그를 통해 각 객체들 간의 계층 구조를 구성하고, 일반 태그를 통해 각 객체들의 실제 데이터 위치를 저장한다. 그런 다음 헤더 Chunk를 통해 각 객체가 가리키는 파일이나 디렉터리의 이름을 기록한다. [그림 14]는 YAFFS2가 NAND Flash의 데이터를 읽어 메인 메모리에 파일 시스템을 구성하는 과정이다.

 



[그림 14] YAFFS2 구성 과정

 

다음으로 YAFFS2에서 파일 입ㆍ출력이 일어났을 때의 동작 과정을 살펴보자. 이 과정은 NAND Flash의 동작 원리를 이해하는 데에 도움이 된다.

YAFFS2 동작 과정



블록당 4개의 Chunk(페이지)로 구성되는 간단한 NAND Flash가 있다고 가정하자. 이 NAND Flash 위에 YAFFS2가 구성돼 있다. 만약 새로운 파일이 하나 생성된다면 다음 [그림 15]와 같이 Chunk ID가 ‘0’인 파일 헤더 Chunk 하나가 기록된다.

 



[그림 15] 새로운 파일 생성 시 변화

 

그리고 해당 파일에 데이터를 기록하면 다음 [그림 16]처럼 데이터 Chunk들이 기록된다.



 

[그림 16] 파일 데이터 기록 시 변화

 

파일 데이터의 기록이 모두 끝나면 파일을 닫는데 이때, 파일 헤더 Chunk의 속성 데이터가 수정된다. NAND Flash는 덮어쓰기 작업을 하지 않으므로 새로운 파일 헤더 Chunk를 생성하고 기존 파일 헤더 Chunk는 비활성화한다. 새롭게 생성된 파일 헤더 Chunk는 기존에 있던 Chunk가 수정된 것이므로 시리얼 넘버(Serial Number)를 ‘1’ 증가시킨다.

 



[그림 17] 데이터 기록이 끝난 뒤 파일을 닫았을 시 변화

 

다음 과정은 파일을 다시 열고 첫 번째 데이터 Chunk의 내용을 수정하고 파일을 닫았을 경우다. 이 경우, 새로운 첫 번째 데이터 Chunk가 기록되고 시리얼 넘버를 ‘1’ 증가시킨다. 기존 첫 번째 데이터 Chunk는 비활성화한다. 그리고 파일의 내용이 바뀌었으므로 새로운 파일 헤더 Chunk를 생성하고 시리얼 넘버를 ‘1’ 증가시킨다. 기존 파일 헤더 Chunk는 비활성화시킨다.

 



[그림 18] 첫 번째 데이터 Chunk의 내용 수정 후 파일을 닫았을 때의 변화

 

만약 파일의 크기를 ‘0’으로 변경해 파일 안의 모든 데이터를 삭제하고 파일을 닫으면 아래 그림과 같이 모든 데이터 Chunk는 비활성화되고 새로운 파일 헤더 Chunk가 기록되면서 시리얼 넘버가 ‘1’ 증가한다.

 



[그림 19] 모든 데이터 삭제 후 파일을 닫았을 시 변화

 

그 다음으로 파일 이름을 변경하면 파일 헤더 Chunk의 내용만 수정되므로 새로운 파일 헤더 Chunk가 기록되고 기존 헤더 Chunk는 비활성화한다.

 



[그림 20] 파일 이름 변경 시 변화

 

이와 같이 YAFFS2에 입ㆍ출력 작업을 통해 수많은 비활성화된 Chunk들이 존재한다. 위 설명에서는 간단히 ‘Delete’ 칼럼에서 ‘Live’와 ‘Del’ 값으로 활성화된 Chunk와 비활성화된 Chunk를 구분했지만 실제로 YAFFS2 구조에는 활성/비활성화 Chunk를 구분하는 Flag가 존재하지 않는다. 이 때문에 파일 시스템은 활성화된 Chunk들로만 구성돼야 하므로 활성/비활성화 Chunk를 구분하는 방법이 필요하다.

 



YAFFS2 활성/비활성 Chunk 구분 방법



앞서 설명했듯 YAFFS2에는 수많은 비활성화 Chunk가 존재한다. 게다가 파일 시스템을 구성하려면 활성/비활성화 Chunk를 구분해야 한다.



YAFFS2에서는 활성/비활성화 Chunk를 구분하는 Flag 값이 없고 Chunk Sequence ID로 활성/비활성화 Chunk를 구분한다. 다시 말해 같은 Object ID와 Chunk ID를 가지고 있는 Chunk들 중 Chunk Sequence ID가 가장 큰 Chunk가 활성화된 Chunk이고 나머지 Chunk들은 모두 비활성화된 Chunk이다.



Chunk Sequence ID 정보는 별도로 기록되는 값이 아니다. Block Sequence ID를 통해 Chunk Sequence ID를 계산해야 한다. Chunk Sequence ID를 계산하는 방법은 다음과 같다.

 

Chunk Sequence ID = (Block Sequence ID X 블록당 Chunk 수) + 블록 내 Chunk의 offset

 

Block Sequence ID는 태그가 기록돼 있고 블록당 Chunk의 수는 이미지 스캔 시, Block Sequence ID가 같은 Chunk들의 수를 계산하면 된다. 블록 내 Chunk의 Offset은 Chunk가 블록 내 순차적으로 할당되는 사실을 이용해 계산한다. 이렇게 계산된 Chunk Sequence ID는 메인 메모리에 저장되고 활성/비활성화 Chunk 구분에 사용된다.



 

YAFFS2 이미지에서 삭제 데이터 복구



YAFFS2에서 파일을 삭제하면 삭제된 파일의 객체는 ‘unlinked’로 이름이 변경된다. 그 후 다시 ‘deleted’로 이름이 변경돼 deleted 디렉터리 아래로 이동한다. 하지만 실제 파일 데이터의 부분은 그대로 남는다. 즉, 헤더 Chunk의 파일 명과 부모 Object ID 값의 변화없이 그대로 남는 것이다. 이처럼 deleted 디렉터리로 옮겨진 파일들은 YAFFS2의 가비지 컬렉션 작업 시 완전히 삭제된다.



가비지 컬렉션은 YAFFS2 내에 남겨진 비활성화 Chunk들을 다시 사용하기 위해 블록 단위로 모은 후 삭제하는 작업이다. 삭제 작업이 완료된 블록들은 모두 ‘1’로 기록되고 비할당 영역으로 인식돼 쓰기 작업 시, 다시 할당돼 데이터가 기록된다. 이에 따라 삭제 파일의 데이터들은 파일 시스템 내에서 가비지 컬렉션 작업이 수행되기 전에 복구가 가능하다. 또 삭제된 파일의 Object ID와 동일한 헤더 Chunk 중 세 번째로 Chunk Sequence ID가 큰 헤더 Chunk가 존재하면 삭제된 파일의 파일명과 위치 정보도 복구할 수 있다.

 



[그림 21] YAFFS2 파일 삭제 과정

 

또 다른 삭제 데이터 복구 방법으로는 SQLite Record 카빙 기법이 있다. 앞서 설명한 바대로 YAFFS2 이미지에는 수많은 비활성 Chunk들이 존재한다. 때문에 이러한 비활성 Chunk에 존재하는 SQLite Record를 추출할 수 있다면 지난 월간 안 4월호에서 언급했던 SQLite 파일 내의 비할당 공간에서의 데이터를 복구하는 것보다, 훨씬 많은 양의 데이터를 복구할 수 있다.

 

이 같은 SQLite Record의 카빙 작업을 할 수 있는 도구는 ‘yaffs2PageAnalyzer’다. 해당 도구는 ‘DFRWS 2011 Forensic Challenge’에 참가한 한 대학의 연구 제출물에 포함돼 있으며 특정 사이트(http://sandbox.dfrws.org/2011/dfrc/)에서 다운로드가 가능하다. 아래 [그림 22]는 ‘yaffs2PageAnalyzer’를 사용해 YAFFS2 이미지 내의 SQLite Record를 카빙해 엑셀 파일로 출력해주는 모습이다.

 



[그림 22] ‘yaffs2PageAnalyzer’를 이용한 SQLite Record 카빙

 

지금까지 YAFFS2에 대한 전반적인 내용을 살펴보았다. YAFFS2는 NAND Flash 전용 파일 시스템이며 NAND Flash와 동일한 구조를 지닌다. 이로 인해 일반적으로 NAND Flash의 페이지들을 물리적인 컨트롤러가 조합한다면, YAFFS2에서는 Chnuk들의 조합을 소프트웨어 YAFFS2 드라이버가 담당한다. 앞서 설명한 YAFFS2의 구조와 원리를 충분히 이해했다면 NAND Flash의 구조와 원리를 이해하는 데에도 어려움은 없을 것이다. 그 외에 안드로이드에서 사용하는 또 다른 파일 시스템으로는 Ext4가 있지만 이번에는 생략하도록 하겠다.

 



이미지 분석 도구



위의 방법을 통해 생성한 안드로이드 NAND Flash 이미지는 ‘EnCase’라는 도구로 분석할 수 있다. 이 도구는 버전7부터 YAFFS2, Ext4에 대한 분석을 도와준다. 이후 진행되는 분석은 지난 호에서 소개한 ‘물리적 수집 데이터에 대한 분석’ 방식과 동일하다.

 



[그림 23] EnCase7을 통한 YAFFS2 이미지 분석

 

문제는 EnCase가 다소 고가의 제품이라는 점이다. 이 때문에 무료로 사용할 수 있는 도구인 ‘Slueth Kit’도 자주 사용된다. 이 도구는 콘솔 기반의 도구로 YAFFS2, Ext4 모두 지원해준다.

 



[그림 24] Slueth Kit을 통한 YAFFS2 이미지 분석

 

만약 Slueth Kit이 콘솔 기반이라 사용이 불편하다면 ‘Autopsy’를 이용하면 된다. Autopsy는 Slueth Kit의 모듈을 그대로 사용, GUI 환경에서 분석을 수행할 수 있도록 해준다. 현재 버전3까지 공개돼 있으며 버전3부터는 Slueth Kit을 설치하지 않고도 단독으로 사용이 가능하다.



 

[그림 25] Autopsy를 통한 Ext4 이미지 분석

 

위와 같은 도구들을 활용해 분석가는 NAND Flash 이미지 분석과 삭제된 파일의 복구, 비할당영역에 대한 카빙 작업을 수행한다. 이들은 일반적인 분석 작업으로 얻을 수 없는 증거를 획득할 수 있다는 점에서 이점이 있다.

 

이제까지 안드로이드 NAND Flash의 구조와 접근 방식, 이미지 생성 및 분석 방법을 살펴보았다. 여기에 추가로 대표적인 NAND Flash 전용 파일 시스템인 YAFFS2에 대해서도 알아보았다. 분석가 입장에서 안드로이드 NAND Flash의 이미지를 생성하는 것은 삭제된 데이터를 복구하기 위해 꼭 필요한 작업이다. 대부분의 데이터가 SQLite 데이터베이스에 저장되기 때문에 이미지의 비할당 영역에서 복구할 수 있는 SQLite Record의 데이터는 분석 결과에 결정적 영향을 미칠 수 있어서다. 이렇듯 이번에 살펴본 NAND Flash의 이미지 생성 및 분석은 안드로이드 분석에서 아주 중요한 영역을 차지한다고 할 수 있다.@










  • AhnLab 로고



  • 솔루션서비스팀 오정훈 연구원




이 정보에 대한 저작권은 AhnLab에 있으며 무단 사용 및 도용을 금합니다.

단, 개인이 비상업적인 목적으로 일부 내용을 사용하는 것은 허용하고 있으나, 이 경우 반드시 출처가 AhnLab임을 밝혀야 합니다.

기업이 이 정보를 사용할 때에는 반드시 AhnLab 의 허가를 받아야 하며, 허가 없이 정보를 이용할 경우 저작권 침해로 간주되어 법적인 제재를 받을 수 있습니다. 자세한 내용은 컨텐츠 이용약관을 참고하시기 바랍니다.

정보 이용 문의 : contents@ahnlab.com


댓글 없음:

댓글 쓰기