CTF/CTF Write-Up

[Write-Up] Hex Encrypt Data

2024. 7. 21. 20:13

QUOTE THE DAY

Self-Talk
반응형

 

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! 원본 문자가 출력되는 걸 알 수 있다

 

반응형
저작자표시 (새창열림)
'CTF/CTF Write-Up' 카테고리의 다른 글
  • [Write-Up] KakaoTalk Decrypt
MUSA
MUSA
Nine Point Eight

최근 댓글

최근 글

인기 글

  • MUSA
    무사
    Nine Point Eight
    • 홈

    • 방명록

    • 분류 전체보기 (124)
      • Minecraft (29)
        • Server Development (16)
        • ResourcePack (7)
        • Plugin (5)
        • Java Plugin (1)
      • Tistory (15)
        • 티스토리 수익 (3)
        • 티스토리 검색 유입 (3)
        • 티스토리 꾸미기 (9)
      • Windows (2)
      • Kali Linux (42)
        • Linux (24)
        • Bandit (18)
        • Tool (0)
      • Web Study (26)
        • Theory (14)
        • Training (12)
      • CTF (5)
        • HackTheon (1)
        • Customized CTF (2)
        • CTF Write-Up (2)
      • Forensics (1)
      • System (1)
      • Cryptography (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 반응형
  • hELLO· Designed By정상우.v4.10.3
MUSA
[Write-Up] Hex Encrypt Data
상단으로

티스토리툴바