HackCTF Classic Cipher -3
2022. 3. 13. 04:42ㆍ0x0D Crypto
728x90
사용해야하는 지식: affine cipher
공식:
val = (a*p+s) % 26
p는 각 알파벳의 인덱스
예를 들어 'a'인 경우 인덱스는 [0]
Cipher
FqyeYBX{Yv4kk1y_Y1lfgt_1k_jgti_g4ki_1x91cqx14x}
공식에 의거하여 추출한 딕셔너리
{'0': ['0, 7'], '1': ['1, 2'], '2': ['2, 23'], '3': ['3, 18'], '4': ['4, 13'], '5': ['5, 8'], '6': ['6, 3'], '7': ['7, 24'], '8': ['8, 19'], '9': ['9, 14'], '10': ['10, 9'], '11': ['11, 4'], '12': ['12, 25'], '13': ['13, 20'], '14': ['14, 15'], '15': ['15, 10'], '16': ['16, 5'], '17': ['17, 0'], '18': ['18, 21'], '19': ['19, 16'], '20': ['20, 11'], '21': ['21, 6'], '22': ['22, 1'], '23': ['23, 22'], '24': ['24, 17'], '25': ['25, 12']}
딕셔너리를 통해 Cipher 각 인덱스 찾은 결과물
플래그 형태 HackCTF임을 알고 있기 때문에 7바이트만으로 규칙을 찾을 수 있다.
upper enc value = F / a = 0 / s = 7
upper enc value = F / a = 1 / s = 2
upper enc value = F / a = 2 / s = 23
upper enc value = F / a = 3 / s = 18
upper enc value = F / a = 4 / s = 13
upper enc value = F / a = 5 / s = 8
upper enc value = F / a = 6 / s = 3
upper enc value = F / a = 7 / s = 24
upper enc value = F / a = 8 / s = 19
upper enc value = F / a = 9 / s = 14
upper enc value = F / a = 10 / s = 9
upper enc value = B / a = 10 / s = 9
upper enc value = X / a = 10 / s = 9
upper enc value = F / a = 11 / s = 4
upper enc value = F / a = 12 / s = 25
upper enc value = F / a = 13 / s = 20
upper enc value = F / a = 14 / s = 15
upper enc value = F / a = 15 / s = 10
upper enc value = F / a = 16 / s = 5
upper enc value = F / a = 17 / s = 0
upper enc value = F / a = 18 / s = 21
upper enc value = F / a = 19 / s = 16
upper enc value = F / a = 20 / s = 11
upper enc value = F / a = 21 / s = 6
upper enc value = F / a = 22 / s = 1
upper enc value = F / a = 23 / s = 22
upper enc value = Y / a = 23 / s = 22
upper enc value = B / a = 23 / s = 22
upper enc value = X / a = 23 / s = 22
upper enc value = F / a = 24 / s = 17
upper enc value = F / a = 25 / s = 12
lower enc value = q / a = 23 / s = 22
lower enc value = y / a = 23 / s = 22
lower enc value = e / a = 23 / s = 22
Solve
알파벳이 대문자 일 경우, 대문자로만 치환되며
알파벳이 소문자 일 경우, 소문자로만 치환된다.
#!-*-encoding:utf-8-*-
enc = "FqyeYBX{Yv4kk1y_Y1lfgt_1k_jgti_g4ki_1x91cqx14x}"
# block, { } 숫자 고정
'''
지식: affine cipher
val = (a*p+s) % 26
p는 각 알파벳의 인덱스
예를 들어 'a'인 경우 인덱스는 [0]
'''
import string
target = "HackCTF"
# H의 경우 인덱스 [7]
# 즉, p는 7
tmp_upper = string.ascii_uppercase
tmp_lower = string.ascii_lowercase
p = 7
offset = 0
flag = -1
'''
while(offset < len(target)):
for a in range(0,26):
for s in range(0,26):
#print(f'test = {type(ord(target[offset]))}')
#exit(0)
if(ord(enc[offset]) >= 65 and ord(enc[offset]) <= 90):
val = (a*tmp_upper.find(enc[offset])+s) % 26
flag = 0 # upper
elif(ord(enc[offset]) >= 97 and ord(enc[offset]) <= 122):
val = (a*tmp_lower.find(enc[offset])+s) % 26
flag = 1 # lower
elif(ord(enc[offset]) == 95 or ord(enc[offset]) == 123 or ord(enc[offset]) == 125):
offset += 1
continue
elif(ord(enc[offset]) == 49 and ord(enc[offset]) == 57):
offset += 1
continue
if(val > 26):
val %= 26
try:
if(flag==0): # upper
if(tmp_upper[val] == target[offset]): # 하나 만족하는게 있다면
print(f'enc\'s index = {tmp_upper.find(enc[offset])} / enc val = {tmp_upper[tmp_upper.find(enc[offset])]} / a = {a} / s = {s} / decode = {target[offset]}') # 0 / 5
offset += 1
else:
#print(f'[fail] a = {a} / s = {s}')
continue
if(flag==1): # lower
if(tmp_lower[val] == target[offset]): # 하나 만족하는게 있다면
print(f'enc\'s index = {tmp_lower.find(enc[offset])} / enc val = {tmp_lower[tmp_lower.find(enc[offset])]} / a = {a} / s = {s} / decode = {target[offset]}') # 0 / 5
offset += 1
else:
continue
except IndexError as e:
break
'''
'''
enc's index = 5 / enc val = F / a = 0 / s = 7 / decode = H
enc's index = 16 / enc val = q / a = 1 / s = 10 / decode = a
enc's index = 24 / enc val = y / a = 2 / s = 6 / decode = c
enc's index = 4 / enc val = e / a = 3 / s = 24 / decode = k
enc's index = 24 / enc val = Y / a = 4 / s = 10 / decode = C
enc's index = 1 / enc val = B / a = 4 / s = 15 / decode = T
enc's index = 23 / enc val = X / a = 4 / s = 17 / decode = F
'''
# round 2
a = 0
s = 0
t = 0
dict = {}
while(a < 26):
for s in range(26):
if(ord(enc[offset]) >= 65 and ord(enc[offset]) <= 90):
val = (a*tmp_upper.find(enc[offset])+s) % 26
flag = 0 # upper
elif(ord(enc[offset]) >= 97 and ord(enc[offset]) <= 122):
val = (a*tmp_lower.find(enc[offset])+s) % 26
flag = 1 # lower
elif(ord(enc[offset]) == 95 or ord(enc[offset]) == 123 or ord(enc[offset]) == 125):
continue
elif(ord(enc[offset]) == 49 and ord(enc[offset]) == 57):
continue
if(val > 26):
val %= 26
if(flag==0):
if(tmp_upper[val] == target[offset]): # 하나 만족하는게 있다면
dict[str(t)] = [f'{a}, {s}']
a += 1
s = 0
t += 1
else:
continue
if(flag==1):
if(tmp_lower[val] == target[offset]): # 하나 만족하는게 있다면
dict[str(t)] = [f'{a}, {s}']
a +=1
s = 0
t += 1
else:
continue
print(dict)
result = 0
cnt = 0
f = open("affine_parse","w")
for key,value in dict.items():
tmp = value[cnt]
a= int(tmp.split(",")[0])
s= int(tmp.split(",")[1].replace(" ",""))
# formula
# a * 문자인덱스 + s % 26
# enc= FqyeYBX
# target = HackCTF
for i in range(8):
if(enc[i] >= 'A' and enc[i] <= 'Z'):
p = tmp_upper.find(enc[i])
tmp = (a * p + s) % 26
if(tmp > 26):
tmp %= 26
if(tmp_upper[tmp] == target[i]):
f.writelines(f'upper enc value = {enc[i]} / a = {a} / s = {s}' + "\n")
for key,value in dict.items():
tmp = value[cnt]
#print(tmp)
a= int(tmp.split(",")[0])
s= int(tmp.split(",")[1].replace(" ",""))
for i in range(8):
if(enc[i] >= 'a' and enc[i] <= 'z'):
p = tmp_lower.find(enc[i])
tmp = (a * p + s) % 26
if(tmp > 26):
tmp %= 26
if(tmp_lower[tmp] == target[i]):
f.writelines(f'lower enc value = {enc[i]} / a = {a} / s = {s}' + "\n")
f.close()
# result : affine_parse를 통해 찾음
a= 23
s= 22
dec = ""
for i in range(len(enc)):
if(enc[i] >= 'a' and enc[i] <= 'z'):
tmp = ( a * tmp_lower.find((enc[i])) + s ) % 26
if(tmp > 26):
tmp %= 26
dec += tmp_lower[tmp]
elif(enc[i] >= 'A' and enc[i] <= 'Z'):
tmp = ( a * tmp_upper.find((enc[i])) + s ) % 26
if(tmp > 26):
tmp %= 26
dec += tmp_upper[tmp]
else:
dec += enc[i]
print(dec)

'0x0D Crypto' 카테고리의 다른 글
HTB ke (0) | 2020.07.03 |
---|---|
HTB - Bank heist (0) | 2020.07.02 |
Math Study Journey (0) | 2020.06.14 |
Math (0) | 2020.06.10 |
Rootme Prob. SHA 2- (0) | 2020.02.02 |