DreamHack/CTF

(CTF 출제) amocafe

G_OM 2024. 9. 5. 13:41

암호학문제인데 인 거 같은데

 

 

 

 

 

 

 

 

 

 

그냥 커피 마시지..

 

일단 소스코드를 한번 보자

 

 

 

 

 

 

 

 

 

def index():
    menu_str = ''
    org = FLAG[10:29]
    org = int(org)
    st = ['' for i in range(16)]

    for i in range (0, 16):
        res = (org >> (4 * i)) & 0xf
        if 0 < res < 12:
            if ~res & 0xf == 0x4:
                st[16-i-1] = '_'
            else:
                st[16-i-1] = str(res)
        else:
            st[16-i-1] = format(res, 'x')
    menu_str = menu_str.join(st)

 

 

menu_str = '' 

> menu_str에 빈 문자열을 선언한다.

 

org = FLAG [10:29]

> FLAG 변수에서 인덱스 11 [시작점]부터 28까지의 슬라이스를 가져와 org 변수에 저장된다. (10,29는 미포함)

 

org = int(org)              [FLAG 값을 가지고 있는 org]

> org 값을 정수로 변환시킨다.

 

st = ['' for i in range(16)]

> 길이가 16인 리스트를 생성하여 st에 저장한다 여기서 리스트는 자리만 있지 전부 빈 문자열이다.

 

for i in range (0,16) {

>  16번 반복

 

res = (org >> (4*i)) & 0xf

> org 값을 오른쪽으로 4 * i 만큼 시프트 한다.

 

if 0 < res < 12:

> res가 0 보다 크고 12보다 작은지 확인 res 가 1부터 11 사이의 값일 경우 참

 

if ~res & 0xf == 0x4:

> res의 비트 반전값을 계산한 후 & 0xf로 하위 4비트만 추출한다 그리고 그 값이 0x4 인지 확인한다.

 

st [16-i-1] = '_'

> 위의 조건이 참일 경우 리스트 st의 (16-i-1) 번째 위치에 '_'를 저장시킨다.

 

else: st [16-i-1] = str(res)

> 참이 아니라면 res 값을 문자열로 변환시켜 똑같이 st [16-i-1] 위치에 저장시킨다.

 

else: st[16-i-1] = format(res, 'x') }

> if 0 < res < 12: 조건이 참이 아닐 때 res 값을 16진수 형식으로 변환시켜 문자열에 저장한다

 

menu_str = menu_str.join(st)

> 리스트인 st의 모든 요소를 합쳐 menu_str에 저장한다.

>그래서 문제에 해당되는 문자열 1_c_3_c_0__ff_3e  이 나온 것이다.

 

이 문제를 풀기 위해서는 이진법, 시프트를 따로 공부해야 할 거 같다

설명해 주기에는 반복문이 자꾸 시프트를 써서 오버다

 

하나 예시를 들어주면

 

10진수 13을 이진수로 변환 -> 00001101

 

오른쪽으로 4비트 시프트를 했을 때

 

[13 >> 4] -> 00000000 [시프트 후 이진수] -> 결과는 0 이 된다.

 

그러면 오른쪽으로 1비트 시프트를 했을 때는

[13 >> 1] -> 00000110 [시프트 후 이진수] -> 결과는 6 이 된다.

 

오른쪽으로 밀어내는 듯한 느낌?으로 알면 될 거 같다.

 

그러면 연산에 대한 계산법을 알았으니 역연산을 해야 답을 추출할 수 있다.

 

 

 

 

 

 

for char in encoded_str:
        if char == '_':
            value = 0xb
        elif char in 'cdef':
            value = int(char, 16)
        else:
            value = int(char)

        result |= (value << (shift_amount * 4))
        shift_amount -= 1

 

디코딩 중요한 부분을 가져와 봤다.

 

일단은 반대로 '_' 먼저 처리하도록 하자  '_' 경우 에는 0xb(11)로 처리하도록 하고...

 

문자열에 c, d, e, f 중 포함이 될 경우 16진수로 변환하여 value에 저장

 

숫자인 경우에도 문자 그대로 정수로 변환하여 value에 저장

 

shift_amount를 설정하여 왼쪽으로 4비트 시프트를 시킨다.

 

실행될 때마다 shift_amount는 1씩 줄어든다.

 

실행해서 코드를 주면....

 

 

 

 

 

 

뱉어낸다 오래 걸렸다 은근