Digital Forensics/Windows Registry

vk 셀 복구하기

geunyeong 2020. 4. 18. 00:21

2019 DFC AF 200 문제는 하이브 파일의 레지스트리를 복구하고, 복구한 레지스트리에서 숨어 있는 파일을 찾아내는 문제였다. vk 셀 복구하는 방법을 AF 200 문제로 알아보자.

 

하이브 파일은 레지스트리 헤더와 여러 개의 하이브 빈 파일로 이루어져있다. 하이브 빈은 또 여러 개의 셀을 포함하고 있다. 셀은 레지스트리에서 키와 값을 저장하는 구조체다. 종류에 따라 각각의 시그니처를 가지고 있는데, 키를 의미하는 셀은 nk라는 시그니처를, 값을 가지고 있는 셀은 vk라는 시그니처를 가지고 있다.

 

010 Editor로 2019 DFC AF200 문제로 주어진 하이브 파일을 열면 레지스트리 헤더와 하이브 빈 구조들을 볼 수 있다. 하이브 빈 구조들은 시작 오프셋 값이 모두 0x1000(4096)의 배수인 걸 볼 수 있다. 블록의 크기가 0x1000이기 때문이다. 하나의 하이브 빈은 여러 블록을 가질 수 있다.

 

레지스트리 헤더에는 ROOT 노드 키 헤더의 위치(Pointer to first key record)를 상대적 위치 값으로 나타내주는 멤버가 있다. 이 위치 값은 첫번째 하이브 빈이 위치하는 0x1000부터의 상대적 위치이므로, 실제 ROOT 노드 키는 0x1020 오프셋에 존재한다.

 

첫번째 하이브 빈인 0x1000 위치에서 앞서 본 0x20을 더한 0x1020에 ROOT 노드 키가 존재하는 걸 볼 수 있다. 이처럼 하이브 파일은 대부분의 오프셋 값을 첫번째 하이브 빈 오프셋인 0x1000을 기준으로 두고 있다.

 

REGA로 "Last one!"이라는 키를 확인해보면 "(default)" 값에 $$$Golden-Chamber$$$가 2개의 보물을 가지고 있다는 메시지를 담고 있다.

 

$$$Golden-Chamber$$$ 근처에 REGA로는 보이지 않던 vk 셀이 있다. "1.BITMAPFILEHEADER"라는 vk 셀인데, Size 값을 보면 양수다. 셀은 Size 필드까지 합하여 자신의 크기를 음수로 표현한다. 양수로 표시되어 있다는 건 해당 셀이 위치한 공간은 free 상태라는 의미로, 사용하지 않는다는 뜻이다.

 

"1.BITMAPFILEHEADER" vk 셀의 Padding을 보면 vk라는 시그니처와 "2:BITMAPINFOHEADER+PALETTE"라는 문자열을 볼 수 있다. 하이브 파일 내에서 서로 인접한 위치에 있는 여러 vk 셀이 모두 free되면 이들을 모두 합하여 비할당 셀의 크기를 증가시킨다. 쉽게 말해 안 쓰는 셀들을 묶어서 하나의 큰 빈 공간으로 만드는 것이다. 그래서 "2:BITMAPINFOHEADER+PALETTE" vk 셀이 "1.BITMAPFILEHEADER" vk 셀과 합쳐져 있다.

 

"1.BITMAPFILEHEADER" vk 셀의 Size 값이었던 208은 16진수로는 0xD0이다. 이를 Signed Byte로 표현하면 -48이다. Signed Int 형 -48(0xFFFFFFD0)로 변경하고 템플릿을 재적용하면 "2:BITMAPINFOHEADER+PALETTE" vk 셀이 인식된다. "2:BITMAPINFOHEADER+PALETTE" vk 셀의 Size 값도 음수로 변경한다.

 

하지만 아직 REGA로 두 값이 인식되지 않는다. 

 

nk 셀의 ValueCount와 ValuelistOffset이 설정되어 있어야 vk 셀들이 인식될 수 있다. 어느 nk 셀이든 큰 상관은 없지만 $$$Golden-Chamber$$$ nk 셀을 위 두 vk를 포함하는 키 노드로 써보겠다.

 

nk 셀이 자신이 가지는 vk 셀을 가리키는 방법은 위 그림과 같다. nk->ValuelistOffset이 가리키는 오프셋에 리스트 크기를 음수로 표현한 4바이트 Size 필드가 있고 그 뒤로 vk 셀의 오프셋 값을 가지는 4바이트가 nk->ValueCount 값 만큼 존재한다.

하이브 파일의 모든 오프셋은 첫번째 하이브 빈인 0x1000을 기준으로 상대적인 오프셋 값을 가지므로 nk->ValuelistOffset이 가리키는 0x7820에 0x1000을 더한 0x8820 오프셋에 value list가 위치한다. value list가 가리키는 vk 셀 오프셋 값도 마찬가지다.

 

파일 내 사용하지 않는 적당한 공간에 순서대로 -12, "1.BITMAPFILEHEADER" vk 셀의 오프셋, "2:BITMAPINFOHEADER+PALETTE" vk 셀의 오프셋 값을 넣어줬다. 여기서 또 주의해야 할 것은 누누히 말했지만 첫번째 하이브 빈인 0x1000으로부터 상대적인 오프셋 값을 사용하므로 파일 내 실제 오프셋에서 0x1000 만큼 뺀 값을 사용해야 한다. 때문에 "1.BITMAPFILEHEADER" vk 셀의 오프셋 값으로 0x5A60을 넣었고, "2:BITMAPINFOHEADER+PALETTE" vk 셀의 오프셋 값으로 0x5AB0를 넣었다.

 

value list를 만들었으니 nk 셀이 해당 value list를 참조하게 만들어야 한다. $$$Golden-Chamber$$$ nk 셀의 ValueCount를 2로, ValuelistOffset을 value list의 오프셋 값으로 설정한다. 이 역시 0x1000을 뺀 값을 넣어준다. value list의 오프셋 값이 0x6B20이므로 nk->ValuelistOffset의 값은 0x5B20이어야 한다.

 

수정 내용을 저장하고 REGA로 다시 열어보면 $$$Golden-Chamber$$$ 키 밑에 "1.BITMAPFILEHEADER" 값과, "2:BITMAPINFOHEADER+PALETTE"값이 생겨난 걸 볼 수 있다. 

 

같은 방법으로 "3,PIXELS" vk 셀도 복구해낼 수 있다. 다만 데이터 크기가 너무 큰 탓에 제대로 보이지 않아 그냥 파일 내에서 vk->DataOffset이 가리키는 곳으로 가 바이너리 데이터를 추출하는 것이 더 나아 보인다. 

 

 

 

* ref

http://www.sentinelchicken.com/data/TheWindowsNTRegistryFileFormat.pdf