오랜만에 이 사이트의 문제를 풀게 되었다.
겉으로만 보면, 입력값을 이용해 encrypted.enc를 복호화하는 프로그램인 것 같다.

입력값 각 자리의 ASCII 코드를 더한 후, 마지막으로 0xA('\n')까지 더해준다.
10자리가 맞으면 encrypted.enc 파일을 읽어온다. (우연찮게 10자리를 입력했다...)

좀 복잡하다.
위에서 계산한 입력값 10자리의 ASCII 코드 + 0xA의 합과 encrypted.enc에서 읽어들인 데이터를 바이트 단위로 XOR한다.
쉽게 말하면, hex editor로 봤을 때 encrypted.enc는 0x31, 0x4d, 0x39, ...로 되어 있는데,
위 루틴에서 계산한 값 ^ 0x31, 위 루틴에서 계산한 값 ^ 0x4d, ...을 해준다는 의미이다.
그리고 그 XOR한 결과를 다 더한다.
그런데, encrypted.enc의 모든 바이트열을 건드리는 것이 아니라, 순차적으로 읽다가 index 값이 아래 조건을 만족하면, 끊어버린다.
index & 4 and index & 1
계산해보면, index가 5일 때 처음으로 이 조건을 만족하므로, 실제 XOR 연산에 참여하는 바이트열은 그 파일의 0~4번째 바이트 뿐이다.

2중 루프 부분은 encrypted.enc에 대한 복호화 루틴이다.
입력값 조건만 맞으면 알아서 복호화해줄테니 건드리지 않아도 될 것 같다.

XOR의 합이 0xDCA가 되어야 성공 메시지와 패스워드를 볼 수 있다.

그래서 우리는 입력값이 어떤 조건이 되어야 encrypted.enc의 첫 5 바이트와의 XOR 합 결과가 0xDCA으로 될 수 있는지 알아야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #-*- coding: utf-8 -*- import os import binascii enc_file = "G:" + os.sep + "Analyze it!" + os.sep + "HackThisSite" + os.sep + "app7win" + os.sep + "encrypted.enc" target = 0x0dca # load all byte array with open(enc_file, 'rb') as f: contents = f.read() # extract only valid bytes for i in range(len(contents)): if (i & 4 and i & 1): contents = contents[:i] break #contents = [0x31, 0x4d, 0x39, 0x35, 0x33] for i in range(ord("0")*10+10, ord("z")*10+10): sum = 0 for j in range(len(contents)): sum += i ^ ord(contents[j]) if sum == target: print "Sum: %d when sum of inputs is %s" % (sum, hex(i)) break | cs |
답이 나왔다.
입력값 10자리의 ASCII 코드 합 + 0xA가 0x2f1이 되어야 한다.

0xA('\n')을 고려하여, 10자리 합이 0x2e7(0x2f1-0xa)이 되도록 입력값을 구성해주면 되겠다.
이유는 모르겠지만, 일반적으로 실행 시 맞는 답에도 "Failed to open encrypted.enc"라는 메시지가 표시되는데,
디버거 위에서 실행하면, 제대로 성공 메시지를 볼 수 있다.
