본문 바로가기

카테고리 없음

2014 whitehat 'Cold war' 풀이

문제

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