Misc 4개 / Crypto 1개 / Reverse 1개 / Web 0개 / Pwn 0개


위와 같이 문제풀고 마무리. Pwn 문제를 좀 더 풀고 싶었지만 heap overflow를 아직 몰라서(공부해야한다...) 풀지 못했다.


[Misc]Sign



간단한 문제다 IDA를 이용해 스트링을 살펴보면 FLAG를 찾을 수 있다.



RCTF{WelCOme_To_RCTF}




[Misc] git



git 관련해서 파일을 하나 주는데, 로그를 보면 하나밖에 없다. flag를 검색하면 뭔가 나오지않을까해서 Notepad++로 끌어다가 검색해보니 아니다 다를까

Flag라고 커밋해둔게 있다. git checkout을 해서 다시 되돌려주면 flag.txt를 얻을 수 있다.




굿..



[Misc] cats



꽤나 재미있는 문제였다. 주어진 url로 들어가면 아래와 같은 문구를 볼 수 있다.


I love cats! Can you find 15 cats for me ._.?

I'll save the cat food as file "food" and observe whether the outcomes of "cat food" and "eachCatNameYouProvided food" are exactly the same (including return code and trailing CRLFs). Download dockerfile to find cats locally, or you may find reCAPTCHA annoying.

dockerfile을 주는데, 어떻게 cats를 찾느냐. 이 dockerfile을 통해서 가상이미지 환경설정을 하고 그 컨테이너에서 cat들을 찾으면 된다.

도커(docker)는 컨테이너 기반의 오픈소스 가상화 플랫폼이라고 하는데, 자세한 건 검색하면 좋은 자료들이 많이 나온다.


참고자료 : 

https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html

http://pyrasis.com/Docker/Docker-HOWTO#dockerfile


cat을 찾는 방법은 간단하다. 

명령어로 cat food했을때 나오는 결과와 eachCatNameYouProvided food라고 쳤을때 나오는 결과가 같으면 된다. (둘다 CRLF(\r, \n 등등)으로 끝마쳐 리턴해준다.)


예를 들어 tarcat이란 명령어가 있는데 아래와 같이 치면 둘다 같은 결과를 반환해주는 것을 알 수 있다.

cat: food: No such file or directory



이제 환경변수 PATH에 등록되어있는 곳에서 명령파일들을 하나하나 실행시켜가며 찾든가 하면 된다.

필자는 find 명령어를 사용해서 쓸만한 바이너리파일들을 모아서 cat과 비슷한 결과가 나오는 놈들을 찾게 코드를 돌려서 찾았다.




cat과 같은 결과를 내놓는 명령어들은 대부분 아래와 같다.

tarcat, tail, head, sort, shuf, fold, expand, paste, unexpand, iconv, bash, sh, rbash, erb, dash


RCTF{you_love_cats_dont_you}



[Misc] Number Game



넘버게임이라고 nc로 접속하게 되면, 게임에 들어가기 전에 proof of work를 해야한다.

주어진 sha256 해시값과 같은 해시값을 가지게 4자리 XXXX를 채워넣어주면 게임이 시작된다.


게임은 숫자야구게임으로 외국에서는 Bulls and Cows 라고 불리는 게임이다. 6번의 기회가 주어지고 중복없는 4자리 숫자를 순서에 맞게 맞추면 되는 게임이다. 자세한 룰은 이쪽에서 보면 좋다.(한글번역은 이쪽)


하드코딩해서 풀면 된다. Bulls and Cows solver 라고 검색해서 적당한 소스를 가져와서 문제의 조건에 맞게 수정해서 사용하였다.

소스가 길어서 따로 글을 작성해서 올렸다.


Solve.py



[Reverse] babyre


babyre라는 바이너리 파일과 out파일을 주는데, out으로 나온게 아마 암호화된 flag일 것이다.

babyre 파일을 분석해보면 처음에 문자열과 정수를 입력받고 "your input:try again"라는 문자열을 출력하고 다시 입력을 받는데


이때 입력한 문자들이 각각 인코딩되서 나오므로, 이를 이용해서 out을 디코딩할 수 있다.


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
from pwn import *
import string
 
 
 
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()_+{}.,/'"
table = [alpha[i:i+30for i in range(0,len(alpha),30)]
print(table)
 
p_table = {}
 
for plain in table:
    conn = process("./babyre")
    conn.sendline("A"*32)
    conn.sendline(str(32))
 
    conn.sendline(plain)
    conn.recvuntil("try again")
    for i in range(len(plain)):
        #print(plain[i]+" :"),
        P = conn.recvline().strip().upper()
        p_table[P]=plain[i]
    conn.close()
 
= open("out"'r')
lines = f.readlines()
f.close()
 
flag = ""
 
for c in lines:
    if c[:8in p_table:
        flag += p_table[c[:8]]
    else:
        flag += "?"
    if c[8:16in p_table:
        flag += p_table[c[8:16]]
    else:
        flag += "?"
 
 
print(flag)
 
 
cs






[Crypto]cpushop


nc를 통해 들어가면 돈과 무엇을 할 수 있는 지 나온다.

문제소스는 여기 

cpushop.py




과연 cpushop이라 할만하다. List Items를 해보면 CPU들과 가격이 나온다.

그리고 9번째 항목을 보면 Flag도 팔 고 있는 것을 볼 수 있다. 물론 돈이 없어서 Flag를 살 수는 없다...


물건을 사려면 먼저 Order을 통해서 Items ID에 해당하는 구입증(?)을 발급받아야한다. 

만약 0번 제품인 Intel Core i9-7900을 산다고 하면 아래와 같은 코드에 의해서 출력된 것을 Pay에 입력하면 물건을 살 수 있다.


1
2
3
4
    payment = 'product=%s&price=%d&timestamp=%d' % (items[n][0], items[n][1], time.time()*1000000)
    sign = sha256(signkey+payment).hexdigest()
    payment += '&sign=%s' % sign
    print 'Your order:\n%s\n' % payment
cs



payment에 제품에 대한 정보가 들어가 있고, 그 제품정보들 앞에 signkey를 붙여 sha256으로 서명한 값이 payment뒤에 붙어 고객에게 전달되고,

그 값을 고객이 제출하면 샵에서는 payment에서 sign값을 파싱해 그 값을 가지고 payment에 대한 무결성을 검증할 수 있고 고객은 상품을 구입할 수 있다. 


만약 상품정보에서 price값을 낮게 설정하고 그 값에 대한 sha256 sign값이 있다면 Order을 통해서 상품구입이 가능하고 우리는 Flag를 구입할 수 있을 것이다. 참고로 Shop측에서 제품정보를 파싱하는 부분에서 취약점이 있는데 아래와 같다.


1
2
3
4
5
6
7
8
9
    for k,v in parse_qsl(payment):
        if k == 'product':
            product = v
        elif k == 'price':
            try:
                price = int(v)
            except ValueError:
                print 'Invalid Order!'
                return
cs


어디가 취약한지 알겠는가? 만약 payment과 다음과 같다면 어떻게 될 것 같은가..?


payment = "product=Flag&price=999&timestamp=15235&price=1"


기존의 payment 뒤에 price=1이라는 값을 붙여쓴것이다. 

만약 위와 같은 payment가 있다면 price값을 파싱할때, 처음 만난 price=999에서 price=999로 설정하고 계속 for문을 돌다가 마지막에 price를 또 만나 최종적으로 price=1로 설정되고 종료될 것이다.


그러므로 여기서 할 공격은 Hash Length Extension Attack이다!

github에 hash_extender라는 툴이 있으므로 이것을 이용해서 공격할 것이다.


(대회가 끝나고 몇달이 지난후, 우연히 다른 사람의 writeup을 보게 되었다. python 라이브러리중 hashpumpy라는 꿀툴이 있더라... ㄷㄷ;; 이걸 이용하면 좀 더 소스가 깔금해진다. )

https://ctftime.org/task/6126


참고로 우리는 signkey는 모르므로 signkey의 길이는 브루트포싱으로 맞춰줘야한다.



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
66
67
#!/usr/bin/env python
 
from pwn import *
import string
from subprocess import Popen, PIPE
 
#context.log_level = 'debug' 
#conn = remote('cpushop.2018.teamrois.cn', 43000)
conn = process(['python''cpushop/cpushop.py'])
 
def OrderItemFlag(id=9):
    conn.sendline("2")
    conn.recvuntil("Product ID:")
    conn.sendline(str(id))
    
    conn.recvline()
    payment=conn.recvline().strip()
    return payment
 
    
def SHA256_Extender(paym, sign, keylen):
    fake_price = "&price=1"
    keylen = str(keylen)
    
    command = './hash_extender --data "'+ paym +'" --secret '+keylen+' --append "'+ fake_price +'" --signature '+sign+' --format sha256'    
    popen = Popen(command, shell=True, stdout=PIPE)
    output, error = popen.communicate()
    
    New_signature, expanded_payment = output.split("New string: ")
    New_signature = "&sign="+(New_signature.split("New signature: "))[1].strip()
    expanded_payment = expanded_payment.strip().decode("hex")
    
    expanded_payment += New_signature
    return expanded_payment
    
def PayItem(payment):
    conn.sendline("3")
    conn.recvuntil("Your order:")
    conn.sendline(payment)
    conn.recvline()
    result=conn.recvline()
    return result
 
 
print(conn.recvuntil('Command:'))    
payment = OrderItemFlag()
 
paym, sign = payment.split("&sign=")
 
for keylen in range(8,32):
    print("keylen : " + str(keylen))
    conn.recvuntil('Command:')
    payment = SHA256_Extender(paym,sign,keylen)
    result = PayItem(payment)
    
    if "Invalid Order!" not in result:
        print(result)
        conn.interactive()
 
#conn.shutdown()  # Ctrl+D
conn.interactive()
 
"""
https://github.com/iagox86/hash_extender
./hash_extender --data "product=Intel Core i9-7900X&price=999&timestamp=1526710428630790" --secret 20 --append append --signature a3f3282990039a1cb6816c172b9e5d44308213c25d0c76d3d5dddfb627b2a0f8  --format sha256
"""
 
cs


'Write-up > CTF _ Write UP' 카테고리의 다른 글

[HITCON-Training] lab12 : secretgarden  (0) 2019.07.13
DEFCON CTF Quals 2018 Writeup  (0) 2018.05.14
[WriteUP] Byte Bandits CTF 2018  (0) 2018.04.10
[WriteUp] UIUCTF 2018 Writeup  (0) 2018.04.10

+ Recent posts