본문 바로가기

Dreamhack/Forensic

WarGame - BMP Recovery 풀이

728x90
반응형

BMP 파일을 지웠다 복구해라

그러면 

문제파일은 python 파일 하나랑 broken된 bmp파일이 있었다

chal.py

코드가 주어진 걸 보니까 아마 문제풀이도 파이썬으로 해야할 것 만 같은 그런 느낌이다

일단 주어진 코드 분석을 해보자

flag.bmp파일을 rb로 열고
파일내용을 읽고 data에 저장
그리고 BMP파일 시작 부분 부터 0x1C까지 0으로 채우고
0x22부터 0x36까지 0으로 채운다
수정된 data를 flag.bmp.broken이라는 이름으로 새로 저장

그니까 쉽게 풀이하면 헥사코드를 bmp구조에 해당되는 부분을 0으로 바꿔놨다 이얘기다

bmp구조

bmp구조는 여기 말고 다른 블로그 찾아보면 좋은 글이 많으니까 참고했음 한다


참고만

일단 BMP파일을 복구 하기위해선 파일의 헤더와 해당 오프셋의 데이터가 필요

이걸 이해하기 위해선

  1. 파일 헤더 (14 바이트):
    • 0x00 - 0x01: 서명 ("BM")
    • 0x02 - 0x05: 파일 크기
    • 0x06 - 0x07: 예약된 필드 (일반적으로 0)
    • 0x08 - 0x09: 예약된 필드 (일반적으로 0)
    • 0x0A - 0x0D: 비트맵 데이터의 시작 위치
  2. DIB 헤더 (40 바이트):
    • 0x0E - 0x11: 헤더 크기 (일반적으로 40)
    • 0x12 - 0x15: 이미지의 너비
    • 0x16 - 0x19: 이미지의 높이
    • 0x1A - 0x1B: 색상 평면 수 (1)
    • 0x1C - 0x1D: 비트 수 (1픽셀 당 비트 수, 예: 24)
    • 0x1E - 0x21: 압축 방식 (일반적으로 0)
    • 0x22 - 0x25: 이미지 데이터의 크기
    • 0x26 - 0x29: 가로 해상도 (픽셀/미터)
    • 0x2A - 0x2D: 세로 해상도 (픽셀/미터)
    • 0x2E - 0x31: 색상 팔레트의 색상 수
    • 0x32 - 0x35: 중요한 색상 수

확인해 보니까 file header, image header 등 다 뿌셔놨다


이 문제에서 중요한건 픽셀당 바이트 수를 체그한 후 전체 파일 바이트 크기 안에서 width와 height를 찾는 것 같다.

with open('flag.bmp.broken', 'rb') as f:
    data = bytearray(f.read())

total_bytes = 14309622  # 전체 파일 바이트 크기
header_size = 54  # BMP 파일 헤더 크기
info_header_size = 40
bitplane_value = 1
bytes_per_pixel = 3  # 픽셀당 바이트 수 (24비트 = 3바이트)

# 이미지 데이터 크기 계산
image_data_size = total_bytes - header_size

# 전체 픽셀 수 계산
num_pixels = image_data_size // bytes_per_pixel

data[0x0] = 0x42
data[0x1] = 0x4D
data[0x2:0x6] = total_bytes.to_bytes(4, byteorder='little')     
data[0xA:0xE] = header_size.to_bytes(4, byteorder='little')
data[0xE:0x12] = info_header_size.to_bytes(4, byteorder='little')     
data[0x1A:0x1C] = bitplane_value.to_bytes(2, byteorder='little')     
data[0x22:0x26] = image_data_size.to_bytes(4, byteorder='little')       


# 가능한 가로와 세로 조합 찾기
for width in range(1, int(num_pixels**0.5) + 1):
    if num_pixels % width == 0:
        height = num_pixels // width
        data[0x12:0x16] = width.to_bytes(4, byteorder='little')
        data[0x16:0x1A] = height.to_bytes(4, byteorder='little')
        with open(f'flag_{width}.bmp', 'wb') as f:
            f.write(data)
        data[0x12:0x16] = height.to_bytes(4, byteorder='little')
        data[0x16:0x1A] = width.to_bytes(4, byteorder='little')
        with open(f'flag_{height}.bmp', 'wb') as f:
            f.write(data)


for width in range(1, int(num_pixels**0.5) + 1):
    num_pixels = image_data_size // bytes_per_pixel

주어진 코드는 'flag.bmp.broken' 파일을 수정하여 가능한 모든 가로와 세로 조합에 해당하는 BMP 파일을 생성

먼저, 'flag.bmp.broken' 파일을 읽어와서 바이트 배열로 저장한다.
다음으로, BMP 파일의 헤더 크기, 정보 헤더 크기, 비트 평면 값, 픽셀당 바이트 수 등의 정보를 변수에 저장합니다.
이미지 데이터 크기를 계산한다.
가능한 모든 가로와 세로 조합을 탐색합니다. 이를 위해 전체 픽셀 수를 가로로 나누어서 나머지가 없는 경우, 즉 가로와 세로가 정수로 나누어 떨어지는 조합을 찾는다.
찾은 각 조합에 대해 헤더 정보를 수정하여 새로운 BMP 파일로 저장합니다. 가로와 세로 값을 헤더에 적용한 후 파일을 저장한다.
마지막으로, 같은 작업을 수행하지만 가로와 세로를 서로 바꾼 조합에 대해 파일을 생성한다.

그럼 bmp파일이 바로 출력이 된다.

 

728x90
반응형

'Dreamhack > Forensic' 카테고리의 다른 글

WarGame - sleepingshark 풀이  (0) 2024.05.21
WarGame - Snowing! 풀이  (0) 2024.05.18
WarGame - FFFFAAAATTT  (0) 2024.05.17
WarGame - Basic_Forensics_1  (0) 2024.05.17
WarGame - lolololologfile  (0) 2024.05.17