[picoCTF] New Caesar writeup

SCY·2023년 1월 26일
0

picoCTF

목록 보기
8/13

문제

We found a brand new type of encryption, can you break the secret code?

mlnklfnknljflfjljnjijjmmjkmljnjhmhjgjnjjjmmkjjmijhmkjhjpmkmkmljkjijnjpmhmjjgjj

https://play.picoctf.org/practice/challenge/158?page=1&search=new%20caesar

풀이

문제 분석

  1. 우리가 찾을 값은 flag이다. assert문을 통해 key 값은 a와 p 사이의 값임을 알 수 있다.

  2. flag를 b16_encode 함수로 인코딩하고, shift 함수로 한 번 더 암호화한다. 이 때, key[i%len(key)]는 말장난으로, key[0]과 같다.

  3. b16_encode 함수
    첫글자를 'a'라고 했을 때 아래 과정을 거쳐 암호화된다.

    'a' --> 97 --> 0110|0001 --> 6|1 --> 'gb'
  4. shift 함수
    key 값은 고정이므로 t2는 고정된 값이고, 해당 연산으로 한 번 더 암호화한다.

복호화

import string

LOWERCASE_OFFSET = ord("a") # 97
ALPHABET = string.ascii_lowercase[:16] # a ~ p

enc = "mlnklfnknljflfjljnjijjmmjkmljnjhmhjgjnjjjmmkjjmijhmkjhjpmkmkmljkjijnjpmhmjjgjj"

for key in ALPHABET :
	dec = ""
	for e in enc :
		dec += unshift(e, key)
	dec = b16_decode(dec)
	print(f"key : {key}, flag : {dec}")

문제는 b16_encode -> shift 과정을 거쳤으므로
나는 반대로 unshift -> b16_decode 과정으로 코드를 작성했다.
key 값은 알 수 없기 때문에 a부터 p까지 모든 경우를 출력해준다.

def unshift(c, k) :
	t1t2 = ord(c) - LOWERCASE_OFFSET
	t2 = ord(k) - LOWERCASE_OFFSET
	t1 = t1t2 - t2
	if t1 < 0 :
		t1 += 16
	return chr(t1 + LOWERCASE_OFFSET)

t1t2는 shift 함수의 (t1 + t2) % 16을 의미한다.
t2는 shift 함수의 t2와 동일하다.
두 수의 차로 t1을 생성해 주었다.

shift 함수의 모듈러를 무시하고 if문을 작성하지 않아 답을 찾지 못했었다.
t1이 음수가 될 수 있음을 고려하여 if문을 추가해 주었다.
shift 함수의 t1 + t2가 최대 32임을 계산하여
t1에 16을 한 번만 더해도 괜찮다고 판단하였다.

def b16_decode(txt) :
	res = ""
	for i in range(0, len(txt), 2) :
		tmp1 = ALPHABET.index(txt[i])
		tmp2 = ALPHABET.index(txt[i+1])
		res += chr((tmp1 << 4) + tmp2)
	return res

문제 분석 3번에 작성한

'a' -> 97 -> 0110|0001 -> 6|1 -> 'gb'

과정을 reverse한다는 생각으로 차근차근 코드를 작성했다.


위와 같은 결과가 출력되었고 key가 g일 때 가장 괜찮은 답이 나온다.

정답

picoCTF{et_tu?_5723f4e71a0736d3b1d19dde4279ac03}

profile
성장 중독 | 서버, 데이터, 정보 보안을 공부합니다.

0개의 댓글