문제
def g(l): r ="".join(chr(random.randint(0, 0xff)) for idx in xrange(l)) return r def e(r, p): ret = "" if len(p) % len(r) == 0: c = len(p) / len(r) for idx in xrange(c): for (c1, c2) in zip(r, p[idx * len(r):(idx + 1) * len(r)]): ret += ''.join(chr(ord(c1) ^ ord(c2))) else: print "[+] Error" return ret if __name__ == "__main__": a = g(n) ps = [l.rstrip('\n') for l in open("input_messages")] ret = [] print a페이지 5 / 7 for p in ps: ret.append(e(a, p).encode('hex')) print a.encode('hex') print ret
복호화해야할 암호문
fee304acd551a17fbd3b7f23c1e51fba9c55a93de43d797187fc1eaa9055ba74fc3e2c62d4ac10fe864fbb79f83c7822 f0e414aa9d5ebc3df2202c6dc8f85197d54caf6ebd267971c9e51fb9d54fa678bd226d64c2ff51aa9a5faf64bd332c60c6e014b0915abc3df4212c64c8e51fb9d554b878ef732d22 eeac15b1d555a169bd316d71c2ac10fe965aa27ee83e7970 f7e903ad9a55ee6ff8226962d3ff51b39c48ba7cf6372c62c9e851999a5fee7bf2206b6ad1e902fe9852bd69fc396922 eeac05b69c55a53de93a6923c9ed05b79a55af71bd337f70c2e113b28c1bb974f13e2c61c2ac15bb8652a973fc26696787ed02fe941ba67ce7337e67c8f902fe9954ad7ce93b636d f3e414ad901ba972f2362c70c6f518b0921ba86ff23f2c50cfe51ffebd5aab3dde3a796f f3e414fe9e5eb73df4212c6287ff19bfc41bb87cf1276923c8ea51aa9d5eee73fc3f6922 fee304fe8252a271bd20696ec6e51ffe9c55ee70e4726466c6fe05fe9354bc78eb377e22
문제 소스를 확인해보면 평문을 읽어서 특정한 키값 리스트와 xor를 하는 암호화(?) 방식을 취한다.
xor를 할 키 길이는 평문 길이를 나누었을때 나머지가 0이여야 한다.
if len(p) % len(r) == 0: ... else: #Error!
암호문은 7라인이며 각 암호문의 길이는 96,144,48,144,72,72,72 이다
해당 값은 hex값이니 2글자가 하나의 character와 매칭되므로 평문의 길이는 48,72,24,72,36,36,36이 된다
따라서 키의 길이는 12,6,4,3,2,1 이 될수 있다
평문은 알파벳,숫자,특수문자,스페이스 등으로 이루어져 있다고 예상하고
암호문를 12글자씩 나누어서 0~255까지 xor 연산 해보면 12 길이의 키값을 알아낼수 있다.
복호화 소스
encrypted="""fee304acd551a17fbd3b7f23 c1e51fba9c55a93de43d7971 87fc1eaa9055ba74fc3e2c62 d4ac10fe864fbb79f83c7822 f0e414aa9d5ebc3df2202c6d c8f85197d54caf6ebd267971 c9e51fb9d54fa678bd226d64 c2ff51aa9a5faf64bd332c60 c6e014b0915abc3df4212c64 c8e51fb9d554b878ef732d22 eeac15b1d555a169bd316d71 c2ac10fe965aa27ee83e7970 f7e903ad9a55ee6ff8226962 d3ff51b39c48ba7cf6372c62 c9e851999a5fee7bf2206b6a d1e902fe9852bd69fc396922 eeac05b69c55a53de93a6923 c9ed05b79a55af71bd337f70 c2e113b28c1bb974f13e2c61 c2ac15bb8652a973fc266967 87ed02fe941ba67ce7337e67 c8f902fe9954ad7ce93b636d f3e414ad901ba972f2362c70 c6f518b0921ba86ff23f2c50 cfe51ffebd5aab3dde3a796f f3e414fe9e5eb73df4212c62 87ff19bfc41bb87cf1276923 c8ea51aa9d5eee73fc3f6922 fee304fe8252a271bd20696e c6e51ffe9c55ee70e4726466 c6fe05fe9354bc78eb377e22""" if __name__ == "__main__": char_set=range(48,123)+[32,33] # 복호화된 값이 가지는 char_set는 숫자,알파벳,일부특수기호,space,! 로 한정 char_set.remove(ord('`')) # ` 값이 나오는 경우는 제외 (xor key 값이 여러개 나옴) xor_list=[] # xor key 값 for idx in range(12): lines= [ l.strip()[idx*2:(idx+1)*2] for l in encrypted.splitlines()] # xor 값은 0~255 까지 대입해서 복호화값이 char_set만 나오는 xor key 값을 찾는다 for i in range(0xff): ret = "" is_error=False for line in lines: dec_num=ord(line.decode('hex'))^i # 정상 char_set만 가지는가? if dec_num not in char_set: is_error=True break else: ret+=chr(dec_num) if is_error: continue print "[%2d] %3d : %s => %s" % (idx,i,''.join(lines),ret) xor_list.append(i) decode="" # 구해진 xor key 값을 이용해 복호화 시도 for line in [l.strip().decode('hex') for l in encrypted.splitlines()]: for idx in range(len(xor_list)): decode+=chr(ord(line[idx])^xor_list[idx]) print decode exit() n=4 # n 개의 길이로된 문자열 만들기 a = g(n) # 메시지를 읽음 ps = [l.rstrip('\n') for l in open("input_messages")] ret = [] print a for p in ps: # encoding 을 한다 ret.append(e(a, p).encode('hex')) print a.encode('hex') print ret