HackIT CTF 2017 Writeup

この大会は2017/8/25 23:00(JST)~2017/8/27 23:00(JST)に開催されました。
今回もチームで参戦。結果は220点で1406チーム中123位でした。
自分で解けた問題をWriteupとして書いておきます。

USB ducker (Foren 100)

USBの通信パケットをキャプチャしたpcapファイルが与えられる。DESCRIPTOR Response DECICEを探してキーボードの種類を調べると、No.267のパケットから Aluminum Keyboard (ISO)とわかる。
そこでhttp://www.usb.org/developers/hidpage/Hut1_12v2.pdfを参考に押したキーを割り当てていく。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from scapy.all import *

keymap = { 0x04: ('a', 'A'), 0x05: ('b', 'B'), 0x06: ('c', 'C'),
           0x07: ('d', 'D'), 0x08: ('e', 'E'), 0x09: ('f', 'F'),
           0x0a: ('g', 'G'), 0x0b: ('h', 'H'), 0x0c: ('i', 'I'),
           0x0d: ('j', 'J'), 0x0e: ('k', 'K'), 0x0f: ('l', 'L'),
           0x10: ('m', 'M'), 0x11: ('n', 'N'), 0x12: ('o', 'O'),
           0x13: ('p', 'P'), 0x14: ('q', 'Q'), 0x15: ('r', 'R'),
           0x16: ('s', 'S'), 0x17: ('t', 'T'), 0x18: ('u', 'U'),
           0x19: ('v', 'V'), 0x1a: ('w', 'W'), 0x1b: ('x', 'X'),
           0x1c: ('y', 'Y'), 0x1d: ('z', 'Z'), 0x1e: ('1', '!'),
           0x1f: ('2', '@'), 0x20: ('3', '#'), 0x21: ('4', '$'),
           0x22: ('5', '%'), 0x23: ('6', '^'), 0x24: ('7', '&'),
           0x25: ('8', '*'), 0x26: ('9', '('), 0x27: ('0', ')'),
           0x28: ('[Enter]', '[Enter]'), 0x29: ('\x1b', '\x1b'),
           0x2a: ('\x08', '\x08'), 0x2b: ('\x09', '\x09'),
           0x2c: ('\x20', '\x20'), 0x2d: ('-', '_'),
           0x2e: ('=', '+'), 0x2f: ('[', '{'), 0x30: (']', '}'),
           0x31: ('\\', '|'), 0x32: ('#', '~'), 0x33: (';', ':'),
           0x34: ('\'', '\"'), 0x35: ('`', '~'), 0x36: (',', '<'),
           0x37: ('.', '>'), 0x38: ('/', '?'), 
           0x51: ('[Down]', '[Down]'), 0x52: ('[Up]', '[Up]') }

def read_usb_data_from_pcap():
    packets = rdpcap('task.pcap')
    usb_data = []
    for p in packets:
        buf = p['Raw'].load
        if buf[19] == '\x03' and buf[22] == '\x01':
            usb_data.append(buf[27:])
    return usb_data

def analyze_usb_data(usb_data):
    flag = ''
    for d in usb_data:
        if d[2] == '\x00' or not('\x00' in d[3:8]):
            continue
        if d[0] == '\x02' or d[0] == '\x20':
            c = keymap[ord(d[2])][1]
            flag += c
        else:
            c = keymap[ord(d[2])][0]
            flag += c
    print flag

def main():
    data = read_usb_data_from_pcap()
    analyze_usb_data(data)

if __name__ == '__main__':
    main()

これを実行すると、以下のようなキー入力があったことがわかる。

w[Enter]k[Enter]f[Enter]b[Enter]3'[Up][[Up]l[Up]#[Up]{w$[Down]>b[Down]ag[Down][e[Down]ci.[[Up][f[Up]{k[Up]n$[Up]ju}[Down]:[Down]3[Down]u[Down]%=[Up]~[Up]y[Up]6[Up],'[Down]p[Down]b[Down]7[Down]%&[Up]d[Up]0[Up]j[Up]pt[Down]i[Down]a[Down][[Down]k([Up]=[Up]r[Up]m[Up]]=[Down]0[Down]d[Down]>[Down]lc[Up]*[Up]_[Up]{[Up]j%[Down]u[Down]s[Down]([Down]*2[Up]0[Up]n[Up]'[Up];9[Down]h[Down]4[Down]][Down]y4[Up]'[Up]k[Up];[Up]+p[Down]f[Down]e[Down]$[Down]!}[Up]1[Up]_[Up]k[Up]s&[Down]s[Down]2[Down]c[Down]%q[Up]$[Up].[Up]![Up]#,[Down]s[Down]0[Down]c[Down]z3[Up]e[Up]}[Up]-[Up]i

上記の結果通りキーを押していくと、3段目にフラグが出来上がる。

w{w$ju},'pt]=j%;9+ps&#,i
k#>bn$:6pjim0{u'h;fks!s-
flag{k3yb0ard_sn4ke_2.0}
b[[e[fu~7d[=>*(0]'$1c$ce
3'ci.[%=%&k(lc*2y4!}%qz3
flag{k3yb0ard_sn4ke_2.0}