前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >USB流量知识点小结

USB流量知识点小结

作者头像
回天
发布2023-04-25 15:06:06
6110
发布2023-04-25 15:06:06
举报
文章被收录于专栏:Ga1@xy's W0r1d

USB接口是目前最为通用的外设接口之一,通过监听该接口的流量,可以得到很多有意思的东西,例如键盘击键,鼠标移动与点击,存储设备的明文传输通信、USB无线网卡网络传输内容等。

前言

USB流量的捕获可以使用wireshark或usbpcap来进行,在ctf中通常会给出已经捕获好的流量包,而我们需要做的便是从流量包中还原捕获的数据。USB流量分为两大类:键盘流量和鼠标流量。下面会分别进行解析。

键盘流量

附件链接:https://pan.baidu.com/s/1aJ_EDTqpUJht7Mpybnw5zQ 提取码:zuqw

注:以下内容以附件中的题为例

USB协议的数据部分在Leftover Capture Data域中,用wireshark打开流量包

在蓝色部分可以看到这个区域,右键→应用为列,即可在上面显示出来这一列

键盘流量的数据长度为8个字节,其中有关击键的信息在第三字节(十六进制表示)

详细的击键信息对照表可参考:https://max.book118.com/html/2017/0407/99227972.shtm

tshark命令可以提取对应的Leftover Capture Data域中数据:

代码语言:javascript
复制
tshark -r usb.pcap -T fields -e usb.capdata > usbdata.txt

如果提取出来的数据有空行,可以将命令改为如下形式:

代码语言:javascript
复制
tshark -r usb.pcapng -T fields -e usb.capdata | sed '/^\s*$/d' > usbdata.txt

提取出来的数据

提取出来的数据可能会带冒号,也可能不带(有可能和wireshark的版本相关),但是一般的脚本都会按照有冒号的数据来识别,有冒号时提取数据的[6:8],无冒号时数据在[4:6],可以用脚本来加上冒号

代码语言:javascript
复制
f=open('usbdata.txt','r')
fi=open('out.txt','w')
while 1:
    a=f.readline().strip()
    if a:
        if len(a)==16: # 鼠标流量的话len改为8
            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()

得到这样的数据,此时对应的第三字节,也就是[6:8]就代表了击键信息

提取出键盘流量后需要用脚本还原数据对应的信息,附上两个还原信息较为完整的脚本(python2)

代码语言:javascript
复制
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))
代码语言:javascript
复制
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

此题我用了第二个脚本,还原得到以下信息

将其中[DEL]对应的字符删去,得到

代码语言:javascript
复制
HELLO , I AM WRITING SOMETHING IMPORTANT .
BUT I DO NOT USE PINYIN
I AM OLD .

DDPEIYUJ,Q S GAVCLWBMPYG RUG STK B .
I FPI J ET K YYGY R GAAA LWBMR .
WQ SK C RCN GHDMP QKD YTD R RUUJ WT O PYG RUG STK RJUQ H FCU 

Q YI J PYG RUG STK KWKW 


OVER 
ENJOY MY MISC .

最后再用五笔输入下中间的看似乱码的字符串,就可以得到flag

ps:重要的不是五笔,而是借这道题来讲述有关键盘流量的提取和解密,不要过于纠结五笔……

鼠标流量

附件链接:https://pan.baidu.com/s/1lIDKVmnNkqhv4h3JNsx8Mg 提取码:a1tn

鼠标流量的提取方式和上述键盘流量的方式相同,但不同的是鼠标流量的数据长度为4字节

以附件中的流量包为例

删去提取出来的数据中长度不正确的数据(没有冒号可用上面提到过的脚本加上),得到

在鼠标流量数据中,第一字节代表按键,当取0x00时代表没有按键,取0x01时代表按左键,取0x02时代表按右键。第二个字节可以看成是一个signed byte类型,当这个值为正时,代表鼠标水平右移多少像素,为负时,代表水平左移多少像素。第三个字节与第二字节类似,代表垂直上下移动的偏移。(具体可见下面的代码)

代码语言:javascript
复制
nums = []
keys = open('out.txt','r')
f = open('xy.txt','w')
posx = 0
posy = 0
for line in keys:
    if len(line) != 12 :
        continue
    x = int(line[3:5],16)
    y = int(line[6:8],16)
    if x > 127 :
        x -= 256
    if y > 127 :
        y -= 256
    posx += x
    posy += y
    btn_flag = int(line[0:2],16)  # 1 for left , 2 for right , 0 for nothing
    if btn_flag == 1 : # 1 代表左键
        f.write(str(posx))
        f.write(' ')
        f.write(str(posy))
        f.write('\n')

f.close()

本题的flag信息藏在右键中,当脚本中btn_flag取2时可以得到一系列坐标

熟悉的坐标形式,用gnuplot转化成图像即可

看起来是颠倒的,导出后convert翻转一下即可

得到flag:XNUCA{USBPCAPGETEVERYTHING}

参考文章

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-04-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 键盘流量
  • 鼠标流量
  • 参考文章
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档