경희대학교 장대희 교수님의 정보보호 수업을 기반으로 정리한 글입니다.
crypto0
lfkmqY:UO>ysUR:xUOdixsz~;ed++w
▶ 암호화된 파일
def xor_encrypt_decrypt(data: bytes, key: int) -> bytes:
return bytes([data[i] ^ key for i in range(len(data))])
# 테스트 코드
if __name__ == "__main__":
plaintext = b"flag{????}"
key = 10
encrypted = xor_encrypt_decrypt(plaintext, key)
with open("encrypted_flag.bin", "wb") as f:
f.write(encrypted)
print("Encrypted file saved as encrypted_flag.bin")
▶ 파일을 암호화하는 스크립트
- Plaintext(flag)를 읽어 xor를 통한 암호화 구조를 파악
def xor_encrypt_decrypt(data: bytes, key: int) -> bytes:
return bytes([data[i] ^ key for i in range(len(data))])
# 테스트 코드
if __name__ == "__main__":
plaintext = b"lfkmqY:UO>ysUR:xUOdixsz~;ed++w"
key = 10
encrypted = xor_encrypt_decrypt(plaintext, key)
print(encrypted)
▶ 파일을 복호화하는 스크립트
- Xor 비트 연산의 특성을 활용하여 복호화를 진행: A ^ B = C -> B ^ C = A 이용
- flag{S0_E4sy_X0r_Encrypt1on!!}
결론
노출되는 코드에 복호화 정보를 삽입하지 않도록 주의하는 것이 필요
crypto1
카이사르 암호 (Caesar cipher)
카이사르 암호는 고대 로마의 율리우스 카이사르(Julius Caesar)가 사용했다고 전해지는 간단한 암호화 기법으로, 알파벳을 일정한 수만큼 이동시키는 방식으로 암호화하는 방법이다.
▶ 알파벳을 3칸씩 이동하는 예시
synt{ebg13_vf_pynffvp_pvcure}
▶ 암호화된 파일
- 암호문의 형식 자체가 flag{ } 형식과 유사함을 확인
- f와 s의 차이가 l과 l과 y의 차이와 같은 것을 확인
def caesar_encrypt(text, shift):
result = ""
for i in range(len(text)):
char = text[i]
if char.isupper():
result += chr((ord(char) + shift - 65) % 26 + 65)
elif char.islower():
result += chr((ord(char) + shift - 97) % 26 + 97)
else:
result += char
return result
def caesar_decrypt(text, shift):
return caesar_encrypt(text, -shift)
plain_text = "synt{ebg13_vf_pynffvp_pvcure}"
shift = 13
decrypted_text = caesar_decrypt(plain_text, shift)
print(decrypted_text)
▶ 파일을 복호화하는 스크립트: Caesar cipher(카이사르) 코드 구현
- 문자가 대문자인 경우 'A'의 아스키 코드 값(65)을 기준으로 값을 이동한 후 다시 문자로 변환
- 26으로 mod 연산을 하여 범위를 넘어가는 값 처리
- 문자가 소문자인 경우 'a'의 아스키 코드 값(97)을 기준으로 값을 이동한 후 다시 문자로 변환
- 암호문의 시작 's'와 flag의 문자열의 시작 'f'의 차이가 13이므로 shift 값을 13으로 설정
- flag{rot13_is_classic_cipher}
결론
카이사르 암호는 현대의 암호화 기법에 비하면 매우 약한 보안 수준을 가지고 있음
- 이동값(shift)의 범위가 고정되어 있기 때문에, 가능한 모든 이동값(shcift)을 시도해보는 간단한 무차별 대입 공격으로 쉽게 해독할 수 있음
crypto2
문자 인코딩
- 사용자가 입력한 문자나 기호들을 컴퓨터가 이용할 수 있는 신호로 만드는 것을 말함
- 복잡한 신호를 0과 1의 디지털 신호(2진수)로 변환하는 것을 의미
- 대표적인 문자 인코딩에는 아스키 코드가 있음
아스키코드
아스키코드는 33개의 출력 불가능한 제어 문자들과 공백을 비롯한 95개의 출력 가능한 문자들로 0x00부터 0x7F까지 총 128개로 이루어져 있다.
▶ 아스키코드 표
666c61677b6865785f656e636f64696e675f69735f656173797d
▶ 암호화된 파일
- 두 글자씩 묶었을 때 16진수의 문자열임을 확인
def hex_to_ascii(hex_string):
ascii_string = ''.join(chr(int(hex_string[i:i+2], 16)) for i in range(0, len(hex_string), 2))
return ascii_string
hex_string = "666c61677b6865785f656e636f64696e675f69735f656173797d"
ascii_string = hex_to_ascii(hex_string)
print(ascii_string)
▶ 파일을 복호화하는 스크립트: 디코딩 코드 구현
- hex_string을 2자리씩 나눠서 16진수 값을 10진수로 변환한 후, 그 10진수를 chr() 함수로 ASCII 문자로 변환
- flag{hex_encoding_is_easy}
결론
아스키코드는 단순한 문자 인코딩 방식이기 때문에 보안 목적으로서의 암호화 기법으로 사용하기엔 적합하지 않음
crypto3
def xor_encrypt(input_file, output_file, key):
with open(input_file, 'rb') as f:
data = f.read()
print(len(data))
key_bytes = key.encode()
key_len = len(key_bytes)
encrypted_data = bytearray()
for i in range(len(data)):
encrypted_data.append(data[i] ^ key_bytes[i % key_len])
with open(output_file, 'wb') as f:
f.write(encrypted_data)
xor_encrypt('original.png', 'encrypted_flag.bin', '???') # 암호화
▶ 플래그를 획득할 수 있는 암호화 파일
- XOR 비트 연산을 진행하는 암호화 패턴을 확인
- 암호화 key가 ???로 가려져 있음
- original.png가 암호화된 것을 확인
▶ PNG 고유 구조를 통해 key를 알아낼 수 있음 (Hex dump라는 어플리케이션을 통해 내부 데이터 확인 가능)
- 0x89 0x50 0x4E ^ XorKey == 0xE2 0x38 0x3B
def xor_encrypt(input_file, output_file, key):
with open(input_file, 'rb') as f:
data = f.read()
print(len(data))
key_bytes = key.encode()
key_len = len(key_bytes)
encrypted_data = bytearray()
for i in range(len(data)):
encrypted_data.append(data[i] ^ key_bytes[i % key_len])
with open(output_file, 'wb') as f:
f.write(encrypted_data)
key = chr(0x89^0xE2) + chr(0x50^0x38) + chr(0x4E^0x3B)
xor_encrypt('encrypted_flag.bin', 'original.png', key) # 암호화
▶ 복호화된 PNG 파일 얻기 위한 스크립트
▶ 복호화된 original.png 사진
결론
파일 확장자에 따른 파일 Structure에 대한 개념을 익힐 수 있었음
crypto4
Base64
Base64란 8비트 2진 데이터(zip 파일이나 exe 파일 등)를 문자 코드에 영향을 받지 않는 공통 ASCII 영역의 문자들로만 이루어진 일련의 문자열로 바꾸는 인코딩 방식이다.
▶ Base64 색인표
▶ Base64 예시
- Base64 인코딩 시 input 보다 output의 길이가 길어질 수 있음
▶ Base64 디코딩 (방법 1)
import base64
def decode_base64(encoded_str):
decoded_bytes = base64.b64decode(encoded_str)
decoded_str = decoded_bytes.decode('utf-8')
return decoded_str
encoded_string = "ZmxhZ3tiYXNlNjRfaXNfaGFuZHl9"
decoded_string = decode_base64(encoded_string)
print(decoded_string)
▶ 파이썬 모듈 base64를 사용하여 디코딩 (방법 2)
- base64.b64decode() 함수는 base64로 인코딩된 문자열을 바이트 형태로 디코딩
- UTF-8 인코딩을 사용하여 문자열로 변환
- flag{base64_is_handy}
결론
Base64는 단순한 문자 인코딩 방식이기 때문에 보안 목적으로서의 암호화 기법으로 사용하기엔 적합하지 않음
'CS > 정보보호' 카테고리의 다른 글
해킹 문제 풀이 실습 (웹 해킹) - 1 (6) | 2025.05.21 |
---|---|
3. 인터넷 프로토콜과 웹 보안 (0) | 2025.04.14 |
2. 보안을 위한 네트워크 이론 (2) | 2025.04.04 |
해킹 문제 풀이 실습 (http_hack) - 2 (1) | 2025.04.03 |
해킹 문제 풀이 실습 (http_hack) - 1 (0) | 2025.04.02 |