Hex Encrypt Data
코드에서 나와있듯이 _encryption 함수는 실제 encryption 암호화하는 함수를 호출하기 위해 입력 데이터를 각각 2byte씩 처리하여 암호화하는 형식이다
사진에서 코드를 실행할 때 암호화할 인자를 같이 넘겨주면 a는 3102 b는 31e4로 암호화되어 출력되는 걸 알 수 있다 즉 원본 문자와 암호화된 결과를 각각 딕셔너리로 저장한 다음 암호화된 문자열을 찾을 때 딕셔너리에 같이 저장된 원본 데이터를 이용해서 원래 문자열로 되돌릴 수 있다
import subprocess
import string
from concurrent.futures import ProcessPoolExecutor, as_completed
def run_external_program(pair):
try:
result = subprocess.run(['./hexencrypt', pair], capture_output=True, text=True, check=True)
output = result.stdout.strip()
encrypted_data = output[len('Encrypted data in hexadecimal format: '):]
return pair, encrypted_data
except subprocess.CalledProcessError as e:
print(f"Error: {e}")
return pair, None
def generate_encryption_results():
# Create a list of all characters from 'a' to 'Z'
chars = string.ascii_letters + string.punctuation # a~Z 특수문자포함
pairs = [a + b for a in chars for b in chars] + [c for c in chars]
encryption_results = {}
# Use ProcessPoolExecutor to parallelize the encryption process
with ProcessPoolExecutor() as executor: # 병렬 프로세스
future_to_pair = {executor.submit(run_external_program, pair): pair for pair in pairs}
for future in as_completed(future_to_pair):
pair = future_to_pair[future]
try:
result_pair, encrypted_data = future.result()
if encrypted_data:
encryption_results[encrypted_data] = result_pair
except Exception as e:
print(f"Exception occurred for pair {pair}: {e}")
return encryption_results #딕셔너리 반환
def decrypt_encrypted_data(encrypted_data, encryption_results):
decrypted_data = ''
index = 0
while index < len(encrypted_data):
for length in range(1, 9):
segment = encrypted_data[index:index+length]
if segment in encryption_results:
decrypted_data += encryption_results[segment]
index += length
break
else:
print(f"No decryption found for segment starting at {index}")
index += 1
return decrypted_data
if __name__ == '__main__':
# Generate the encryption results dictionary
encryption_results = generate_encryption_results()
# Example encrypted strings
encrypted_string1 = '307bf941333a751c12d4d2902901fe813334db20341f5c012514c950283f582b13ee69aa283f582b34f611f48c2'
# Decrypt and print results
print("Decrypted Data 1:", decrypt_encrypted_data(encrypted_string1, encryption_results))
이를 파이썬으로 작성한 코드이고(GPT 이용했다 ㅋㅋ..) 대회에 함께 참가한 선배 write-up의 병렬 기능만 추가했다
def run_external_program(pair):
try:
result = subprocess.run(['./hexencrypt', pair], capture_output=True, text=True, check=True)
output = result.stdout.strip()
encrypted_data = output[len('Encrypted data in hexadecimal format: '):]
return pair, encrypted_data
except subprocess.CalledProcessError as e:
print(f"Error: {e}")
return pair, None
각각 함수를 해석해 보자면 run_external_program은 주어진 pair를 인자로 ./hexencrypt 프로그램을 실행하여 암호화된 결과를 얻고 결과를 반환한다 앞서 Hex Encrypt Data 코드를 컴파일 후 실행 파일에 Encrypted data in hexadecimal format : 부분을 제외한 값을 가져옵니다
pair가 만약 a라면 ./hexencrypt a 결과인 Encrypted data in hexadecimal format : 3102에서 3102에 값을 반환합니다
def generate_encryption_results():
# Create a list of all characters from 'a' to 'Z'
chars = string.ascii_letters + string.punctuation # a~Z 특수문자포함
pairs = [a + b for a in chars for b in chars] + [c for c in chars]
encryption_results = {}
# Use ProcessPoolExecutor to parallelize the encryption process
with ProcessPoolExecutor() as executor: # 병렬 프로세스
future_to_pair = {executor.submit(run_external_program, pair): pair for pair in pairs} # pair를 값으로하는 딕셔너리 생성
for future in as_completed(future_to_pair): # 각 작업이 완료되기까지 대기하고 완료시 순서대로 future에 반환
pair = future_to_pair[future] # 완료된 future 객체에 대응하는 pair를 가져오기
try:
result_pair, encrypted_data = future.result() # future의 결과를 result_pair와 암호화된 데이터로 분리됨
if encrypted_data: # 만약 암호화된 데이터가 존재하면
encryption_results[encrypted_data] = result_pair # 암호화된 결과 딕셔너리에 encrypted_data 키로 result_pair를 저장함
except Exception as e:
print(f"Exception occurred for pair {pair}: {e}")
return encryption_results #딕셔너리 반환
그다음 해당 함수에서 병렬 프로세스를 이용하셔 실제 암호화된 결과와 원본 데이터를 딕셔너리에 저장하는 역할을 합니다 chars는 주석 처리된 내용(a~Z 특수문자)을 저장한다
pairs 변수의 [a + b for a in chars for b in chars] 부분은 두 문자로 이루어진 모든 가능한 조합 생성을 의미한다
for a in chars : chars 문자열의 각 문자 a로 사용
for b in chars : chars 문자열의 각 문자 b로 사용
이런식이다 그래서 a+b는 a와 b를 이어 붙여 두 문자로 이루어진 문자열을 생성하는데
예를 들어 chars가 abc라면 a는 a,b,c를 차례대로 값을 가질 거고 각 a에 대해 b도 a, b, c로 가진다
따라서 생성되는 조합 ['aa', 'ab', 'ac', 'ba', 'bb', 'bc', 'ca', 'cb', 'cc']가 된다
여기까지 chars의 모든 문자에 대해 두 문자로 이루어진 모든 가능한 조합을 얻을 수 있다
단일 조합인 [c for c in chars]의 chars가 'abc'라면 생성되는 리스트는 [ 'a', 'b', 'c' ]가 된다
결과적으로 두 문자로 이루어진 조합과 단일 문자 조합을 모두 포함하면
['aa', 'ab', 'ac', 'ba', 'bb', 'bc', 'ca', 'cb', 'cc', 'a', 'b', 'c'] 이런식으로 출력된다
즉 pairs 변수는 암호화 프로그램에 입력할 모든 가능한 문자열 조합을 생성하기 위해 사용했다
나머지는 주석으로 작성한 기능과 동일하고 최종적으로 반환되는 encryption_results 딕셔너리는
{'25165714': 'aa', '25da76d8': 'ab', '26a012a2': 'ac', '2768326a': 'ad' ........ } 으로 "암화화된 결과", "원본 문자"로 반환된다
def decrypt_encrypted_data(encrypted_data, encryption_results):
decrypted_data = ''
index = 0
while index < len(encrypted_data): #암호화된 데이터 길이보다 작을때까지 ( 암호화 데이터를 모두 순회할때까지 작동 )
for length in range(1, 9): # 현재 암호화된 데이터가 {'25165714': 'aa'..}에서 최대 8글자까지 있으니 1부터8까지 반복해서 해당 길이를 가져옴
segment = encrypted_data[index:index+length] # 암호화된 데이터에 인덱스에서 length 길이의 세그먼트 추출
if segment in encryption_results: # 세그먼트가 암호화된 데이터에 있으면
decrypted_data += encryption_results[segment] # 암호화된 데이터에 원래값을 찾아 복호화 데이터에 추가
index += length # 현재 세그먼트 길이만큼 증가
break
else:
print(f"No decryption found for segment starting at {index}")
index += 1
return decrypted_data
if __name__ == '__main__':
# Generate the encryption results dictionary
encryption_results = generate_encryption_results()
# Example encrypted strings
encrypted_string1 = '307bf941333a751c12d4d2902901fe813334db20341f5c012514c950283f582b13ee69aa283f582b34f611f48c2'
# Decrypt and print results
print("Decrypted Data 1:", decrypt_encrypted_data(encrypted_string1, encryption_results))
나머지 코드는 주석에서 설명한 것과 동일하다
이제 암호화된 문자를 복호화 시켜보면 Your_Efforts_are_Great! 원본 문자가 출력되는 걸 알 수 있다