WARGAME/PicoCTF

picoCTF2019 - c0rrupt

daydreamtalker 2024. 4. 27. 10:48

Problem

picoCTF


Explanation

다운 받은 파일을 보면 열리지가 않는다.

HxD로 열어보니 head 부분이 망가져 있는 것 같다.

 

푸터를 보니 png의 시그니처임를 알 수 있었다.

헤더를 png의 시그니처로 바꿔주고 fixed.png 파일로 저장했다.

시그니처 부분을 고쳐도 파일이 열리지 않는다. 파일에 다른 부분도 마찬가지로 손상된 것 같다.

 

Pngcheck 명령어를 사용해서 파일에 손상된 부분을 찾아보려고 한다.

먼저 sudo apt-get install pngcheck으로 pngcheck 실행파일을들 다운받는다.

 

file fixed.png를 통해 파일을 불러오고

 

pngcheck -v -t fixed.png 명령어를 통해 손상된 부분을 찾아보았다. 잘 보면 맨 마지막 문장에서 CRC error in chunk pHYs 에러 메세지를 확인할 수 있다.

헤더는 원래 가 9바이트로 선언된 다음 pHY는 4바이트, 페이로드는 9바이트, 체크섬는 4바이트로 선언된다.

pngcheck에서 파일에 명시된 예상 체크섬(0x495224f0)이 계산된 체크섬과 일치하지 않는다는 뜻이다. 따라서 체크섬이 손상되었거나 데이터가 손상된 것을 알 수 있다.

pHYs 파일을 정의해보자면

xxd -g 1 -s 0x3e -l $((4+4+9+4)) fixed.png 으로 고쳐주면 된다

Printf ‘\x00’를 하는 이유는 단위당 픽셀 수는 1바이트만 다르고 X축의 0xAA가 값을 매우 크게 만들기 때문에 0을 배치하는 것이 좋기 때문이다. 0 값을 통해 체크섬이 수정되는지 확인할 수 있다.

틀린 부분을 수정했으니 다시 pngcheck으로 돌려봤다.

얻게되는 에러 메세지는 invalid chunk length (too large)

 

pHY 청크가 종료된 후에 시작되는 것을 살펴보면

0xaaaaaffa5의 크키가 크고 존재하지 않는 유형인 \DET가 있는 것을 알 수 있다.

가장 비슷한 청크 유형은 IDAT이기 때문에 IDAT로 수정해 보았다.

 

다음 IDAT 청크가 있는 경우 이를 검색하여 차이를 계산할 수 있었다.

다음 IDAT 청크는 오프셋 0x10008에 있는 것을 확인했다.

0x5B부터 시작하는 첫 번째 IDAT 청크의 길이를 계산하고 체크섬에 대해 4바이트를 추가해야 한다.

따라서 원래 값이 0xAAAA FFA5

0x10008 - 0x5B - 0x4 를 계산하면 0xFFA5의길이를 얻는다. 0xAAAA에 붙이면 원래값과 비슷해진다.

0xAAAA를 0000으로 오버라이딩 해주면 원하는 결과를 얻을 수 있다.

 

다시 pngcheck를 돌려봤을 때 에러가 검출되지 않았다. fixed.png파일을 열어보니 제대로 열리고 flag를 찾을 수 있었다.

 


🔑: picoCTF{c0rrupt10n_1847995}

2023/May/04 solved.