본문으로 바로가기

riftCTF

category CTF/CTF Playground 2020. 3. 21. 05:01

반 년 동안 했던 CTF 중 가장 열받는 CTF였다. 하다가 짜증나서 때려치운다.

이전에 했던 CTF들이 어떤 문제점들을 1개씩 갖고 있었다면 이 CTF는 그 모든 문제점들을 한 데 모아 때려박은 것 같다.

 

1. 웹 latency 10분 이상

2. 일관적이지 않은 플래그 형식

3. Not user-friendly 한 UI 구성

4. (개인적으로 맘에 안드는) 문제 유형들

 

이 CTF는 CTFd 프레임워크를 사용한다. 설정을 잘못한 건지 문제 로딩, 플래그 제출 등 모든 요청에 대해 서버 응답이 짧게는 2분에서 길게는 30분 뒤에 온다. 두 번째 문제인 비일관적인 플래그 형식은 이 느린 연결 속도와 합쳐져서 환장환상적인 사용자 경험을 제공한다. 문제 페이지에서는 줄바꿈을 그대로 LF로 넣어버려서 읽기가 불편하고, 메인 화면도 텍스트만 때려박아서 가독성이 꽝이다.

 

리버싱으로 나온 문제는 바이너리를 뜯어보기만 하면 보이는 2개의 문제와 VM 리버싱이라는 엄청난 난이도 양극화를 보여준다. (뒤에 몇 개 문제가 추가되었는데, 연결 속도 때문에 볼 수가 없다.) 암호학이라고 나온 문제는 대부분이 Substitution Cipher이고, dcode의 tool list에서 뽑아다가 대강 만든 것 같다. 다른 분야는 마찬가지로 답답한 웹 반응 때문에 확인조차 못했다.

 

perfect ui provided

 

아무튼 그런 이유로 더 풀어보고 싶었지만 하다가 관뒀다. 처음으로 여는 CTF라고 하는데 최소한 팀 내부에서 사전 검증이라도 해 봤으면 하는 아쉬움이 있다.

 

Reverse Engineering :: Rev 0x0001

Flag: riftCTF{tr4c1ng-mAkes-17-SUPeR-345Y}

 

Reverse Engineering :: Rev 0x0002

0x2050에 위치한 37바이트를 0x55랑 XOR하면 플래그가 나온다.

 

Flag: riftCTF{tr4cing_d03snt_w0rk_anyM0r33}

 

Reverse Engineering :: Rev 0x0004

compare (0x1175, 비교 함수) 호출하기 전에 bp 설정하고 스택 메모리 보면 플래그가 보인다.

bp 걸고 run 하면 실행이 안 되는데, starti를 쓰니까 잘 됐다.

 

Flag: riftCTF{---=[Did_Y0U_kN0W_YoU_CoU1D_ActuallY_FinD_ThE_FlaG_1n_m3M0rY]=--}

 

Reverse Engineering :: Not XVM 2.0

Intel pin을 사용해 instruction count 기준의 side channel attack으로 플래그를 한 글자씩 뽑아올 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import copy
import logging
import os


def RetrieveInsCount(input_str) :
    cmdline = 'echo "{}" | ./pin/pin -t ./obj-intel64/inscount0.so -- ./xvm ./crackme > /dev/null'.format(input_str)
    os.system(cmdline)

    with open('inscount.out'as f :
        inscount = int(f.read().split(' ')[1])

    return inscount


def TestLength(length_limitprefix='') :
    for l in range(len(prefix), length_limit) :
        inp = prefix+'A'*(l+1-len(prefix))
        inscount = RetrieveInsCount(inp)
        print('[Info] Input Length={}, Instruction Count={}'.format(l+1, inscount))


def TestInput(lengthprefix=''charset='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&\'()*+,-./:;<=>?@[]^_{}~') :
    found = copy.deepcopy(prefix)

    for index in range(len(found), length) :
        dc = {}

        for c in charset :
            inp = found + c + 'A'*(length-len(found)-1)
            inscount = RetrieveInsCount(inp)
            dc[c] = inscount
            print('[Info] Input={}, Instruction Count={}'.format(inp, inscount))

        expected = '\x00'
        highest = -1
        avg = 0

        for key in dc :
            avg += dc[key]

            if dc[key] > highest :
                expected = key
                highest = dc[key]

        found += expected
        avg = (avg-highest)/(len(charset)-1)

        print('[Info] Applying character \'{}\' at index={}, Instruction Count={} (excl. Average={})'.format(expected, index, highest, avg))
        if highest-avg <= 725 : print('[Info] WARNING: The test is unreliable; difference={}'.format(highest-int(avg)))

    print('[Info] Final input: {}'.format(found))


if __name__ == '__main__' :
    try :
        #TestLength(60)
        TestInput(28)

    except KeyboardInterrupt :
        exit()

    except Exception as e :
        logging.error('Error'exc_info=e)
        exit()

 

Flag: riftCTF{s0lv3d_w1th0ut_r3versiiNG_;)}

 

Cryptography :: crypto 0x0001

주어진 문자열을 BASE64로 4번 디코딩한다.

 

Flag: riftCTF{Its_4LL_ab0ut_BaS3}

 

Cryptography :: crypto 0x0005

Daggers' Alphabet

 

 

Flag: riftctfbonjourelliot

 

Cryptography :: crypto 0x0003

DNA Cryptography

A는 00, T는 01, C는 11, G는 10에 대응된다. 4글자씩 자른 뒤 문자열을 이진수로 치환하고 little endian으로 문자로 변경하면 된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def strand_to_num(c) :
    if c == 'A' : return 0b00
    if c == 'T' : return 0b11
    if c == 'C' : return 0b01
    if c == 'G' : return 0b10
    return None


if __name__ == '__main__' :
    flag_enc = 'GATCCGGCGCGCACTCTAACACCCGCACTGTCTACCTCTAACTACGTCTTCCTATCCAGCGCGCCCGCTTCCGCGCGATCAATACTGCTTCCTAACAATAGATCTTGCGTACACTACTTC'
    flag = ''
    cut = [flag_enc[i:i+4for i in range(0len(flag_enc), 4)]

    for c in cut :
        ch = 0

        for i in range(4) :
            ch += strand_to_num(c[i]) << 2*i

        flag += chr(ch)

    print(flag)

 

Flag: riftCTF{S74y_safe_fr0m_C0roN4}

 

Cryptography :: crypto 0x0004

Navy Signal Flags

 

 

Flag: RIFTCTFJUSTA7R1BUT3T0ARMEDFORCES (Unconfirmed)

 

Miscellaneous :: Misc 0x0001

디스코드 #flag 채널에 플래그가 있다.

 

Flag: riftCTF{sanity_check}

 

Miscellaneous :: Misc 0x0005

https://www.cloudflare.com/learning/ddos/ddos-attack-tools/slowloris/

 

Flag: riftCTF{application}

 

Miscellaneous :: Misc 0x0006

https://ai.googleblog.com/2019/10/quantum-supremacy-using-programmable.html

ps. Google의 Sycamore는 54-qubits 프로세서지만 실험 당시에는 53개만 돌아갔다고 한다. 따라서 엄밀히는 "operates on 54-qubits" 가 맞는 표현이다.

 

Flag: riftCTF{sycamore}

 

Miscellaneous :: Misc 0x0002

mp3를 추출한 뒤 거꾸로 재생하면 된다.

The Weeknd - The Hills

 

Flag: riftCTF{the_hills}

 

Miscellaneous :: Misc 0x0004

XOR 연산에 대한 진리표 이미지를 준다. 101과 110을 XOR한 011을 플래그 형식에 맞춘 게 정답이다.

 

Flag: riftCTF{011}

'CTF > CTF Playground' 카테고리의 다른 글

TAMUctf 2020  (0) 2020.03.30
Securinets Prequals 2K20  (0) 2020.03.23
ångstromCTF 2020  (0) 2020.03.16
HackTM CTF 2020  (0) 2020.02.02
Rice Tea Cat Panda #cat-chat  (0) 2020.01.24