VolgaCTF 2015 - captcha



파일 링크
https://github.com/ctfs/write-ups-2015/tree/master/volgactf-quals-2015/stego/captcha

파일을 다운로드 받으면 'i' 라는 png 파일이 달랑 하나가 있다.

png 파일을 헥스에디터로 확인해보면 다른 png 파일들이 존재하는 것을 알 수 있다.

모든 png 파일을 꺼낸 후 꺼낸 순서대로 차례대로 적혀있는 글자를 이어주면 base64 인코딩 된 값임을 알 수 있다.

직접 그림에 있는 글자를 인식하지 않아도 글자가 적혀있는 png파일에 대한 해쉬값을 이용해서 같은 해쉬값끼리 똑같은 문자로 인식시켜주면 된다.

import md5
import base64

def GetMD5(fileName) :
 f = open(fileName, "rb")
 data = f.read()
 result = md5.md5(data).hexdigest()
 f.close()
 return result

pngHeader = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"
pngDataList = []

f = open("captcha.png", "rb")
data = f.read()
f.close()

findIdx = data.rfind(pngHeader)
while findIdx != -1 :
 pngDataList.append(data[findIdx:])
 data = data[:findIdx]
 findIdx = data.rfind(pngHeader)

pngDataList = pngDataList[::-1]

# extract files
for i, item in enumerate(pngDataList) :
 f = open(str(i + 1) + ".png", "wb")
 f.write(item)
 f.close()

# setting png MD5 hash
m = {}
m[GetMD5("62.png")] = "Q"
m[GetMD5("17.png")] = "S"
m[GetMD5("80.png")] = "8"
m[GetMD5("4.png")] = "O"
m[GetMD5("9.png")] = "G"
m[GetMD5("31.png")] = "C"
m[GetMD5("166.png")] = "3"
m[GetMD5("61.png")] = "6"
m[GetMD5("50.png")] = "X"
m[GetMD5("177.png")] = "9"
m[GetMD5("10.png")] = "g"
m[GetMD5("58.png")] = "s"
m[GetMD5("124.png")] = "e"
m[GetMD5("437.png")] = "2"
m[GetMD5("76.png")] = "x"
m[GetMD5("386.png")] = "5"
m[GetMD5("139.png")] = "W"
m[GetMD5("172.png")] = "a"
m[GetMD5("12.png")] = "A"
m[GetMD5("60.png")] = "c"
m[GetMD5("11.png")] = "o"
m[GetMD5("2.png")] = "V"
m[GetMD5("7.png")] = "0"
m[GetMD5("425.png")] = "p"
m[GetMD5("42.png")] = "d"
m[GetMD5("44.png")] = "b"
m[GetMD5("3.png")] = "B"
m[GetMD5("32.png")] = "D"
m[GetMD5("109.png")] = "q"
m[GetMD5("6.png")] = "w"
m[GetMD5("81.png")] = "Y"
m[GetMD5("506.png")] = "y"
m[GetMD5("8.png")] = "K"
m[GetMD5("92.png")] = "Z"
m[GetMD5("5.png")] = "R"
m[GetMD5("59.png")] = "4"
m[GetMD5("41.png")] = "7"
m[GetMD5("79.png")] = "v"
m[GetMD5("178.png")] = "P"
m[GetMD5("43.png")] = "M"
m[GetMD5("170.png")] = "k"
m[GetMD5("379.png")] = "z"
m[GetMD5("16.png")] = "N"
m[GetMD5("162.png")] = "m"
m[GetMD5("18.png")] = "U"
m[GetMD5("88.png")] = "J"
m[GetMD5("19.png")] = "h"
m[GetMD5("116.png")] = "f"
m[GetMD5("373.png")] = "/"
m[GetMD5("484.png")] = "u"
m[GetMD5("68.png")] = "n"
m[GetMD5("128.png")] = "t"
m[GetMD5("20.png")] = "E"
m[GetMD5("57.png")] = "r"
m[GetMD5("71.png")] = "1"
m[GetMD5("77.png")] = "j"
m[GetMD5("143.png")] = "+"
m[GetMD5("641.png")] = "F"
m[GetMD5("146.png")] = "T"
m[GetMD5("122.png")] = "H"
m[GetMD5("1.png")] = "i"
m[GetMD5("1892.png")] = "="
m[GetMD5("461.png")] = "L"
m[GetMD5("35.png")] = "I" # i -> I
m[GetMD5("371.png")] = "l" # l -> L

# make string from files
result = ""
for pngData in pngDataList :
 result += m[md5.md5(pngData).hexdigest()]

f = open("result.png", "wb")
f.write(base64.decodestring(result))
f.close()

댓글