ENCRYPT CTF Writeup

この大会は2019/4/2 14:00(JST)~2019/4/4 14:00(JST)に開催されました。
今回もチームで参戦。結果は3536点で681チーム中4位でした。
自分で解けた問題をWriteupとして書いておきます。

sanity check (Misc 1)

ルールのページにフラグが書いてあった。

Thanks for reading rules here's your free flag: encryptCTF{L3t5_H4CK}
encryptCTF{L3t5_H4CK}

ham-me-baby (Misc 100)

$ nc 104.154.106.182 6969

                        Welcome To 

	   ____                       __    _______________  
	  / __/__  __________ _____  / /_  / ___/_  __/ __/  
	 / _// _ \/ __/ __/ // / _ \/ __/ / /__  / / / _/    
	/___/_//_/\__/_/  \_, / .__/\__/  \___/ /_/ /_/      
	              ___/___/_/_____                        
	             |_  |/ _ <  / _ \                       
	            / __// // / /\_, /                       
	           /____/\___/_//___/                        
		                                                     

you will be receiving hamming(7,4) codes. your job is to send data bits
from a 7 bit hamming code. 
 ___________________________________________________________________
|                                                                   |
|   DO YOUR RESEARCH : https://en.wikipedia.org/wiki/Hamming(7,4)   |
|  FLAG WILL BE PRINTED AFTER YOU SEND CORRECT DATA BITS 100 TIMES  |
|___________________________________________________________________|

and come back here. remember somebits could be flipped. you need to send
correct data bits.


[*] CODE: 1011101
[*] DATA: 1101
[*] CODE: 1100010
[*] DATA: 0010
[*] CODE: 1011100
[*] DATA: 1100
[*] CODE: 1001110
[*] DATA: 

Hamming(7,4)の問題。訂正せずにCODEから一部を取り出せばよいだけ。

import socket

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('104.154.106.182', 6969))

data = recvuntil(s, 'bits.\n').strip()
print data
data = recvuntil(s, '\n').strip()
print data
data = recvuntil(s, '\n').strip()
print data

for i in range(100):
    print 'Round %d' % (i+1)
    data = recvuntil(s, '\n').strip()
    print data
    if data == 'CODE VALIDATED':
        data = recvuntil(s, '\n').strip()
        print data
    code = data.split(': ')[1]
    d = code[2] + code[-3:]
    data = recvuntil(s, ': ')
    print data + d
    s.sendall(d + '\n')

data = recvuntil(s, '\n').strip()
print data
encryptCTF{hummmmm_hummmmmm}

ham-me-baby-2 (Misc 100)

ham-me-babyの問題の訂正らしい。CODEから必要に応じて訂正し、データ部分のみ返す必要がある。

import socket

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

def check_bit(code):
    d = map(int, [code[2], code[4], code[5], code[6]])
    p = map(int, [code[0], code[1], code[3]])
    if (d[0] + d[1] + d[3]) % 2 != p[0]:
        return False
    elif (d[0] + d[2] + d[3]) % 2 != p[1]:
        return False
    elif (d[1] + d[2] + d[3]) % 2 != p[2]:
        return False
    return True

def correct(code):
    if check_bit(code):
        try_code = code
    else:
        for i in range(len(code)):
            if code[i] == '0':
                try_code = code[:i] + '1' + code[i+1:]
            else:
                try_code = code[:i] + '0' + code[i+1:]
            if check_bit(try_code):
                break
    return try_code[2] + try_code[-3:]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('104.154.106.182', 6969))

data = recvuntil(s, 'bits.\n').strip()
print data
data = recvuntil(s, '\n').strip()
print data

for i in range(100):
    print 'Round %d' % (i+1)
    data = recvuntil(s, '\n').strip()
    print data
    code = data.split(': ')[1]
    correct_data = correct(code)
    data = recvuntil(s, ': ')
    print data + correct_data
    s.sendall(correct_data + '\n')
    data = recvuntil(s, '\n').strip()
    print data

data = recvuntil(s, '\n').strip()
print data
encryptCTF{1t_w4s_h4rd3r_th4n_1_th0ught}

Sweeeeeet (Web 50)

CookieのFLAGに以下がセットされている。

encryptCTF%7By0u_c4nt_U53_m3%7D
→encryptCTF{y0u_c4nt_U53_m3}

これはフラグとして通らない。
CookieのUIDに以下がセットされている。

f899139df5e1059396431415e770c6dd

md5逆変換すると、"100"になる。
以下の"0"のmd5をセットしてみる。

cfcd208495d565ef66e7dff9f98764da

CookieのFLAGが以下に変わった。

encryptCTF%7B4lwa4y5_Ch3ck_7h3_c00ki3s%7D%0A
encryptCTF{4lwa4y5_Ch3ck_7h3_c00ki3s}

It's a WrEP (Forensics 50)

無線通信のcapファイルが添付されている。

$ aircrack-ng encryptCTFWEP.cap 
Opening encryptCTFWEP.cap
Read 546320 packets.

   #  BSSID              ESSID                     Encryption

   1  58:D7:59:79:61:34  MCSP                      No data - WEP or WPA
   2  40:31:3C:E6:CA:3C  Malik’s                 WPA (1 handshake)
   3  14:CC:20:F5:32:FE  encryptCTF                WEP (88648 IVs)
   4  0C:D2:B5:72:3C:D4  home                      WPA (0 handshake)
   5  E4:6F:13:80:82:99  prime2                    No data - WEP or WPA
   6  04:95:E6:05:50:60  Letzpay1                  WPA (0 handshake)
   7  C4:B8:B4:BF:5B:C8  foresightinn              No data - WEP or WPA
   8  B4:EF:FA:51:EC:53  Le 2                      No data - WEP or WPA
   9  72:B7:AA:33:56:23  vivo 1802                 None (0.0.0.0)
  10  78:D3:8D:E4:E5:8C  Sarovar                   None (172.16.168.188)
  11  50:5D:AC:94:3D:E4  Webnyxa_airtel_12G        No data - WEP or WPA
  12  C4:B8:B4:4D:93:74  Webnyxa_airtel_first      No data - WEP or WPA
  13  C8:D7:79:A7:E0:0A                            Unknown
  14  B0:C1:9E:A3:18:BA  Airtel-Hotspot-18BA       WPA (0 handshake)
  15  C4:B8:B4:A8:92:20  sanchez                   No data - WEP or WPA
  16  74:DA:DA:D8:86:77  Orium                     WPA (0 handshake)
  17  AC:EE:9E:91:D3:43  AndroidAP                 No data - WEP or WPA
  18  AE:56:2C:96:57:C9                            Unknown
  19  84:FE:DC:DC:8C:06  password                  No data - WEP or WPA
  20  04:B1:67:C2:3D:87  Redmiamit                 No data - WEP or WPA
  21  70:5A:AC:92:B9:BC  Ritesh mobile             No data - WEP or WPA

Index number of target network ? 3

Opening encryptCTFWEP.cap
Attack will be restarted every 5000 captured ivs.
Starting PTW attack with 88648 ivs.


                                 Aircrack-ng 1.2 beta3


                 [00:00:00] Tested 837 keys (got 85909 IVs)

   KB    depth   byte(vote)
    0    0/ 17   57(107520) 84(99840) 71(97536) B5(97536) D0(96512) 
    1    0/  1   C4(116992) DD(98816) 1A(97792) 3A(96768) 59(94720) 
    2    2/  2   3E(101632) 4D(98816) 9B(97536) 2B(96256) 5E(96000) 
    3   13/  3   C5(93952) B6(93440) 63(93184) 72(93184) B8(92928) 
    4    0/  1   98(121344) F8(98048) C2(97536) C1(97280) D4(96000) 

     KEY FOUND! [ 57:34:35:5F:31:37:5F:52:33:34:4C:3F:21 ] (ASCII: W45_17_R34L?! )
	Decrypted correctly: 100%

WEPキーが見つかった。

encryptCTF{W45_17_R34L?!}

Journey to the centre of the file 1 (Forensics 75)

zipとgzで何重にも圧縮しているので、スクリプトで解凍する。

import subprocess
import os

cmd_file = 'file flag'
cmd_zip = 'unzip flag.zip'
cmd_gzip = 'gzip -d flag.gz'

i = 1
while True:
    print 'Round %d' % i
    i += 1

    if os.path.exists('flag.zip'):
        cmd = cmd_zip
        ret = subprocess.check_output( cmd.split(" ") )
        os.remove('flag.zip')
    elif os.path.exists('flag.gz'):
        cmd = cmd_gzip
        ret = subprocess.check_output( cmd.split(" ") )
        ret = subprocess.check_output( cmd_file.split(" ") )
        if 'Zip archive' in ret:
            os.rename('flag', 'flag.zip')
        else:
            ret = subprocess.check_output( 'cat flag'.split(" ") )
            print ret
            break
    else:
        break
encryptCTF{w422up_b14tch3s}

Wi Will H4CK YOU!! (Forensics 100)

無線通信のcapファイルが添付されている。

$ aircrack-ng -w dict/rockyou.txt encryptCTFWPA.cap 
Opening encryptCTFWPA.cap
Read 4790 packets.

   #  BSSID              ESSID                     Encryption

   1  14:CC:20:F5:32:FE  encryptCTF                WPA (1 handshake)
   2  0C:D2:B5:72:3C:D4  home                      No data - WEP or WPA
   3  40:31:3C:E6:CA:3C  Malik’s                 WPA (0 handshake)
   4  00:00:00:00:00:00                            Unknown

Index number of target network ? q
Index number of target network ? 1

Opening encryptCTFWPA.cap
Reading packets, please wait...

                                 Aircrack-ng 1.2 beta3


                   [01:41:30] 7049164 keys tested (1210.81 k/s)


                           KEY FOUND! [ ThanckYou ]


      Master Key     : 48 89 DD 32 53 9E A7 49 1E 63 3D F7 06 CD CD 4F 
                       0E 1E 22 56 BD DA 8B 10 ED 80 6D 8E 20 3C 7B D3 

      Transient Key  : F0 F9 59 E0 EA 24 01 AC B4 B9 CE 01 F3 04 60 A9 
                       C9 84 6F 2A 59 0A 24 9E 3E 5E 87 36 64 EC D8 8D 
                       C3 2C AA FA E7 02 D0 D1 D2 64 96 2E A7 A8 D5 29 
                       4B FF A3 EB AB 16 D9 11 F7 2F F3 6B 2D F8 61 31 

      EAPOL HMAC     : EC F7 55 70 56 9E 7B AE 18 BB 39 6E 88 C6 F3 F2

WPAキーが見つかった。

encryptCTF{ThanckYou}

yhpargonagets (Steganography 25)

Pythonライブラリを使う。

from steganography.steganography import Steganography

flag = Steganography.decode('encode.jpg')
print flag
encryptCTF{pip_in5t411_5teg4n0graphy}

Stressed out? (Steganography 100)

wavファイルのプロパティを見ると、タイトルは以下のようになっている。

1_4M_Str3ss3d_0ut

wavを対応しているsteghideを試してみる。

$ steghide extract -sf dontstressoutkiddo.wav 
Enter passphrase: ★先ほどのタイトルを指定
wrote extracted data to "flag.jpg".

flag.jpgを取り出せて、そこにフラグが書いてあった。
f:id:satou-y:20190409211547j:plain

encryptCTF{tyl3r_j0s3ph_is_4_g0d}

Hard Looks (Cryptography 75)

"-"を1、"_"を0にして考える。暗号文の長さは8の倍数でないので、先頭に不足分0をつけて、デコードする。

enc = '--_--___--_-_-__--_--__--__-_-__--_--___--__--__--_---__--__-___--_---__---__-__--_---__--______--_---__--_-____--_-____--__--__--_-_-__--_-____--_-____--_--___--_---_--___-___--_-_-__--_---__--__--__--_-____--__--__--_-_-__--_-_-_--__--___--__--__--___-__--__--__--_---__--_-_-_--__--___--_-____---_____--__--__--_-____--_-_-__--__-___--_-____--_-____--_-_-_--__--___--__--__--__--__--_-___--__-_-__--__--__--______--_-_-__--_-_-__--_-____--_---__--_-____---_____--__--_--__--___--__-___--___-__--_---_--__-__'

enc = enc.replace('-', '1')
enc = enc.replace('_', '0')

while True:
    if len(enc) % 8 == 0:
        break
    enc = '0' + enc

msg = ''
for i in range(0, len(enc), 8):
    msg += chr(int(enc[i:i+8], 2))

flag = msg.decode('hex')
print flag
encryptCTF{W45_17_H4RD_3N0UGH?!}

RSA_Baby (Cryptography 100)

qとnが分かっているので、pは算出できる。あとはそのまま復号する。

from Crypto.Util.number import *

e = 65537
q = 9896984395151566492448748862139262345387297785144637332499966426571398040295087125558780121504834847289828037371643927199404615218623314326851473129699891

with open('flag.enc', 'r') as f:
    data = f.read()

c = int(data.split('\n')[1], 16)
n = int(data.split('\n')[2].split(': ')[1])
p = n / q

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)

flag = long_to_bytes(m)
print flag
encryptCTF{74K1NG_B4BY_S73PS}

Julius,Q2Flc2FyCg== (Cryptography 150)

Base64デコードして、シフトしたら復号できた。

enc = 'fYZ7ipGIjFtsXpNLbHdPbXdaam1PS1c5lQ'

while True:
    if len(enc) % 4 == 0:
        break
    enc += '='

dec = enc.decode('base64')

flag = ''
for i in range(len(dec)):
    code = ord(dec[i]) - 24
    flag += chr(code)

print flag
encryptCTF{3T_7U_BRU73?!}

AEeeeeS (Cryptography 200)

AESキーは2進数になっているが、バイナリに変えると16バイトになる。あとはそのままAES復号を行う。

from Crypto.Cipher import AES

with open('AEeeeeS.key', 'r') as f:
    data = f.read().strip()

while True:
    if len(data) % 8 == 0:
        break
    data = '0' + data

key = ''
for i in range(0, len(data), 8):
    key += chr(int(data[i:i+8], 2))

enc = 'c68145ccbc1bd6228da45a574ad9e29a77ca32376bc1f2a1e4cd66c640450d77'
cipher = AES.new(key, AES.MODE_ECB)
flag = cipher.decrypt(enc.decode('hex'))
print flag
encryptCTF{3Y3S_4R3_0N_A3S_3CB!}

(TopNOTCH)SA (Cryptography 300)

nをfactordbで素因数分解する。

57891041571118599917733172578294383243762455810797917992757930072844611988433
= 194038568404418855662295887732506969011 * 298348117320990514224871985940356407403

あとはそのまま復号する。

from Crypto.PublicKey import RSA
from Crypto.Util.number import *

with open('pubkey.pem', 'r') as f:
    pub_data = f.read()

pubkey = RSA.importKey(pub_data)
n = pubkey.n
e = pubkey.e

p = 194038568404418855662295887732506969011
q = 298348117320990514224871985940356407403
assert n == p * q

with open('flag.enc', 'r') as f:
    data = f.read()

c = int(data.split('\n')[1], 16)

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(m)
print flag
encryptCTF{1%_0F_1%}