[0ctf 2017] integrity - 75p

2018. 5. 2. 00:06

0ctf quals 2017 : integrity

Category: Crypto Points: 75 Solves: Description:

Just a simple scheme.

nc 202.120.7.217 8221

integrity_f2ed28d6534491b42c922e7d21f59495.zip


문제가 괜찮아서 writeup을 써본다.


문제코드는 아래와 같다.


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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/python -u
 
from Crypto.Cipher import AES
from hashlib import md5
from Crypto import Random
from signal import alarm
 
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 
unpad = lambda s : s[0:-ord(s[-1])]
 
 
class Scheme:
    def __init__(self,key):
        self.key = key
 
    def encrypt(self,raw):
        raw = pad(raw)
        raw = md5(raw).digest() + raw
 
        iv = Random.new().read(BS)
        cipher = AES.new(self.key,AES.MODE_CBC,iv)
 
        return ( iv + cipher.encrypt(raw) ).encode("hex")
 
    def decrypt(self,enc):
        enc = enc.decode("hex")
 
        iv = enc[:BS]
        enc = enc[BS:]
 
        cipher = AES.new(self.key,AES.MODE_CBC,iv)
        blob = cipher.decrypt(enc)
 
        checksum = blob[:BS]
        data = blob[BS:]
 
        if md5(data).digest() == checksum:
            return unpad(data)
        else:
            return
 
key = Random.new().read(BS)
scheme = Scheme(key)
 
flag = open("flag",'r').readline()
alarm(30)
 
print "Welcome to 0CTF encryption service!"
while True:
    print "Please [r]egister or [l]ogin"
    cmd = raw_input()
 
    if not cmd:
        break
 
    if cmd[0]=='r' :
        name = raw_input().strip()
 
        if(len(name) > 32):
            print "username too long!"
            break
        if pad(name) == pad("admin"):
            print "You cannot use this name!"
            break
        else:
            print "Here is your secret:"
            print scheme.encrypt(name)
 
 
    elif cmd[0]=='l':
        data = raw_input().strip()
        name = scheme.decrypt(data)
 
        if name == "admin":
            print "Welcome admin!"
            print flag
        else:
            print "Welcome %s!" % name
    else:
        print "Unknown cmd!"
        break
 
 
 
cs


AES로 암호화하는데 CBC모드를 이용한다. CBC모드란?


CBC모드는 랜덤하게 생성된 IV으로 첫 블록을 암호화시킨 암호문을 다음 블록의 암호화에 사용한다. 


CBC encryption.svg

CBC decryption.svg

If the first block has index 1, the mathematical formula for CBC encryption is

while the mathematical formula for CBC decryption is



그런데 여기 문제에서는 secret값의 IV || encrypted형식이고 encrypted는 md5(pad(username)) || pad(username)이다.


CBC모드는 IV로 블록을 암호화한 암호문을 다음 블록을 암호화하는데 쓰이므로, IV를 떼어낸 encrypted만 보내면 encrypted의 첫 블록을 IV로 사용하여 나머지 블록들은 모두 복호화가 될 것 이다.


우리가 이 값 md5(pad("admin")).digest() || admin을 username으로 보내면 


IV || enc(real md5) || enc(admin md5) || enc(admin) 이렇게 값이 돌아올 것이다. 


+---------+------------------------+--------------------+---------------+ | IV | Enc(md5(admin)||admin) | Enc(md5(admin)) | Enc(admin) | +---------+------------------------+--------------------+---------------+


md5가 128bit이고 암호화 블록사이즈를 128bit로 해서 이런 암호문을 얻을 수 있는 것이다.


여기서 우리가 필요한 값은 admin을 복호화시키는 것 뿐이므로 IV와 첫암호화블록 C1을 빼버린 값을 보낸다면


Enc(md5(admin))값이 IV로 들어가서 Enc(admin)을 복호화하여 admin만 남게 될 것이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
from hashlib import md5
 
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 
unpad = lambda s : s[0:-ord(s[-1])]
 
 
name = md5(pad("admin")).digest() + "admin"
 
= remote("202.120.7.217"8221)
 
r.sendlineafter("or [l]ogin\n""r")
r.sendline(name)
r.recvuntil("secret:\n")
secret = r.recvline().strip()
 
r.sendlineafter("or [l]ogin\n""l")
r.sendline(secret[32:])
r.interactive()
cs



'Write-up > Crypto' 카테고리의 다른 글

[Byte Bandits CTF 2018]R u Ronald Rivest?  (0) 2018.06.02
[Plaid CTF 2018] macsh - 125  (0) 2018.05.07
[Byte Bandits CTF 2018] R u Ronald Rivest? 70p  (0) 2018.04.27
[UIUCTF 2018] xoracle (250)  (0) 2018.04.18
[TyokoWesterns] My Simple Cipher[75]  (0) 2017.09.02

+ Recent posts