menu Ga1@xy's Wor1d
记一道比较复杂的USB流量分析题
674 浏览 | 2020-03-26 | 阅读时间: 约 3 分钟 | 分类: wp,MISC | 标签: Misc,刷题wp
请注意,本文编写于 384 天前,最后修改于 305 天前,其中某些信息可能已经过时。

在各位师傅的共同努力下终于搞懂了这道题,感谢各位师傅的帮助!!

[XMAN2018排位赛] AutoKey

题目附件链接:https://pan.baidu.com/s/1xVu0t_jrfo4nVpy17bopGw
提取码:zrxf

题目考点

  • USB流量提取
  • 键盘流量分析
  • 未知密钥爆破autokey

题目详解

下载附件打开,可以很清楚的辨认出是USB流量包:

所以我们需要将其中的数据提取出来,要用到 tshark 命令:

tshark -r attachment.pcapng -T fields -e usb.capdata > usbdata.txt

提取出来后可以看到得到的数据有空行,可以在提取时用 | sed '/^\s*$/d' 命令删去空行:

tshark -r attachment.pcapng -T fields -e usb.capdata | sed '/^\s*$/d' > usbdata.txt

这样就得到了没有空行的数据:

通过观察得到的数据,可以看到除了第一行以外都是 8字节 长度的数据,于是可以判断其为键盘流量数据,删去第一行不符合长度的数据,然后将剩余完整的数据保存,跑解键盘流量的脚本
我先跑了我之前用过的解键盘流量的脚本,因为我得到的数据中没有冒号,所以应该提取对应 4~6位 的数据:

import sys
import os

usb_codes = {
0x04:"aA", 0x05:"bB", 0x06:"cC", 0x07:"dD", 0x08:"eE", 0x09:"fF",
0x0A:"gG", 0x0B:"hH", 0x0C:"iI", 0x0D:"jJ", 0x0E:"kK", 0x0F:"lL",
0x10:"mM", 0x11:"nN", 0x12:"oO", 0x13:"pP", 0x14:"qQ", 0x15:"rR",
0x16:"sS", 0x17:"tT", 0x18:"uU", 0x19:"vV", 0x1A:"wW", 0x1B:"xX",
0x1C:"yY", 0x1D:"zZ", 0x1E:"1!", 0x1F:"2@", 0x20:"3#", 0x21:"4$",
0x22:"5%", 0x23:"6^", 0x24:"7&", 0x25:"8*", 0x26:"9(", 0x27:"0)",
0x2C:"  ", 0x2D:"-_", 0x2E:"=+", 0x2F:"[{", 0x30:"]}",  0x32:"#~",
0x33:";:", 0x34:"'\"",  0x36:",<",  0x37:".>", 0x4f:">", 0x50:"<"
}

def code2chr(filepath):
    lines = []
    pos = 0
    for x in open(filepath,"r").readlines():
        code = int(x[4:6],16) 
        if code == 0:
            continue        # newline or down arrow - move down
        if code == 0x51 or code == 0x28:
            pos += 1
            continue        # up arrow - move up
        if code == 0x52:
            pos -= 1
            continue        # select the character based on the Shift key
        while len(lines) <= pos:
            lines.append("")
        if code in range(4,81):
            if int(x[0:2],16) == 2:
                lines[pos] += usb_codes[code][1]
            else:
                lines[pos] += usb_codes[code][0]
    for x in lines:
        print(x)

if __name__ == "__main__":
    filepath = "usbdata.txt"
    code2chr(filepath)

跑这个脚本结果却得到了报错信息:


到这里我就卡住了,上网搜索这个错误信息的相关原因,也没得到什么比较有用的信息(也可能是因为我太菜了)

于是我便百度搜索了这道题的wp,在wp中发现这个键盘流量中,有一些 不可解的字符 ,我怀疑我的这个脚本可能是因为不包含这种情况,所以在解流量的时候没有与之对应的解,才会报错……

我多次尝试了一些该题wp的解流量脚本,屡屡失败,于是我便向群里的各位师傅求助,师傅们都tql!!!

下面给出夏风师傅提供的两个脚本(python2环境下):

normalKeys = {
    "04":"a", "05":"b", "06":"c", "07":"d", "08":"e",
    "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j",
     "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o",
      "13":"p", "14":"q", "15":"r", "16":"s", "17":"t",
       "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y",
        "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4",
         "22":"5", "23":"6","24":"7","25":"8","26":"9",
         "27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t",
         "2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\",
         "32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".",
         "38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>",
         "3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>",
         "44":"<F11>","45":"<F12>"}
shiftKeys = {
    "04":"A", "05":"B", "06":"C", "07":"D", "08":"E",
     "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J",
      "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O",
       "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T",
        "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y",
         "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$",
          "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")",
          "28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>",
          "2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"",
          "34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>",
          "3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>",
          "41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
output = []
keys = open('out.txt')
for line in keys:
    try:
        if line[0]!='0' or (line[1]!='0' and line[1]!='2') or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0' or line[6:8]=="00":
             continue
        if line[6:8] in normalKeys.keys():
            output += [[normalKeys[line[6:8]]],[shiftKeys[line[6:8]]]][line[1]=='2']
        else:
            output += ['[unknown]']
    except:
        pass

keys.close()

flag=0
print("".join(output))
for i in range(len(output)):
    try:
        a=output.index('<DEL>')
        del output[a]
        del output[a-1]
    except:
        pass

for i in range(len(output)):
    try:
        if output[i]=="<CAP>":
            flag+=1
            output.pop(i)
            if flag==2:
                flag=0
        if flag!=0:
            output[i]=output[i].upper()
    except:
        pass

print ('output :' + "".join(output))
mappings = { 0x04:"A",  0x05:"B",  0x06:"C", 0x07:"D", 0x08:"E", 0x09:"F", 0x0A:"G",  0x0B:"H", 0x0C:"I",  0x0D:"J", 0x0E:"K", 0x0F:"L", 0x10:"M", 0x11:"N",0x12:"O",  0x13:"P", 0x14:"Q", 0x15:"R", 0x16:"S", 0x17:"T", 0x18:"U",0x19:"V", 0x1A:"W", 0x1B:"X", 0x1C:"Y", 0x1D:"Z", 0x1E:"1", 0x1F:"2", 0x20:"3", 0x21:"4", 0x22:"5",  0x23:"6", 0x24:"7", 0x25:"8", 0x26:"9", 0x27:"0", 0x28:"\n", 0x2a:"[DEL]",  0X2B:"    ", 0x2C:" ",  0x2D:"-", 0x2E:"=", 0x2F:"[",  0x30:"]",  0x31:"\\", 0x32:"~", 0x33:";",  0x34:"'", 0x36:",",  0x37:"." }

nums = []
keys = open('out.txt')
for line in keys:
    if line[0]!='0' or line[1]!='0' or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0':
         continue
    nums.append(int(line[6:8],16))

keys.close()

output = ""
for n in nums:
    if n == 0 :
        continue
    if n in mappings:
        output += mappings[n]
    else:
        output += '[unknown]'

print 'output :\n' + output

这两个脚本中提取的数据为 6~8位 ,所以需要将没有冒号的数据加上冒号才可以对应提取,附上加冒号的脚本:

f=open('usbdata.txt','r')
fi=open('out.txt','w')
while 1:
    a=f.readline().strip()
    if a:
        out=''
        for i in range(0,len(a),2):
            if i+2 != len(a):
                out+=a[i]+a[i+1]+":"
            else:
                out+=a[i]+a[i+1]
        fi.write(out)
        fi.write('\n')
    else:
        break

fi.close()

解出的数据:

解得结果中的 <CAP> 和 [unknown] 就是一些wp中所说的 不可解的字符

在结果中可以看到 Autokey decipher 的字样,可以断定其是被autokey这种加密方式加密得到的字符串:

mplrvffczeyoujfjkybxgzvdgqaurkxzolkolvtufblrnjesqitwahxnsijxpnmplshcjbtyhzealogviaaissplfhlfswfehjncrwhtinsmambvexo<DEL>pze<DEL>iz

删去 <DEL> 前对应字符,得到:

mplrvffczeyoujfjkybxgzvdgqaurkxzolkolvtufblrnjesqitwahxnsijxpnmplshcjbtyhzealogviaaissplfhlfswfehjncrwhtinsmambvexpziz

接下来就需要解密,由于题中没有给出autokey加密所需的密钥,所以我们需要爆破得到明文

在该网址中详细介绍了有关autokey爆破的方法,我将爆破脚本以及要用到的其他几个文档打了包,可自行下载:

网盘链接:https://pan.baidu.com/s/18CgPQfHAUpTs9ssx2z1rgA

提取码:k70s

脚本的运行需要前置库 pycipher,安装方法如下:

pip install pycipher

解压后将里面的五个东西放在同一文件夹中,然后运行 breakautokey.py,脚本中 ctext 变量对应了要爆破的字符串(脚本对应环境python2)

可以看到当密钥长度爆破到8的时候对应密钥 FLAGHERE ,得到明文:

HELLOBOYSANDGIRLSYOUARESOSMARTTHATYOUCANFINDTHEFLAGTHATIHIDEINTHEKEYBOARDPACKAGEFLAGISJHAWLZKEWXHNCDHSLWBAQJTUQZDXZQPF

观察明文里面就有flag字样:FLAGISJHAWLZKEWXHNCDHSLWBAQJTUQZDXZQPF

所以得到最终的flag:flag{JHAWLZKEWXHNCDHSLWBAQJTUQZDXZQPF}

总结

本题考点虽然不多,但是考的类型都较为复杂,对脚本编写能力要求也较高,由此看来想要打好misc,python一定不能太差,要有一定的脚本编写和改写能力
ps:如果wp中哪里有写错的地方,还请各位dalao指正!!

发表评论

email
web

全部评论 (暂无评论)

info 还没有任何评论,你来说两句呐!