| Name | l'm s0o0o0o0o00o00o0o higH!!!.png |
| Format(extension) | PNG |
| Image Data | ![]() |
PNG 파일 분석하여 플래그 찾기
파일을 열었을 때 정상적으로 이미지 데이터가 출력되며 HEX editor을 통하여 분석 결과 PNG 구조, 각각의 필수 Chunk 유무(IHDR Chunk, IDAT Chunk, IEND Chunk)와 Chunk 형식, 특히 IHDR Chunk의 width과 height, bit depth, color type, filter type, interlace type에 해당하는 16진수 값들과 이에 따른 CRC(Cyclic Redundancy Check) 값 역시 확인해 보았을 때 특별한 이상은 없었으므로 이미지 데이터 자체에는 문제가 없다.

그러나 HEX editor를 통하여 PNG 파일의 끝을 나타내는 IEND Chunk 이후 ‘12D3A’ Offset부터 파일의 이미지에 해당하는 데이터가 아닌 다른 숨겨진 데이터가 있음을 알 수 있다.
| { Length : 00 00 00 00 (0 byte), Chunk Type : IEND, Chunk Data (0 byte), CRC } |
위의 IEND Chunk의 구조에서 IEND Chunk 마지막에 위치해 있는 CRC 값인 ‘AE 42 60 82’이후 ‘12D3A’ Offset부터 PDF 파일의 Header Signature 값인 ‘25 50 44 46 2D 31 2E’ 가 존재하며 PDF 파일의 Footer Signature 값인 ‘25 25 45 4F 46’를 찾아보았을 때

다음 사진과 같이 존재하므로 우선 PDF 파일이 숨겨져 있음을 유추 해볼 수 있다. 각 파일들에 해당하는 Signature 값들을 16진수 값으로 검색 해 본 결과 기존의 PNG 파일에 해당하는 16진수 데이터들을 제외하고 데이터 순서대로 1개의 PDF 파일 데이터와 2개의 ZIP 파일 데이터들이 숨겨져 있음을 유추 해볼 수 있었고, 각 확장자에 해당하는 파일 구조를 분석하여 데이터들을 추출해 보았다.

‘12D3A’ Offset부터 ‘429EF6’ Offset까지 “1_1.pdf”파일, ‘E850’ Offset부터 ‘12D2D’ Offset까지 “1_2.zip”파일, ‘429EF7’ Offset부터 ‘42B73F’ Offset까지 “1_3.zip”파일로 데이터 블록을 추출하여 저장한다.
“1_1.pdf”은 이상 없이 실행되며 바이너리 데이터에도 특별한 점이 없다.
“1_3.zip”안에는 “Wkf.png”라는 파일이 있고, 압축을 해제하기 위해서는 비밀번호가 필요하지만

위 사진과 같이 원본 데이터의 마지막에 존재하는 16진수 데이터를 해당하는 ASCII Code 값으로 변환하였을 때 “WKF PW: too much easy”라는 text를 통하여 비밀번호를 “too much easy”로 짐작해볼 수 있었고

위의 사진과 같이 입력하였을 때

다음과 같은 PNG 파일을 열어 볼 수 있다. 그러나 마찬가지로 HEX editor로 분석해보았을 때 특별한 점은 없었다.
“1_2.zip”도 압축을 해제하기 위하여 비밀번호가 필요하다.
따라서 Password-Cracking 공격 기법중 하나인 Brute Force Attack으로

위의 사진과 같이 비밀번호를 찾은 뒤에 압축을 해제 하였으나

파일이 정상적으로 출력되지 않기에 이 파일은 훼손된 파일이다.

따라서 “08.11.23 dGUR BIZ.png”를 HEX editor로 분석해본 결과 IHDR Chunk의 bit depth 값에 문제가 있음을 알 수 있다. color type 값인 “06”은 RGB + alpha 값을 가지며, bit depth에는 “08” 혹은 “16” 값만이 올 수 있다. 그러나 위 사진에는 bit depth 자리에 “02”값이 위치하여 있다.

다음과 같이 bit depth 값을 “08”로 수정한 뒤 저장하고 파일을 실행시키면

위와 같이 PNG 파일이 열린다. 이미지는 출력되지만 명확한 이미지 데이터를 찾기 위해 CRC 값을 계산하여 width 값과 height 값에 해당하는 IHDR Chunk의 데이터를 확인해 본다.
| from zlib import crc32 file_name = input('파일 이름 입력: ') data = open(file_name, 'rb').read() index = 12 IHDR = bytearray(data[index:index + 17]) width_index = 7 height_index = 11 target_crc = input('CRC 값 입력: ') target_crc = int(target_crc, 16) for width in range(1, 2000): width_bytes = bytearray(width.to_bytes(2, 'big')) for height in range(1, 2000): height_bytes = bytearray(height.to_bytes(2, 'big')) # for i in range(len(height_bytes)): IHDR[height_index - i] = height_bytes[-i - 1] for i in range(len(width_bytes)): IHDR[width_index - i] = width_bytes[-i - 1] current_crc = crc32(IHDR) & 0xFFFFFFFF if current_crc == target_crc: print("width: {}, height: {}" .format(hex(width)[2:].upper(), hex(height)[2:].upper())) break else: continue break |

다음과 같이 Python의 ‘zlib’모듈에서 ‘crc32’ 함수를 import하여 CRC 값을 계산하여 width 값과 height 값을 구하는 코드를 실행시켜서

파일 이름과 HEX editor로 확인한 IHDR Chunk의 CRC 값인 “08 2B 81 0D”를 입력하면 width 값과 height 값이 16진수로 출력된다.

출력된 값으로 데이터를 수정한 후에 저장하고 다시 PNG 파일을 실행시켜보면

Flag를 찾을 수 있다.
Reference
PNG file format:
(https://stackoverflow.com/questions/54845745/not-able-to-read-ihdr-chunk-of-a-png-file)
ZIP file format: (https://www.crowdstrike.com/blog/how-to-prevent-zip-file-exploitation/)
List of signature: (https://www.garykessler.net/library/file_sigs.html)
Password-Cracking(Attack Techniques):
(https://www.linkedin.com/pulse/password-cracking-top-10-techniques-1c)
Python CRC 값 계산 코드 수정 전 원본:
(https://github.com/W3rni0/RACTF_2020#dimensionless-loading)
위 문제는 아래의 블로그 운영자가 출제한 문제입니다.
'Digital_forensic > CTF' 카테고리의 다른 글
| [TetCTF 2024] TET & 4N6 Write-up (1) | 2024.05.29 |
|---|---|
| [Dreamhack] Snowing! Write-up (0) | 2024.01.28 |
| [DEBUG] upgradepng1.png Write-up (1) | 2024.01.27 |
| [DEBUG] ExpertPNG Write-up (1) | 2024.01.27 |
| [Sooboon] Sob_PNG_Lv1.5 Write-Up (0) | 2024.01.26 |
