Hack.lu CTF 2016 供養(Writeup)

Hack.lu CTF 2016に参加。594ptで66位。

simplepdf (Programming 150 (- 52))

注釈に添付ファイルがついており、これを抽出すると同じようなPDFがまた出てくる。 抽出を10003回繰り返すとflagが得られる。

import zlib
import re

with open('simplepdf_f8004a3ad0acde31c40267b9856e63fc.pdf', 'rb') as f:
    data = f.read()

n = 0
while True:
    n += 1
    print n

    m = re.search(r'/Length (\d+)\n', data)
    if not m:
        break
    num = int(m.group(1))
    data = data[m.end():]
    idx = data.index('\nstream\n')
    data = data[idx+8:]
    data = data[:num]

    data = zlib.decompress(data)

    print len(data)
    print "%r" % data[:0x10]

with open('s.pdf', 'wb') as f:
    f.write(data)
flag{pdf_packing_is_fun}

cryptolocker (Crypto 200 (- 52))

8文字のkeyを2文字ずつ4個に分け、それぞれSHA-256にかけたものをkeyとして4回暗号化している。 2文字ずつブルートフォースで復号し、パディングが長いものを正しいkeyとして特定していく。 得られたkeyで復号するとodtファイルが得られる。

#!/usr/bin/env python3
import sys
import hashlib
from AESCipher import *

def checkpad(s):
    c = s[-1]
    pad = s[-ord(c):]
    if all(x == c for x in pad):
        return pad
    else:
        return ''

if __name__ == "__main__":
    filename = "flag.encrypted"
    ciphertext = open(filename, "rb").read()

    seed = '4D'
    key = hashlib.sha256(seed).digest()
    cipher = AESCipher(key)
    ciphertext = AESCipher._unpad(cipher.decrypt(ciphertext))

    seed = 'WH'
    key = hashlib.sha256(seed).digest()
    cipher = AESCipher(key)
    ciphertext = AESCipher._unpad(cipher.decrypt(ciphertext))

    seed = '52'
    key = hashlib.sha256(seed).digest()
    cipher = AESCipher(key)
    ciphertext = AESCipher._unpad(cipher.decrypt(ciphertext))

    seed = 'Sg'
    key = hashlib.sha256(seed).digest()
    cipher = AESCipher(key)
    ciphertext = AESCipher._unpad(cipher.decrypt(ciphertext))

    with open('plaintext.bin', 'wb') as f:
        f.write(ciphertext)
    sys.exit(0)

    for i in xrange(0x20, 0x7f):
        for j in xrange(0x20, 0x7f):
            seed = chr(i) + chr(j)
            key = hashlib.sha256(seed).digest()
            cipher = AESCipher(key)
            plaintext = cipher.decrypt(ciphertext)
            pad = checkpad(plaintext)
            if pad:
                print "%r: %r" % (pad, seed)
$ file plaintext.bin
plaintext.bin: OpenDocument Text
flag{v3ry_b4d_crypt0_l0ck3r}

cornelius1 (Crypto 200 (- 29))

入力値がflagと合わせてdeflateで圧縮されて返ってくる。 同じ部分文字列が複数あると圧縮後のサイズが小さくなることをもとに、一文字ずつ特定する(CRIME / compression oracle attack)。

import urllib2
import string

user = "flag:"
while True:
    max_length = None
    for c in '.0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!?_':
        print c
        user2 = user + c
        url = "https://cthulhu.fluxfingers.net:1505/?user=" + (user2 * 100)
        f = urllib2.urlopen(url)
        cookie = f.headers['Set-Cookie']
        secret = cookie[5:].decode('base64')
        length = len(secret)
        if max_length is None:
            max_length = length
        elif length < max_length:
            user += c
            print user
            break
    else:
        break
flag:Mu7aichede

redacted (Crypto 200 (- 23))

一部が伏せられたPEM鍵が与えられる。 鍵の長さからRSA 2048-bitであることがわかるので、適当に生成した鍵で伏せられた部分を埋めてdiffを取るとp、q、eが伏せられずに入っている。 これをもとに、rsatoolで改めて鍵を生成する。

$ diff -u reference.txt problem.txt
--- reference.txt       2016-10-19 22:18:03.911305046 +0900
+++ problem.txt 2016-10-19 22:17:52.591296990 +0900
@@ -1,90 +1,90 @@
 Private-Key: (2048 bit)
 modulus:
     00:a5:3b:05:f6:3a:6c:dd:5e:34:84:9e:18:ff:5c:
-    88:1c:21:47:c2:10:57:bd:d3:a9:78:ce:13:73:63:
-    6c:bc:35:45:c3:7b:55:45:14:a1:76:b3:19:9b:87:
-    5d:34:98:df:78:b2:ad:47:82:0c:14:fc:97:f0:6a:
-    56:6b:ff:ee:dd:19:c0:21:a6:ba:14:1b:24:85:5b:
-    70:f5:5c:ab:b0:fe:15:7d:5c:3a:c9:97:42:82:0d:
-    38:20:81:16:59:5b:77:35:23:e3:26:86:eb:36:55:
-    67:eb:3a:0c:30:d9:03:04:27:6d:07:d1:36:3f:de:
-    a6:52:64:cb:d2:cd:b0:52:1e:7d:55:f3:9d:28:3c:
-    2d:41:f4:f0:29:7f:ab:b3:67:d1:93:ea:dc:f9:e4:
-    64:12:cf:47:0a:a5:5c:e9:7e:a8:7b:f6:3a:9a:05:
-    2c:a1:b1:45:16:9f:6b:fc:6e:e2:fb:c7:87:dd:ae:
-    ed:58:8e:e7:e0:16:fe:1a:58:12:99:2b:c2:ef:3d:
-    c2:52:4a:30:85:db:e0:d1:4a:d0:16:db:bf:ad:08:
-    38:3d:52:2c:f2:a7:13:10:5e:f8:ce:ec:0c:e1:68:
-    98:11:28:20:b3:4c:8c:5e:0e:75:dc:7f:53:11:20:
-    1a:81:68:75:e6:12:ba:dd:c8:4f:7e:db:20:4b:93:
-    a4:25
+    88:ff:4a:9c:d7:8e:94:5d:76:e9:78:ce:13:73:63:
+    6c:bc:35:45:c1:67:bd:01:1d:64:3b:33:19:9b:87:
+    5d:34:98:df:78:b2:ad:47:82:0c:14:fc:97:f0:c4:
+    92:0b:ff:ee:dd:19:c0:21:a6:ba:14:1b:24:87:c7:
+    02:a2:f2:1c:00:e6:71:14:46:85:72:36:b5:c3:11:
+    06:e4:c1:d3:ee:5b:d7:c7:85:34:2a:ad:b6:a7:d1:
+    76:df:7e:dc:b7:ce:1d:78:df:e9:92:85:7e:1a:34:
+    73:07:56:18:6c:a4:c2:00:de:c2:a9:7f:33:b3:6c:
+    78:9f:d7:bb:58:66:fb:d6:8e:83:d8:23:ea:e6:4c:
+    9e:2d:74:0f:2f:09:d0:38:3b:39:d5:1a:ae:b1:90:
+    85:8e:8a:3b:6a:d9:cb:ab:8d:93:5a:a1:bd:01:d1:
+    cb:ba:23:8a:f4:df:84:55:d7:d7:89:c7:1e:e6:09:
+    1f:71:1e:76:6f:63:3a:04:20:f5:30:ad:b7:04:95:
+    06:60:70:a0:70:73:fc:b0:1d:21:cc:2f:d5:64:8d:
+    9f:54:75:d7:69:69:7d:3e:32:58:68:31:5a:b8:e5:
+    0e:73:50:0f:4c:2d:0b:85:48:ce:38:e0:13:38:29:
+    4e:81
 publicExponent: 65537 (0x10001)
 privateExponent:
-    39:cd:97:3d:57:9d:24:28:43:b9:2d:51:d3:6b:fc:
-    95:d2:b2:b6:da:5e:c7:a2:d7:83:d2:9c:0d:5e:f7:
-    f8:33:ae:cf:3f:43:4a:62:78:45:fd:4b:f5:13:fa:
-    f0:5e:96:b7:33:d2:d8:d4:4f:03:bc:86:2e:ee:14:
-    83:bd:ca:43:81:31:ac:d4:15:fe:d8:ac:03:17:45:
-    42:21:04:53:6b:df:fa:b6:1c:3e:cf:f2:cd:6a:70:
-    7b:36:8d:a9:ff:0c:8a:03:9f:00:a8:6c:7a:da:8f:
-    fb:43:98:66:32:55:12:cb:f4:21:aa:f8:0e:8a:06:
-    a7:86:69:a3:ba:9f:77:6a:71:49:a2:47:2f:f2:79:
-    2b:c0:d7:84:f9:3f:f8:77:39:c5:03:f6:74:86:53:
-    d3:8e:46:9a:11:21:2f:8c:65:aa:4f:f3:51:8c:d2:
-    ed:82:14:a0:e0:1a:fa:1f:25:2d:84:f9:02:74:b9:
-    83:c4:3c:75:05:59:46:ae:05:9e:fa:42:4b:66:aa:
-    8c:92:ef:ee:79:c6:67:88:51:33:c7:39:4b:cb:62:
-    cc:f6:b5:02:97:ce:93:66:1d:f6:c3:34:a3:7d:82:
-    e6:32:3e:0b:70:fb:b0:25:e4:56:9a:05:14:63:66:
-    d7:89:bb:8d:ec:4e:cc:4a:f1:72:f4:a1:24:2c:b6:
-    21
+    30:5b:82:3a:4e:4f:4d:ed:fd:cd:3b:00:55:d9:ff:
+    94:94:66:bb:68:be:58:70:1a:78:1f:91:d7:b2:90:
+    46:e9:47:b2:de:99:df:4b:62:a7:7d:96:05:8f:81:
+    1a:8f:37:31:47:6a:1f:35:48:52:80:39:38:d5:7b:
+    1b:75:92:9b:15:56:d2:c5:eb:0d:e6:32:6e:a9:3c:
+    da:8e:26:7d:91:6e:9f:9c:fd:85:5a:01:81:f4:ff:
+    d7:43:b2:4a:85:bf:37:8b:fb:bc:df:ab:13:ce:a1:
+    2a:5b:7e:f4:9b:f0:4b:05:0b:89:a3:1b:97:00:63:
+    69:c4:5a:e9:02:92:91:e3:0f:78:9b:3f:d3:da:b4:
+    cd:3b:3b:88:b7:48:90:b3:57:ee:c0:f0:07:53:5b:
+    25:58:c5:76:04:ad:e3:65:22:c3:9c:fe:22:ba:ba:
+    43:94:07:47:80:59:d6:30:74:7d:75:2d:f5:21:f8:
+    8f:44:a0:fe:d2:88:d9:8e:25:48:40:a2:59:b4:6d:
+    45:1b:b8:e1:60:f2:59:46:85:ec:68:ff:6c:ef:2d:
+    bb:56:31:34:f4:4d:eb:0e:6d:46:7e:8e:bf:95:51:
+    6d:51:ef:a7:b1:0b:bb:0f:20:a4:a6:cd:9c:52:59:
+    9d:67:06:3d:c8:c0:7a:0a:48:58:9c:f5:ec:5a:32:
+    81
 prime1:
-    00:ce:76:b5:36:d8:98:64:d4:e1:b3:2a:c0:d6:a6:
-    e1:e4:96:65:42:bb:a6:6e:6c:65:cb:39:99:dd:86:
-    f4:ab:4f:6d:1f:76:0b:ff:53:70:18:8b:f4:3a:c8:
-    27:d2:87:5c:8a:f4:3f:35:e7:a9:08:e2:d6:f3:fe:
-    84:50:ac:e7:92:4e:c0:7e:e6:44:ad:2a:77:08:4e:
-    4f:79:28:81:0c:0a:84:5c:59:92:50:f5:5d:b0:bc:
-    d0:50:a3:84:ce:ba:f4:f2:c0:67:a5:17:97:9a:e4:
-    56:41:05:00:41:32:7f:5f:f4:2a:06:b8:39:37:d7:
-    f4:3d:47:37:81:4b:65:33:89
+    00:e4:dd:ba:96:c1:cb:c4:f4:12:04:ee:6f:c1:6e:
+    14:83:04:38:ae:ee:4b:bd:21:af:5c:e8:8d:fd:25:
+    a1:2f:2a:9a:26:99:4e:ef:a0:e6:be:d0:4a:c2:e2:
+    9b:f6:39:b4:c8:f9:75:ad:88:6f:31:15:ec:5e:38:
+    4c:c6:8c:1f:d7:d7:db:63:cc:63:f6:34:61:52:80:
+    9c:71:d2:26:22:3d:7d:69:90:ca:e6:4d:fc:16:f1:
+    74:fa:1a:6e:e4:6b:25:af:af:fc:f3:93:6a:61:d3:
+    f2:c6:9d:6c:ee:99:4f:ef:f8:f2:f0:a7:06:38:42:
+    01:10:d3:03:d0:75:ab:16:d3
 prime2:
-    00:cc:df:b7:b2:50:8f:25:a5:bd:e7:d5:c4:ed:ed:
-    fe:53:22:0f:42:e5:f1:d9:5b:66:08:19:ce:03:f6:
-    00:0d:f5:a3:23:46:5c:d6:96:79:b1:b1:f9:be:eb:
-    40:5c:85:3b:67:7c:3f:8e:f8:6b:c2:30:89:84:cf:
-    67:94:44:02:57:7c:ea:4f:52:75:19:66:40:1c:82:
-    25:c0:22:87:15:d0:ef:66:e9:7b:a8:91:33:fa:2b:
-    37:e7:ba:1f:a4:88:93:65:ac:58:0e:90:da:6f:d3:
-    b8:a0:12:c5:a1:69:df:41:4a:7f:c0:ed:a5:bd:1f:
-    8e:b6:2d:9c:7f:06:19:d8:bd
+    00:de:e5:59:98:94:7b:fd:b7:5c:7e:34:9b:c7:6a:
+    16:73:a8:c4:1b:62:92:9c:24:2c:0e:3d:0c:80:87:
+    38:97:25:18:f8:63:93:04:b3:34:0d:6a:88:51:0c:
+    c5:24:e3:79:63:a4:2d:06:38:f6:05:57:2a:a7:b9:
+    3e:da:07:dc:29:45:71:18:fa:9a:99:00:62:f0:5d:
+    00:25:d5:46:7d:3e:df:8d:b4:48:cf:12:ed:4a:b6:
+    79:67:be:70:c2:a5:61:7b:30:85:d0:e1:51:35:7d:
+    63:b1:ec:a4:b5:37:46:fc:be:58:6c:dc:8a:44:05:
+    cf:af:71:9f:3f:01:13:18:db
 exponent1:
-    73:c4:c4:5f:f8:9b:9b:0e:73:70:0f:6d:09:ef:91:
-    82:a7:82:28:25:28:71:8a:7e:99:b1:b6:c1:2c:c7:
-    4c:b7:c0:ac:7f:78:c2:b6:7a:88:89:11:6d:54:86:
-    5f:da:5e:dd:db:8f:06:1e:db:fd:8b:94:94:44:06:
-    d5:65:de:83:7f:7d:18:aa:ed:9f:5b:cc:5a:ef:ee:
-    48:35:9a:06:b2:6e:fd:89:8c:2d:b1:27:d3:ce:4b:
-    d0:ab:9f:f0:7b:8c:96:01:a5:1c:41:5a:55:13:eb:
-    f9:91:60:4f:2e:8d:95:b4:47:4c:75:48:40:33:eb:
-    53:e0:f7:12:9c:c0:26:61
+    06:1a:b3:e3:59:7f:e9:dc:e8:ae:20:fd:f2:16:d1:
+    8d:3d:0b:95:fe:dd:1e:4a:4b:b7:1a:ac:ce:d7:b6:
+    18:df:f6:04:99:8a:35:72:01:35:8d:b0:b0:ca:02:
+    86:ea:bb:1b:b1:2b:a6:59:41:3d:f9:eb:b8:07:a0:
+    64:9b:50:2e:1d:9f:c8:65:a7:34:e5:e8:c2:9e:93:
+    8d:a5:a1:46:c0:85:1b:cf:b4:d9:b7:b2:c5:99:e3:
+    18:d8:a3:a4:8c:07:11:4c:8c:5e:a2:cb:ef:98:0b:
+    9d:a8:8d:43:3f:eb:95:e6:f9:f3:d9:40:9d:37:85:
+    77:c1:69:14:a2:4e:d1:e9
 exponent2:
     7d:2f:de:e1:b8:d4:1f:9f:0d:51:d2:90:09:0b:3a:
-    32:b6:47:39:0b:a5:22:b9:f4:b8:d2:7b:ce:73:cd:
-    48:ba:66:3b:31:cd:9c:da:49:f6:48:d8:60:cf:03:
-    7f:05:72:6d:23:c0:fa:ad:d5:ba:cd:49:da:bb:99:
-    81:41:a5:64:ac:51:c8:b2:8c:17:3f:21:c1:c9:cd:
-    23:80:75:a6:e1:0a:c8:89:b7:24:23:c5:ed:01:e7:
-    a1:53:5b:ee:7f:fe:01:4c:b4:6a:02:1d:57:e3:b9:
-    97:26:a1:58:a6:86:e3:30:90:ab:e5:0b:37:6b:47:
-    1b:0e:f7:e7:ae:64:b0:c9
+    32:b6:47:39:0b:a5:22:b9:f4:b8:d3:e8:2e:cf:96:
+    59:a2:76:fe:5e:db:49:43:53:fd:4a:ed:cf:16:d8:
+    0c:1c:2f:fd:23:c0:fa:ad:d5:ba:cd:49:da:bb:99:
+    81:41:a5:64:ac:51:c8:b2:8c:17:3f:21:c1:c9:54:
+    ea:bf:a8:0a:11:b6:c8:89:b7:24:23:c5:ed:01:e7:
+    a1:53:5b:ee:7f:fe:01:4c:b4:6a:0e:0a:6c:39:81:
+    10:8e:69:5d:45:59:88:0b:ff:22:c8:6b:1a:6f:7b:
+    2b:c3:42:a2:4e:0f:b4:c9
 coefficient:
     39:27:09:7d:f2:1d:84:33:49:f2:10:3b:38:e4:51:
     14:7a:e0:79:f1:6e:72:75:8f:a4:04:8f:54:24:05:
-    90:72:ca:35:1e:45:4a:c5:b6:bd:f8:0c:89:50:f3:
-    3b:ae:5d:8f:3b:be:43:93:87:2c:89:49:ad:8d:25:
+    90:72:ca:35:1e:78:85:44:52:a2:7d:35:8a:79:16:
+    3d:47:ae:8f:3b:be:43:93:87:2c:89:49:ad:8d:25:
     02:36:17:c6:1a:7c:49:00:5d:9b:fa:59:0e:6c:dd:
-    1d:fa:37:49:de:ff:fe:2d:06:66:99:60:64:7b:dd:
-    36:cc:47:a2:b3:aa:2d:9c:9e:3b:64:c9:d6:af:0e:
-    0c:7b:e5:ca:dc:72:65:2c:59:80:3a:c6:94:34:55:
-    49:3a:42:e9:55:d4:d7:0e
+    1d:fa:37:49:de:ff:fe:2d:06:67:7b:e2:12:bf:27:
+    e8:3f:c2:19:3d:ba:0d:56:4d:87:46:37:fa:89:75:
+    20:a6:a9:df:3e:84:3f:ab:3c:05:12:56:10:27:23:
+    ef:1d:fe:d1:79:83:ad:0d
p = """
    00:e4:dd:ba:96:c1:cb:c4:f4:12:04:ee:6f:c1:6e:
    14:83:04:38:ae:ee:4b:bd:21:af:5c:e8:8d:fd:25:
    a1:2f:2a:9a:26:99:4e:ef:a0:e6:be:d0:4a:c2:e2:
    9b:f6:39:b4:c8:f9:75:ad:88:6f:31:15:ec:5e:38:
    4c:c6:8c:1f:d7:d7:db:63:cc:63:f6:34:61:52:80:
    9c:71:d2:26:22:3d:7d:69:90:ca:e6:4d:fc:16:f1:
    74:fa:1a:6e:e4:6b:25:af:af:fc:f3:93:6a:61:d3:
    f2:c6:9d:6c:ee:99:4f:ef:f8:f2:f0:a7:06:38:42:
    01:10:d3:03:d0:75:ab:16:d3
"""
q = """
    00:de:e5:59:98:94:7b:fd:b7:5c:7e:34:9b:c7:6a:
    16:73:a8:c4:1b:62:92:9c:24:2c:0e:3d:0c:80:87:
    38:97:25:18:f8:63:93:04:b3:34:0d:6a:88:51:0c:
    c5:24:e3:79:63:a4:2d:06:38:f6:05:57:2a:a7:b9:
    3e:da:07:dc:29:45:71:18:fa:9a:99:00:62:f0:5d:
    00:25:d5:46:7d:3e:df:8d:b4:48:cf:12:ed:4a:b6:
    79:67:be:70:c2:a5:61:7b:30:85:d0:e1:51:35:7d:
    63:b1:ec:a4:b5:37:46:fc:be:58:6c:dc:8a:44:05:
    cf:af:71:9f:3f:01:13:18:db
"""

p = p.replace(':', ' ').replace('\n', ' ').replace(' ', '')
q = q.replace(':', ' ').replace('\n', ' ').replace(' ', '')
p = int(p, 16)
q = int(q, 16)
e = 65537
print p
print q
print e
$ python test.py
160715260849342318931136112813341037345926969012288227225240875622403009493539093929333081548188459992247771680452063593583756278915740193557402138743266217376005578973188641800583345510266770139969709567420846366801788060791738229180205729066714584288249507088921482835100030743352147986722422517067206563539
156522822773738162417254450203271175855220146400024771706084276654684994055624152101542626647589634389361232150411812572776336649201321449632016603858688896275125914484326556417817195311471437215701390750315213065194536381852437122083849274951300180499399546807140772435452395099516509211865918104434503784667
65537

$ python rsatool.py -p 160715260849342318931136112813341037345926969012288227225240875622403009493539093929333081548188459992247771680452063593583756278915740193557402138743266217376005578973188641800583345510266770139969709567420846366801788060791738229180205729066714584288249507088921482835100030743352147986722422517067206563539 -q 156522822773738162417254450203271175855220146400024771706084276654684994055624152101542626647589634389361232150411812572776336649201321449632016603858688896275125914484326556417817195311471437215701390750315213065194536381852437122083849274951300180499399546807140772435452395099516509211865918104434503784667 -o generated.pem

$ ssh -i generated.pem -p 1504 berlin@cthulhu.fluxfingers.net
Welcome to Ubuntu 14.04.5 LTS (GNU/Linux 3.13.0-65-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.


The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

Last login: Thu Oct 20 15:39:03 2016 from 78-23-31-228.access.telenet.be
Congratz! The flag is:
flag{thought_ssh_privkeys_are_secure?}
Connection to cthulhu.fluxfingers.net closed.

所感

他に解きたかった問題。

  • CthCoin (Crypto / Web 150 (+ 100))
  • maze (Programming / Misc 200 (+ 7))
  • dataonly (Exploiting 200 (+ 7))