CTF | wargame

3DS CTF -What The Hex (jpg파일 복구, 사진에서 문자열 추출 - teeseract)

nopdata 2017. 3. 7. 21:50
keyword : jpg 파일 복구, 사진에서 문자열 추출 - tesseract


파일이 하나 던져지는데 1231312123.... 이런식으로 숫자로 구성되어 있다. 파일확장자가 raw인 점. forensic인 점을 감안해서 제공된 파일의 스트링값을 hex값으로 변환하여 보아야 한다는 것을 유추했다.
하지만 파일의 크기가 266MB로 파이썬에서 한번에 read를 하고 작업을 하려 하면 컴퓨터의 메모리가 부족해지는 현상이 자꾸 발생해서 메모리가 적게 드는 방법을 찾아야 했다.
일단 약 100MB정도를 해서 보았을 때 첫 부분이 다음과 같았다.


시작부분이 FIF인 점. 그 후에 ff db등 jpg의 시그니쳐가 있는 점을 보고 jpg파일일 수 있다는 점을 유추했다. 해서 jpg의 footer인 ff d9를 찾아 보았더니 존재하였고 그 다음에는 바로 위처럼 구성되어 있어
똑같은 형태로 header의 일부분을 자른 형태의 jpg를 붙여 놓은 것이라는 것을 알 수 있었다.
문제는 메모리 초과가 나지 않도록 모든 사진을 복구해야 했다. 사진 한장을 복구 해보니 다음과 같았다.


아마도 이런 사진이 많은 것으로 보아 이 중에 실제 답이 숨어 있는 듯 했다. 일단 모든 jpg를 복구하기 메모리 초과가 나지 않도록 한번에 작업을 하지 않는 파이썬 스크립트를 작성하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
header = "ffd8ffe000104a4649460001"
 
f=open('massa.raw','rb')
data=f.read()
f.close()
data=data.split("4649460001")
 
for i in range(len(data)):
    data[i] = header + data[i]
 
func = lambda x:chr(eval("0x"+''.join(x)))
 
 
for i in range(len(data)):
    f=open('./out/'+str(i)+'.jpg','wb')
    tmp = ''.join(map(func,zip(*[iter(data[i])]*2)))
    f.write(tmp)
    f.close()
cs

물론 시간은 좀 걸린다. 위 코드로 massa.raw에서 jpg들을 추출하면 약 3000개 가량의 jpg파일이 추출된다. 운 좋게 파일 추출 과정에서 답 jpg를 바로 찾았는데 위 스크립트로 푼다면 2365.jpg에 있을 것이다.


Answer : 3DS{u_5h0uldv3_7ried_tesseract}

+++
답을 보아도 그렇고, write up을 보면 hint로 tesseract가 나왔던 것 같다. tesseract는 이미지, 또는 영상에서 특정 문자열을 판별해 주는 기술이라고 한다.

1
2
3
4
5
6
7
8
9
10
import subprocess
 
res = list()
 
for i in range(1,3001):
    subprocess.call(['tesseract',str(i)+'.jpg',str(i)])
    f=open(str(i)+'.txt','rb')
    tmp=f.read()
    res.append(tmp)
    f.close()
cs


이렇게 하면 각 jpg에 대한 문자열을 파싱해서 해당 번호.txt파일로 추출이 되고 이걸 읽어 다시 res 리스트에 저장하고 판별을 해주면 된다.
tesseract가 어디까지 효용이 되는지는 모르겠으나 한글은 일단 잘 되지 않는 듯 하다.