ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CTF 流量分析实战:从 USB 鼠标/键盘数据包解码到 AutoKey 密文破解

CTF 流量分析实战:从 USB 鼠标/键盘数据包解码到 AutoKey 密文破解 文档网络安全教程【免费下载链接】ctf-wikiCome and join us, we need you!项目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki点击查看免费下载USB 流量是 CTF Misc杂项题目中常见的流量分析对象攻击者往往通过物理键盘或鼠标输入留下痕迹而抓包工具捕获的usb.capdata字段中隐藏着每一次击键与鼠标位移的离散数据包。本文基于 ctf-wiki 的 USB 协议分析章节系统讲解 USB HID 鼠标/键盘协议的数据包格式、Wireshark/tshark抓包与提取方法、完整的 Python 解码脚本并以Xman三期夏令营排位赛例题AutoKey为实战案例演示从流量还原出键盘密文、再到爆破 AutoKey 密码拿到flag的完整链路。读完本文你将掌握 USB 流量题的两大核心技能从数据包恢复鼠标轨迹与键盘击键以及将解码结果交给密码学工具做后续攻击。USB 协议基础与三种使用方式在分析任何 USB 流量之前首先要判断设备属于哪种通信类型。USB 设备主要有三种使用方式l USB UART l USB HID l USB MemoryUARTUniversal Asynchronous Receiver/Transmitter设备仅把 USB 当作简单的收发通道除数据传输外没有其他通讯功能HIDHuman Interface Device人性化接口设备用于交互式设备典型代表是键盘、鼠标、游戏手柄和数字显示设备USB Memory数据存储外部硬盘External HDD、U 盘thumb drive/flash drive等存储设备。CTF 流量题中最常见的就是USB HID键盘、鼠标与USB Memory。本文聚焦于 HID 中的键盘流量与鼠标流量。Vendor ID 与 Product ID每一个 USB 设备尤其是 HID 或 Memory 设备都有唯一的供应商 IDVendor ID和产品识别码Product ID。Vendor ID 标记设备由哪个厂商生产Product ID 用于区分同一厂商下的不同产品。在 Linux 下可用lsusb命令查看所有 USB 设备例如虚拟机中连接的一只无线鼠标会显示为Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse其中ID 0e0f:0003就是 Vendor-Product ID 对Vendor ID 0e0fProduct ID 0003。Bus 002 Device 002代表 USB 设备的连接位置这个编号在后面选择抓包接口时需要记录下来——usbmonX接口中的数字 X 正是对应 USB Bus 编号。鼠标协议4 字节数据包鼠标移动表现为连续性与键盘击键的离散性不同但实际上鼠标动作产生的数据包也是离散的计算机呈现的连续信息都由大量离散信息构成。一个鼠标数据包的数据区为4 个字节字节含义第 1 字节按键状态0x00无按键0x01左键0x02右键第 2 字节水平位移signed byte最高位为符号位正值表示水平右移像素负值表示水平左移像素第 3 字节垂直位移signed byte最高位为符号位正值表示垂直下移负值表示垂直上移把每个数据包中的位移点按顺序累积即可恢复出鼠标的移动轨迹例如在手写板上画出字符。键盘协议8 字节数据包键盘数据包的数据长度为8 个字节击键信息集中在第 3 个字节每次 key stroke 都会产生一个 keyboard event usb packet。第 1 字节为修饰键位modifier例如0x00表示无修饰键、0x20表示 Shift 被按下第 3 字节是对应 HID Usage ID 的键码需要借助 USB HID Usage Tables 映射表将其还原为具体字符。00:00:xx:00:00:00:00:00其中xx即第 3 字节的键码值。根据 data 值与具体键位的对应关系即可从数据包恢复出键盘的按键信息。常用工具社区已有现成的半自动化解码工具可直接用于快速验证UsbMiceDataHacker鼠标流量数据包解析工具用于恢复鼠标轨迹UsbKeyboardDataHacker键盘流量数据包解析工具用于恢复击键内容。在自动化工具无效或需要定制处理如处理 Shift 组合键、过滤脏数据时就需要自己编写解码脚本下文会给出完整实现。流量包是如何捕获的usbmon 与 Wireshark拿到一个 USB 流量包后先要理解它是如何被捕获的。Wireshark 通过 Linux 内核的usbmon模块抓取 USB 总线上的原始数据。用 udev 配置抓包权限用root权限运行 Wireshark 可以捕获 USB 数据流但通常不建议这么做。更规范的做法是创建usbmon用户组把当前用户加入该组并写入 udev 规则让普通用户也能读取 USB 总线数据addgroup usbmon gpasswd -a $USER usbmon echo SUBSYSTEMusbmon, GROUPusbmon, MODE640 /etc/udev/rules.d/99-usbmon.rules如果usbmon内核模块未被加载还需要手动加载modprobe usbmon选择正确的抓包接口打开 Wireshark会看到usbmonX这样的接口其中 X 为数字。当接口处于活跃状态或有数据流经过时Wireshark 界面会以波形图方式显示。选择哪个接口就是前面用lsusb记录下来的 USB Bus 编号——例如Bus 002对应usbmon2Bus 000对应usbmon0。选中对应接口后即可观察 USB 设备与主机之间的通信过程为后续流量分析提供原始素材。如何分析一个 USB 流量包tshark 提取数据USB 协议的数据部分位于Leftover Capture Data剩余捕获数据域中Wireshark 中以usb.capdata字段表示。分析的第一步就是把该字段从 pcap 中批量提取出来。Linux / macOStshark 命令行tshark -r example.pcap -T fields -e usb.capdata # 如果想导入 usbdata.txt 文件中后面加上参数 tshark -r example.pcap -T fields -e usb.capdata usbdata.txt-r指定读取的 pcap 文件-T fields指定输出为字段模式-e usb.capdata指定要打印的字段。Windowstshark.exeWindows 下安装 Wireshark 后其安装目录下自带tshark.exe例如D:\Program Files\Wireshark\tshark.exe。调用cmd定位到该目录输入同样的命令即可tshark.exe -r example.pcap -T fields -e usb.capdata usbdata.txt用 -Y 过滤器精准定位补充在 ctf-wiki 的数据提取章节中还给出了更高效的tshark用法通过-Y过滤器与 Wireshark 显示过滤器语法一致先筛出目标报文再用-T fields -e指定字段。通用的命令模板为tshark -r **.pcap -Y ** -T fields -e ** data参数速查-Y display filter packet display filter in Wireshark display filter syntax -T pdml|ps|psml|json|jsonraw|ek|tabs|text|fields text output format -e field field to print if -T fields selected (e.g. tcp.port, _ws.col.Info, usb.capdata)Tips-e后面的字段名如果不确定可以在 Wireshark 界面中右击目标数据选中后自动获得。提取结果的形态运行命令并查看usbdata.txt会发现键盘流量提取出的每行数据包长度为8 个字节以冒号分隔的十六进制形式例如00:00:08:00:00:00:00:00。鼠标流量则每行4 个字节。拿到这种规整的十六进制序列后就可以编写脚本解码了。键盘流量解码实战映射表与 Python 脚本键盘解码的核心是维护一张HID Usage ID → 字符的映射表。按下普通键时用normalKeys按下 Shift 组合键时用shiftKeys。下面是一份完整的解码脚本集成了解析、过滤、输出全流程#!/usr/bin/env python import sys import os DataFileName usb.dat presses [] 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} def main(): # check argv if len(sys.argv) ! 2: print Usage : print python UsbKeyboardHacker.py data.pcap print Tips : print To use this python script , you must install the tshark first. print You can use sudo apt-get install tshark to install it print Thank you for using. exit(1) # get argv pcapFilePath sys.argv[1] # get data of pcap os.system(tshark -r %s -T fields -e usb.capdata %s % (pcapFilePath, DataFileName)) # read data with open(DataFileName, r) as f: for line in f: presses.append(line[0:-1]) # handle result for press in presses: Bytes press.split(:) if Bytes[0] 00: if Bytes[2] ! 00: result normalKeys[Bytes[2]] elif Bytes[0] 20: # shift key is pressed. if Bytes[2] ! 00: result shiftKeys[Bytes[2]] else: print [-] Unknow Key : %s % (Bytes[0]) print [] Found : %s % (result) # clean the temp data os.system(rm ./%s % (DataFileName)) if __name__ __main__: main()脚本逻辑说明参数检查接收 pcap 文件路径作为唯一参数未传参时打印用法并退出数据提取内部调用tshark -r pcap -T fields -e usb.capdata将数据暂存到usb.dat逐包解析按冒号切分每个 8 字节数据包判断第 1 字节修饰键00表示无修饰键走normalKeys映射20表示按下 Shift 走shiftKeys映射其他修饰键值则打印警告输出与清理拼接得到明文并删除临时文件usb.dat。注原脚本基于 Python 2 编写print语句、os.system调用在 Python 3 环境中需将print ...改为print(...)。另一种更轻量的写法是直接把第 3 字节提取出来查表同时用条件过滤掉数据包中的干扰位例如系统自动产生的空按键包如下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(usbdata.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)) # 00:00:xx:.... 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)这段脚本用行内索引逐一检查数据包中除第 3 字节line[6:8]外的其余字节是否全为00从而滤掉非击键包再对第 3 字节的键码查表拼接输出。注这里的print(output :n output)中:n疑为换行符:\n的笔误读者在实际运行时可按需修正映射表中0x28实际对应回车键RET0x2a对应删除键DEL社区脚本中常直接映射为n/[DEL]等可读标记输出后需结合上下文人工整理。鼠标流量解码实战轨迹恢复鼠标流量解码的核心是把每包的 2、3 字节当作有符号数累加坐标。由于位移字节最高位是符号位读取为无符号数后若大于127则需要减去256转为负数即补码还原然后累积到posx/posy。一份可用的鼠标流量转换脚本如下nums [] keys open(usbdata.txt,r) 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 : print posx , posy keys.close()脚本逐行读取 4 字节12 个十六进制字符的鼠标数据包line[3:5]是水平位移、line[6:8]是垂直位移符号位还原后累积坐标并仅在左键按下btn_flag 1时输出当前坐标点——这样输出的坐标点序列就是鼠标实际画出的轨迹。更高效的做法awk gnuplotctf-wiki 的数据提取章节给出了Google CTF 2016 Forensic-200一题的通用解法无需写完整脚本直接用 tshark 导出、awk 做符号还原与坐标累加、gnuplot 绘图tshark -r capture.pcapng -T fields -e usb.capdata data2.txt awk -F: function comp(v){if(v127)v-256;return v}{xcomp(strtonum(0x$2));ycomp(strtonum(0x$3))}$101{print x,y} data.txt data3.txt gnuplot plot data3.txt三步走Step 1从鼠标协议中提取数据usb.capdataStep 2通过 awk 进行位置坐标转换comp()函数完成有符号数还原$101筛选左键按下的包Step 3用 gnuplot 把坐标点绘成图形直接看出隐藏内容。这种方法把脚本编写压缩为一行命令适合快速验证鼠标轨迹类题目。实战例题Xman AutoKey题目Xman三期夏令营排位赛练习题AutoKey流量包为task_AutoKey.pcapng。拿到 USB 流量包后按前面总结的流程逐步推进。Step 1tshark 导出全部键盘数据包tshark -r task_AutoKey.pcapng -T fields -e usb.capdata usbdata.txt观察导出结果确认是 8 字节键盘数据包。Step 2键盘解码得到密文用前面的键盘解码脚本取出第 3 字节对照映射表还原击键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(usbdata.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)) # 00:00:xx:.... 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)运行得到如下解码结果output :n[unknown]A[unknown]UTOKEY.DECIPHER[unknown]MPLRVFFCZEYOUJFJKYBXGZVDGQAURKXZOLKOLVTUFBLRNJESQITWAHXNSIJXPNMPLSHCJBTYHZEALOGVIAAISSPLFHLFSWFEHJNCRWHTINSMAMBVEXO[DEL]PZE[DEL]IZ去除干扰符号[unknown]、[DEL]、引号后得到一段纯大写密文MPLRVFFCZEYOUJFJKYBXGZVDGQAURKXZOLKOLVTUFBLRNJESQITWAHXNSIJXPNMPLSHCJBTYHZEALOGVIAAISSPLFHLFSWFEHJNCRWHTINSMAMBVEXPZIZ从UTOKEY、.DECIPHER 等字样可以推断这是一道**自动密钥密码Autokey Cipher**的题——题目名AutoKey也印证了这一点。问题变成在不知道密钥的情况下如何破解 AutokeyStep 3Autokey 密码的密钥爆破Autokey 密码的破解思路是随机搜索stochastic searching 语言模型评分对候选密钥逐位扩展用英文 n-gram 统计模型quadgrams / trigrams给解密结果打分分数越高越接近真实英文明文。经典做法是先对密钥长度KLEN从 3 到 20 逐一尝试对每个长度先用所有 3 字母组合26³ 种做前缀初始化用 trigram 评分选出前 N 个最优候选在保留下来的候选基础上逐位贪心扩展密钥每步尝试 26 个字符用 qgram 评分保留 Top-N最终对每个候选密钥完整解密选出全局评分最高者输出。依赖pycipher库中的Autokey类和ngram_score模块配合quadgrams.txt、trigrams.txt语料文件爆破脚本如下from ngram_score import ngram_score from pycipher import Autokey import re from itertools import permutations qgram ngram_score(quadgrams.txt) trigram ngram_score(trigrams.txt) ctext MPLRVFFCZEYOUJFJKYBXGZVDGQAURKXZOLKOLVTUFBLRNJESQITWAHXNSIJXPNMPLSHCJBTYHZEALOGVIAAISSPLFHLFSWFEHJNCRWHTINSMAMBVEXPZIZ ctext re.sub(r[^A-Z],,ctext.upper()) # keep a list of the N best things we have seen, discard anything else class nbest(object): def __init__(self,N1000): self.store [] self.N N def add(self,item): self.store.append(item) self.store.sort(reverseTrue) self.store self.store[:self.N] def __getitem__(self,k): return self.store[k] def __len__(self): return len(self.store) #init N100 for KLEN in range(3,20): rec nbest(N) for i in permutations(ABCDEFGHIJKLMNOPQRSTUVWXYZ,3): key .join(i) A*(KLEN-len(i)) pt Autokey(key).decipher(ctext) score 0 for j in range(0,len(ctext),KLEN): score trigram.score(pt[j:j3]) rec.add((score,.join(i),pt[:30])) next_rec nbest(N) for i in range(0,KLEN-3): for k in xrange(N): for c in ABCDEFGHIJKLMNOPQRSTUVWXYZ: key rec[k][1] c fullkey key A*(KLEN-len(key)) pt Autokey(fullkey).decipher(ctext) score 0 for j in range(0,len(ctext),KLEN): score qgram.score(pt[j:jlen(key)]) next_rec.add((score,key,pt[:30])) rec next_rec next_rec nbest(N) bestkey rec[0][1] pt Autokey(bestkey).decipher(ctext) bestscore qgram.score(pt) for i in range(N): pt Autokey(rec[i][1]).decipher(ctext) score qgram.score(pt) if score bestscore: bestkey rec[i][1] bestscore score print bestscore,autokey, klen,KLEN,:bestkey,,Autokey(bestkey).decipher(ctext)注该脚本同样基于 Python 2xrange、print语句且依赖外部语料文件与pycipher、ngram_score模块运行时需提前准备好也可将其中的xrange替换为range并改用print()在 Python 3 下运行。Step 4从爆破结果整理出 flag爆破脚本输出了各密钥长度下的最优候选及其评分。在klen 8时评分最高的结果为-674.914569565 autokey, klen 8 :FLAGHERE, HELLOBOYSANDGIRLSYOUARESOSMARTTHATYOUCANFINDTHEFLAGTHATIHIDEINTHEKEYBOARDPACKAGEFLAGISJHAWLZKEWXHNCDHSLWBAQJTUQZDXZQPF可以看到密钥为FLAGHERE解密明文已经完整可读——HELLO BOYS AND GIRLS YOU ARE SO SMART THAT YOU CAN FIND THE FLAG THAT I HIDE IN THE KEYBOARD PACKAGE FLAG IS JHAWLZKEWXHNCDHSLWBAQJTUQZDXZQPF。按单词切分后HELLO BOYS AND GIRLS YOU ARE SO SMART THAT YOU CAN FIND THE FLAG THAT IH IDE IN THE KEY BOARD PACKAGE FLAG IS JHAWLZKEWXHNCDHSLWBAQJTUQZDXZQPF最后一段JHAWLZKEWXHNCDHSLWBAQJTUQZDXZQPF就是隐藏在键盘流量中的 flag最终答案flag{JHAWLZKEWXHNCDHSLWBAQJTUQZDXZQPF}总结USB 流量分析是 CTF Misc 中极具套路化的一类题目其完整解题链路可以归纳为四步判断设备类型用lsusb查看 Vendor/Product ID确定是 HID 键盘、鼠标还是存储设备抓包或提取数据modprobe usbmon udev 权限配置后用 Wireshark 捕获usbmonX或直接用tshark -r xxx.pcap -T fields -e usb.capdata提取Leftover Capture Data按协议格式解码键盘取 8 字节数据包的第 3 字节查 HID 映射表区分普通键与 Shift 组合键鼠标对 4 字节数据包做有符号坐标还原与累加可用 awk gnuplot 快速绘图对还原出的明文/密文做后续攻击本例中还原出的是 Autokey 密文需结合 n-gram 语言模型与随机搜索爆破密钥最终拿到flag。掌握 USB 键盘/鼠标协议的数据包结构、tshark 字段提取技巧以及两类解码脚本就能在同类题目中快速定位数据、写出解码脚本并把解码结果顺畅地交给后续密码学分析环节。赞分享文档网络安全教程【免费下载链接】ctf-wikiCome and join us, we need you!项目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki点击查看免费下载相关推荐CTF 之 USB 流量包分析從 HID 鍵盤/鼠標協議到 AutoKey 例題實戰ctf-wikiCTF 之 USB 流量包分析從 HID 鍵盤/鼠標協議到 AutoKey 例題實戰ctf wiki 本篇技術指南以 ctf wiki 中文倉庫的 USB文档网络安全教程CTF 流量取证协议分析实战指南——从 Wireshark 过滤到 HTTP、DNS、WIFI、USB 解密CTF 流量取证协议分析实战指南——从 Wireshark 过滤到 HTTP、DNS、WIFI、USB 解密 本篇技术指南源自 ctf wiki https:文档网络安全教程CTF Wiki 密码学专题DES 数据加密标准——Feistel 结构与从差分分析到实战解密CTF Wiki 密码学专题DES 数据加密标准——Feistel 结构与从差分分析到实战解密 本篇是 CTF Wiki 密码学板块块加密专题的 DESDa文档网络安全教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表