SWUFORCE/윈도우 포렌식

File Carving(+method)

hmyang444 2026. 5. 16. 21:56

 

파일 카빙( File Carving )이란?

파일 카빙은 파일 시스템의 메타데이터 없이, 파일 자체의 고유한 바이너리 시그니처(헤더와 푸터)를 기반으로 데이터를 추출하고 재조립하여 복구하는 디지털 포렌식 기술이다.

 

 

왜 파일 카빙이 필요한가?

  • 파일 시스템 손상: 디스크 래핑, 포맷, 비정상적인 종료 등으로 인해 파일 시스템 자체가 완전히 깨졌을 때
  • 의도적인 은닉: 범죄 용의자가 증거를 인멸하기 위해 파일 시스템 영역을 변조하거나, 파일 확장자를 강제로 변경했을 때 

--> CTF 문제를 제작할 때는 의도적으로 은닉 방법을 사용하게 됨!

  • 미할당 영역 분석: 삭제된 파일이 머물러 있는 디스크의 빈 공간에서 유의미한 데이터를 얻어야 할 때

 

파일 카빙에서 비연속적 할당

파일 카빙 문제에서 제일 중요하다고 볼 수 있는 것이 이 문제이다.

파일 카빙의 다양한 방법들인 시그니처 기반, 구조체 기반 카빙은 모두 파일 데이터가 디스크에 연속적으로 저장되어 있다는 가정하에 작동하는 것이다. 하지만 그렇지 않은 경우! 파일이 조각나서 저장되는 비연속적 할당이 발생한다면 문제가 생긴다. 

  • 문제점: 헤더 시그니처를 찾아서 데이터를 쭉 읽어가는데, 중간에 다른 파일의 데이터가 끼어있거나 진짜 데이터는 디스크의 다른 저 멀리 떨어져 있는 곳에 저장되어 있다면?
  • 결과: 복구된 파일이 깨지거나, 다른 파일과 섞여서 열리지 않는 현상이 발생함

 

시그니처 기반 파일 카빙

 

각 파일의 고유 시그니처를 이용해 파일을 카빙하는 방식

시그니처에는 헤더(Header)와 푸터(Footer)시그니처가 존재하는데, 이 시그니처를 이용해 파일의 종류를 파악한 후 숨겨진 데이터를 찾아내거나 복구할 수 있는 것이다.

 

<다양한 파일 시그니처>

 

 

CTF 문제 제작 아이디어

(1) 기본 시그니처 결합 

말그대로 두 가지의 시그니처를 결합하는 방식

정상적인 이미지 파일(egg.png) 뒤에 플래그가 적힌 파일(flag.zip)을 통째로 붙여버리는 방식

 

 

제작 방법

- 리눅스 명령어: cat egg,png flag.zip  >  chicken.png

- 윈도우: copy /b egg.png + flag.zip chicken.png

 

결과: 두 파일이 합쳐진 하나의 png 파일이 나온다

 

의도: 플레이어가 파일의 헤더를 보고 PNG인 걸 알았지만, HxD로 열어보니 맨 뒤에 ZIP 파일의 헤더 시그니처(50 4B 03 04)와 푸터가 있는 것을 발견하고, 이를 직접 잘라내거나(Carving) 카빙 툴을 돌려 획득하도록 하는 것

 

그렇다면 합쳐진 사진은 제대로 보이나??

찾아보니까 이미지 뷰어 프로그램들은 사진 파일을 열 때 파일의 전체 크기를 보지 않고, 오직 PNG 시그니처의 규칙만 보고 작동한다고 함! 그래서 그 뒤에 붙어있는 flag.zip 데이터가 무엇이든 간에, 이미지 뷰어 입장에서는 PNG의 IEND 뒤에 있는 데이터들은 쓰레기 데이터로 취급하기 때문에 무시하고 앞의 egg.png 사진만 깔끔하게 띄워준다!(이부분은 걱정X)

 

실행해보니까

jpeg 푸터 시그니처 이후 바로 zip파일 시그니처인 PK가 보임

압축해제하면..내가 넣어둔..과외자료ㅎ

 

무튼 이렇게 하면 됨--> 이렇게 만드는 건 쉬움!!

 

 

(2)  파일 구조체 변조 (훼손된 시그니처) 

헤더나 푸터 시그니처, 내부 크기 정보를 임의로 수정하는 방식

--> 내부 크기 정보도 예전에 풀었던 width랑 height 크기를 다르게 만들어서 flag 숨겨두고... 그런 문제가 기억나긴하네요...ㅎ

 

 

제작 방법(1) 

PNG 파일의 헤더(89 50 4E 47)를 AA BB CC DD 같은 엉뚱한 값으로 바꾸기

 

의도: 일반적인 자동 카빙 툴은 헤더 시그니처 기반이라 이 파일을 못 찾아낸다고 함. 하지만 이 이미지파일을 HxD로 훑어보다가, 파일 중간에 PNG의 청크 데이터(IHDR, IDAT 등) 구조를 발견하고 PNG파일인 것을 깨닫고 헤더를 복구한 뒤 카빙해가는 것

대충 느낌만 이렇게!

PNG의 헤더 시그니처를 아예 다른 값으로 없애버리고 IHDR, IEND 이런 정보만으로 찾을 수 있도록 하는거지

그대신 헤더를 망가뜨리면 해당 png파일은 형식이 이상하다고 열리지는 않음(이건 좀 많이 쉬울 수도 있겠다) 

아 그러니까 두 파일을 합친다고 생각을 하면, 처음 부분 말고 뒷 부분을 시그니처 훼손해도 괜찮겠다. 만약 첫 파일이 PNG파일이거나 이미지파일이면 깨지지는 않으니까

문제 자체가 푸는게 어렵지는 않은데 뒷부분에서 시그니처가 깨져있으면 자칫하면 못보고 지나칠수도

 

제작 방법(2) 

  1. 아래쪽에 플래그를 적어둔 이미지를 만들고, 아래쪽 공간에 플래그를 배치한다.
  2. HxD로 이 파일을 열면 맨 앞 헤더 바로 뒤에 IHDR 문자열이 보인다.
  3. IHDR 글자 바로 뒤쪽을 보면 가로 크기(4바이트)와 세로 크기(4바이트)데이터가 순서대로 들어있다.
  4. 예를 들어 세로 크기 값이 바이너리로 00 00 03 E8(십진수 1000)로 되어 있다면, 이걸 00 00 02 BC(십진수 700) 정도로 줄여서 덮어쓰는 것

    문제 만들 시 중요한 사항!!!
    PNG는 데이터 무결성을 위해 청크마다 CRC(오류 검증 코드)를 쓴다.
    즉, 크기를 강제로 바꾸면 CRC 에러가 나서 아예 사진이 안 열릴 수 있으므로 파이썬 스크립트로 조작된 세로 크기에 맞게 CRC 값까지 새로 계산해서 수정해줘야하는 것을 잊지 말기!!

krita(그림판) 이용

가로 800, 세로 1000픽셀짜리 흰색 이미지를 만들고 flag를 700 밑에다가 써줌

hxd로 열어주고 너비, 높이 확인해주기

00 00 02 BC (700을 뜻하는 16진수)로 높이 부분을 저장해줌(700으로) 

 

오 운이 좋아서 화면이 깨지지는 않았음

그치만 CRC를 꼭 맞춰줘야 함!!

import zlib
import struct

#세로 크기 조작한 hide.png 파일을 바이너리로 읽어오기
F = open("hide.png", "rb")
D = F.read()
F.close()

#크기를 조작한 IHDR 청크 데이터 영역만 떼어냄
IHDR_DATA = D[12:29]

NEW_CRC = zlib.crc32(IHDR_DATA)

NEW_CRC_BIN = struct.pack(">I", NEW_CRC)


CHALLENGE_FILE = D[:29] + NEW_CRC_BIN + D[33:]
F = open("challenge.png", "wb")
F.write(CHALLENGE_FILE)
F.close()

플레이어가 hxd로 열어서 크기를 조정해주면(어느정도 몇번은 해보겠지)

 

***PNG 파일은 항상 맨 앞에 헤더(8바이트)가 오고, 그 뒤로 IHDR, IDAT, IEND라는 청크(Chunk)들이 순서대로 붙는 구조입니다.

  • Header: 89 50 4E 47 0D 0A 1A 0A 
  • IHDR 청크: 파일의 메타데이터(가로/세로 크기, 색상 정보 등)가 들어있는 구간////
  • IDAT 청크: 실제 이미지 데이터가 압축되어 들어있는 구간
  • IEND 청크: 49 45 4E 44 AE 42 60 82

 

이 두 방법을 섞어서 사용해도 좋을 것 같음!

 

 

(3) 윈도우 아티팩트 내 카빙

찾아보니까 그냥 파일을 넣어놓고 카빙하는 것은 약한 느낌이 들 수 있기 때문에 윈도우 포렌식이라는 주제에 따라 윈도우 아티팩트를 추출하고 그 안에 카빙을 넣어본다면 조금 더 체계적인 문제를 만들 수 있다.

 

제작 방법:

1. 용의자가 어떤 이미지를 본 뒤에 삭제를 했음 --> 우리 배운 아티팩트 중에 Thumcache는 삭제되도 데이터가 남는다고 배웠음

2. Thumbs.db나 thumbcache.db에 작은 미리보기 이미지를 저장함

3. 플레이어가 이 파일들을 보고 export해서 파일 카빙 기법을 할 수 있게끔 만들 수도 있겠다..!

--> 그다음은 이전에 설명했던 기법들을 선택해서 넣어도 될 것 같음