0%

数字取证相关实验

一、背景

1.USB流量分析

该部分实验重点聚焦于通过USB通信流量还原出键盘和鼠标的输入行为。USB接口广泛用于各种外设连接,尤其是键盘和鼠标等HID设备,在数字取证中具有极高的分析价值。在一些攻击或信息泄露事件中,攻击者可能通过插入外接键盘或远程操控鼠标进行非法操作,而这些操作很难通过传统日志直接察觉。因此,捕获并解析USB HID类设备的流量,进而还原用户的输入内容,是一种重要的补充取证手段。

USB流量分析作为数字取证和安全研究中的一个重要方向,近年来逐渐受到重视,尤其是在面对日益复杂的物理层攻击和数据泄露事件时,其在安全审计、恶意设备识别以及用户行为还原等方面展现出显著价值。目前,USB流量分析的研究主要集中在两个方向:一是对大容量存储类设备(如U盘、移动硬盘)的分析,主要关注文件操作行为、数据传输过程及可能的恶意Payload植入;二是对HID类设备(如键盘、鼠标)的分析,致力于还原用户的输入行为,判断是否存在可疑或自动化操控行为。

在技术实现层面,USBPcap 是目前最常用的开源USB数据捕获工具之一,它可与 Wireshark 配合使用,实现对 Windows 平台下 USB 数据包的实时采集和解析。对于 Linux 平台,usbmon 和 Wireshark 结合使用也可实现类似功能。在分析方法上,研究者通常需要对 USB 协议栈的各个层次,如控制传输、批量传输、中断传输等进行解码,并进一步针对特定类设备的协议进行定制化解析。例如,对于键盘输入,还需识别HID报文中的扫描码并映射到具体字符;对于鼠标操作,则需结合时间序列解析相对移动与点击行为。

尽管目前已有一定的工具链和研究基础,但USB流量分析依然面临诸多挑战,例如设备协议的多样性与专有性、数据加密或压缩机制的干扰、以及高频数据还原中的时序精度控制等问题。因此,USB流量分析仍然是一个具有高度实用价值和持续研究空间的取证技术方向。

2.系统日志取证

日志文件在实际数字取证案件中是最基础且最关键的证据来源之一,本实验重点在于通过操作系统日志与网络抓包数据(.pcap 文件)的联合分析,还原系统中的可疑行为或安全事件。日志文件作为操作系统和应用程序运行状态的重要记录,能够详细反映出用户登录、权限变更、系统调用、进程启动、文件访问等活动;而 .pcap 抓包文件则提供了网络层面的数据交互信息,例如主机之间的通信、端口连接、数据传输行为等。将这两类数据结合分析,能够从系统内部行为与外部通信两条线索交叉验证事件真相,进一步增强取证的完整性和说服力。这种方式不仅更贴近真实的攻击溯源流程,也提升了实验的实践价值和技术深度。

从技术现状来看,日志取证已经是数字取证领域中较为成熟的方向,拥有丰富的工具支持与标准化流程。Windows 系统提供 Event Viewer 工具查看系统、安全、应用等多种日志类型,Linux 则通过 syslog、journalctl、auditd 等机制实现对系统活动的细粒度监控。.pcap 文件的分析主要依赖 Wireshark、tcpdump、Tshark 等工具,这些工具能够详细解析网络协议数据包,帮助识别可疑的通信行为、命令控制流量或恶意数据传输。在取证实践中,研究者通常会根据日志中的时间戳与事件类型,定位关键时间段,并在对应的 .pcap 数据中寻找相关通信行为,以此交叉构建事件发生的完整链条。

尽管当前日志与网络流量分析工具较为完善,但在实际应用中仍存在一些挑战。例如系统日志格式差异较大、时间戳不统一、日志内容可能被删除或篡改,而网络抓包数据通常体量庞大,且难以直接对应到特定的系统操作。因此,将日志与 .pcap 数据有效整合并进行关联分析,需要较强的技术功底与逻辑推理能力。通过本次实验,我希望能够掌握从多源数据中提取关键信息、构建时间线和还原行为逻辑的能力,从而提升自身在数字取证与事件分析方面的综合素养。

二、实验的准备工作

本报告包含三个实验

1.USB流量分析

1.1实验目的

**实验一:**某安全测评人员在对某银行卡密码输入系统进行渗透测试,截获了一段通过USB键盘输入6位数字密码的流量,其中也包含了一些其他无关的USB设备的流量,要求从中恢复出6位数字密码。

**实验二:**某密钥数据藏于usb鼠标流量中,通过USB协议数据中的鼠标移动轨迹转换成密钥。

1.2 实验环境

Windows 11

Python 3.11

Wireshark

1.3 理论知识

USB协议数据部分在Leftover Capture Data域中,数据长度为八个字节,其中键盘击健信息集中在第三个字节中。如下所示,在使用wireshark捕捉到的流量中,我们主要看第三个字节的内容,将它与按键值相对以得出按键内容。

如图,发现击键信息为0x06,即对应的按键为C

USB协议鼠标数据部分在Leftover Capture Data域中,数据长度为四个字节,其中第一个字节代表按键,当取0x00时,代表没有按键、为0x01时,代表按左键,为0x02时,代表当前按键为右键。 第二个字节可以看成是一个signed byte类型,其最高位为符号位,当这个值为正时,代表鼠标水平右移多少像素,为负时,代表水平左移多少像素。 第三个字节与第二字节类似,代表垂直上下移动的偏移。

如图0x00002000,表示鼠标垂直向上移动20。

2. 日志取证

2.1实验目的

实验三: 分析给出的.log文件与.pcap文件,还原sql注入回显日志和流量,并解密出加密数据库中的flag值。

2.2 实验环境

Windows 11

Python 3.11

2.3 理论知识

2.3.1 正则表达式

在数字取证分析中,正则表达式是一种强大且高度灵活的文本匹配技术,能够通过模式匹配方式识别和提取结构化或半结构化数据中的关键信息。正则表达式的核心在于使用一套特定语法对字符或字符串的结构进行抽象描述,比如使用\d{1,3}可以匹配任意长度为1到3的数字,这在IP地址提取中尤为常见。在日志解析中,我们常利用正则表达式提取访问时间、请求路径、状态码、User-Agent、Referer等字段。例如,分析HTTP访问日志时,正则表达式可以精准捕获客户端IP、HTTP方法(如GET、POST)、请求资源路径、返回码(如200、404)等内容。正则表达式不仅适用于文本日志文件,也可用于.pcap网络抓包文件中通过文本重构后的HTTP请求内容提取。在实际应用中,结合Python等语言内置的re模块,可以快速实现对大批量日志数据的自动化筛查与格式化提取,为后续的行为判别、攻击分析等奠定数据基础。

2.3.2 Web服务器日志格式

Linux系统中,Web服务器的访问日志通常记录客户端与服务器之间的HTTP请求和响应信息,这些日志广泛用于流量分析、性能监控和安全审计。日志的每一条记录通常包含客户端IP地址和端口、服务器IP地址和端口、请求时间、请求方法、请求资源路径、HTTP协议版本、响应状态码、响应体大小、来源网址和用户代理等多个字段。

以下为示例日志:

1
172.20.0.2:80 172.20.0.1 - - [01/Nov/2024:02:15:06 +0000] "GET / HTTP/1.1" 200 640 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0"

日志开头172.20.0.2:80代表服务器的IP和端口,172.20.0.1是发起请求的客户端IP。接下来的两个破折号通常用作占位符,表示未填写的字段(如身份验证用户名等)。

方括号中的[01/Nov/2024:02:15:06 +0000]表示请求的具体时间和时区信息,紧接着的双引号内为HTTP请求的详细内容,包括请求方法、请求资源路径以及协议版本。之后的数字200代表服务器对请求的响应状态码,表示请求成功,640表示服务器返回给客户端的数据大小。

日志末尾的两个字段分别为来源页面(此处用”-“表示无来源)和用户代理字符串,该字符串详尽描述了客户端所使用的浏览器类型、操作系统和渲染引擎版本,有助于识别访问设备及其特征。

这种格式的日志记录详细且结构化,便于自动化工具进行解析和分析,是网络安全和性能监控中不可或缺的重要数据来源。

2.3.2 Sql注入

SQL注入是一种典型的Web注入攻击方式,这类攻击在流量中具有一系列特征:首先是参数结构复杂、语法规律性强,例如频繁出现SUBSTR((SELECT database()),1,1)=CHAR(100)这样的表达式;其次是请求路径重复但参数略有变化,常用于逐字符爆破;此外,User-Agent字段固定也是重要线索,攻击者常使用sqlmap等自动化工具,其请求头中会出现如sqlmap/1.8.x#dev (https://sqlmap.org)的标识。盲注攻击的响应特征也十分明显,例如使用布尔盲注时,服务端返回页面内容大小(例如459字节)保持一致,可用于判断条件成立与否。因此,在日志与流量联合取证时,可以通过匹配注入语法模式、分析User-Agent异常、统计响应字节变化等手段,逐步识别攻击行为,甚至逆向还原攻击者意图与泄露信息内容。

2.3.1 RSA密钥文件特征

RSA密钥文件是非对称加密体系中的核心私有数据。在实际取证中,RSA密钥文件往往以标准PEM格式存储,其开头和结尾分别为—–BEGIN RSA PRIVATE KEY—–和—–END RSA PRIVATE KEY—–,中间为Base64编码的密钥体。

三、实验的步骤与结果

实验一:

主要步骤:使用tshark命令把cap data 提取出来,根据《USB键盘协议中的键码》中的HID Usage ID将数据还原成键位。

首先使用tshark将usb流量提取到usbdata.txt文件中。

此时的文件还有着默认的空行,使用脚本删除空行。

为了方便提取信息,在各个字节之间加上冒号,脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
f=open('usb2data_gbk.txt','r')
fi=open('out2.txt','w')
while 1:
a=f.readline().strip()
if a:
if len(a)==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()

之后根据对照表,编写脚本来还原数据对应的信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#最后用脚本提取
# print((line[6:8])) #输出6到8之间的值
#取出6到8之间的值
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]是删除键,恢复出6位数字,所以六位数字密码为720593。

实验二:

使用tshark 命令把pcap的数据提取并去除空行到usb2data.txt

使用上面提到过的加冒号的脚本,并将脚本里提到的16改为8,得到格式化后的数据文件。因为信息可能隐藏在左键、右键或无操作当中,利用脚本测试信息隐藏位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
nums = []
keys = open('out2.txt','r')
f = open('xy2.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 == 2 : # 1 代表左键
f.write(str(posx))
f.write(' ')
f.write(str(posy))
f.write('\n')

f.close()

得到有效坐标数据如下:

根据坐标信息绘制出鼠标轨迹:

1
2
3
4
5
6
7
8
from PIL import Image
img = Image.new('RGB',(2000,2000),(255,255,255))#创建Image对象
f =open('xy2.txt')#xy.txt文件
for line in f.readlines():
point =line.split()
img.putpixel((int(point[0]),int(point[1])),(0,0,0))#读取文件中的每一行,并修改像素
f.close()
img.show()

实验三:首先编写脚本对日志文件中的数据进行过滤,得出全部sql注入攻击命令以及回显结果。根据回显结果,还原流量包中的图片信息,得到加密私钥的秘钥。最后利用解密后的私钥针对flag进行解密。

注意到每次盲注后面注释有4个随机字符,可以拿来分组,写脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import re
import json
from urllib.parse import unquote

# 解析access.log
with open('access.log', 'r', encoding='utf-8') as f:
lines = f.readlines()

pattern = re.compile(
r'(?P<ip>\d+\.\d+\.\d+\.\d+):(?P<port>\d+)\s' # IP地址和端口
r'(?P<client_ip>\d+\.\d+\.\d+\.\d+)\s-\s-\s' # 客户端IP
r'\[(?P<timestamp>.*?)\]\s' # 时间戳
r'"(?P<method>\w+)\s(?P<path>[^\s]+)\sHTTP/1.1"\s' # 请求方法和path
r'(?P<status>\d+)\s(?P<size>\d+)\s' # 状态码和返回字节数
r'"(?P<referrer>.*?)"\s' # 来源链接
r'"(?P<user_agent>.*?)"' # 用户代理
)

logs = []
for line in lines:
match = pattern.match(line)
if match:
log = match.groupdict()
log['size'] = int(log['size'])
log['status'] = int(log['status'])
log['path'] = unquote(log['path'])
logs.append(log)

print('[+] 共解析出%d条日志' % len(logs))

# 筛选出user-agent为sqlmap/1.8.9.1#dev (https://sqlmap.org),且时间在01/Nov/2024:03:07:32 +0000及之后的请求,且path开头为"/publishers.php?pub_id=9952",末尾为"-- 任意四字符"
filter_log = []
for log in logs:
if log['user_agent'] == 'sqlmap/1.8.9.1#dev (https://sqlmap.org)' and log['timestamp'] >= '01/Nov/2024:03:07:32 +0000':
pattern = re.compile(r'-- [a-zA-Z]{4}')
if pattern.match(log['path'][-7:]) and log['path'].startswith('/publishers.php?'):
filter_log.append(log)

print('[+] 共筛选出%d条日志' % len(filter_log))


# 将log根据特征进行分组
grouped_logs = {}
for log in filter_log:
key = log['path'][-4:]
if key not in grouped_logs:
grouped_logs[key] = []
grouped_logs[key].append(log)

print('[+] 共分组%d组' % len(grouped_logs))

grouped = {}
for key, logs in grouped_logs.items():
pattern = r"SUBSTR\(\((.*?)\),(\d+),\d+\)([>=])CHAR\((\d+)\)"
if len(logs) > 1:
for log in logs:
match = re.search(pattern, log['path'])
if match:
if key not in grouped:
grouped[key] = {'sql': match.group(1), 'chars': []}
pos = int(match.group(2))
if pos > len(grouped[key]['chars']):
grouped[key]['chars'].append([])
grouped[key]['chars'][pos-1].append((match.group(3), int(match.group(4)), log['size'] == 459))


for key, value in grouped.items():
result_str = ''
print(value['sql'])
for i, chars in enumerate(value['chars']):
larger = []
smaller_equal = []
skip = False
for char in chars:
if char[0] == '=' and char[2]:
result_str += chr(char[1])
skip = True
break
if char[0] == '>' and char[2]:
larger.append(char[1])
else:
smaller_equal.append(char[1])
if not skip:
if len(smaller_equal) > 0:
result_str += chr(min(smaller_equal))
else:
result_str += chr(max(larger))
print(result_str)
print()

得到日志过滤结果:

搜索关键词得出关键信息隐藏在一个图片中。

在wireshark中打开流量包,进行协议分级:

查找到MIME协议数据包对应的TCP报文,将原始数据另存为.jpg文件。

用二进制数据编辑器打开上述文件,删除http报文部分,保留图片编码数据

得到还原后的图片:

从过滤得到的sql回显信息中,找到有关Pontes用户的全部字段信息:

使用图片中的密钥对ENCRYPTED PRIVATE KEY进行解密:

得到解密后的私钥:

根据acc_flag格式看出是base64编码,编写脚本进行解码并保存:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import base64

base64_str = """
tJkjkC9zdTfV/vjWjKBQERPvbJB+MTzNgv9Q7OsSeW9VO+cz9GM7gdfFu3+UwSfK
p3OStBv6wESZitD8x9rR8Jx4LwKU+i1ysKUQWOvORYSSif1zt37ored1r1IALNX1
jKEWRMZXTQU07kNULKk3Zve7Q8qTnbGviNqFjG3W4s0=
"""

# 去除多余空白和换行
clean_str = "".join(base64_str.strip().splitlines())

# Base64 解码
decoded_bytes = base64.b64decode(clean_str)

# 写入二进制文件
with open("data.txt", "wb") as f:
f.write(decoded_bytes)

print("Base64 解码完成,已写入 data.txt")

之后用私钥去解密acc_flag,得到最终flag:

参考资料

[1] USB协议中HID设备描述符以及键盘按键值对应编码表

[2] 2024-CCB-CISCN-Quals https://github.com/CTF-Archives/2024-CCB-CISCN-Quals

[3] USB流量 https://wuyong.lanzout.com/ihBPQ0uug8id