————————————————————————————————————————
阅前提示:
本文针对于刚入学的研究生同学。如果你本科阶段基本上没有什么科研经验,也很少编码(例如知道Python,会用一点,但是完全不熟悉),导师丢过来一个数据集要预处理,但是看不懂数据集,或者看懂了不会写预处理的脚本。
本文在此抛砖引玉,教你如何使用AI来写一个预处理脚本。
PS:博主很菜,本文不涉及任何高深的知识。
————————————————————————————————————————
一、数据集及其介绍
以atlasv2这个数据集为例
ATLASv2数据集在原始ATLAS数据集的基础上进行了扩展,主要包含三类日志数据:Windows安全审计系统日志、Firefox浏览器日志以及通过WireShark捕获的DNS日志。相较于原数据集,ATLASv2引入了更高质量的背景噪声,并增加了额外的日志来源,如Sysmon日志和通过VMware Carbon Black Cloud跟踪的事件。这个扩展旨在提供更全面和详细的攻击检测数据,支持深入分析和研究多种攻击场景。
数据集介绍:[2401.01341] ATLASv2: ATLAS Attack Engagements, Version 2 (arxiv.org)
其中一条数据如下,其实就是一系列的日志数据。
{"type":"endpoint.event.filemod","process_guid":"7DMF69PK-05debeef-000009b8-00000000-1d8984c85f4a992","parent_guid":"7DMF69PK-05debeef-000001e0-00000000-1d8984c83839290","backend_timestamp":"2022-07-19 07:26:53 +0000 UTC","org_key":"7DMF69PK","device_id":98483951,"device_name":"WIN-32-H1","device_external_ip":"130.126.255.183","device_os":"WINDOWS","device_group":"","action":"ACTION_FILE_CREATE | ACTION_FILE_MOD_OPEN | ACTION_FILE_OPEN_WRITE | ACTION_FILE_OPEN_SET_ATTRIBUTES","schema":1,"device_timestamp":"2022-07-19 07:24:57.2128941 +0000 UTC","process_terminated":false,"process_reputation":"REP_RESOLVING","parent_reputation":"REP_RESOLVING","process_pid":2488,"parent_pid":480.0,"process_publisher":[{"name":"Cortado AG","state":"FILE_SIGNATURE_STATE_SIGNED | FILE_SIGNATURE_STATE_VERIFIED"}],"process_path":"c:\\program files\\vmware\\vmware tools\\tpautoconnsvc.exe","parent_path":"c:\\windows\\system32\\services.exe","process_hash":["7bc6e9df892edd7e09c544b598fa5eb3","3e2b444059769eda3d0ca96ca7f8bf49f81193a370d37045b64098ce2c1707ae"],"parent_hash":["5f1b6a9c35d3d5ca72d6d6fdef9747d6","d7bc4ed605b32274b45328fd9914fb0e7b90d869a38f0e6f94fb1bf4e9e2b407"],"process_cmdline":"\"C:\\Program Files\\VMware\\VMware Tools\\TPAutoConnSvc.exe\"","parent_cmdline":"C:\\Windows\\system32\\services.exe","process_username":"NT AUTHORITY\\SYSTEM","sensor_action":"ACTION_ALLOW","event_origin":"EDR","filemod_hash":["",""],"filemod_name":"c:\\windows\\system32\\spool\\drivers\\w32x86\\tp ps driver 642d4d86fc304982923cb27485a07b19.ppd","regmod_name":null,"modload_name":null,"modload_count":null,"modload_effective_reputation":null,"modload_hash":null,"modload_md5":null,"modload_publisher":null,"modload_sha256":null,"process_duration":null,"target_cmdline":null,"remote_port":null,"remote_ip":null,"local_port":null,"local_ip":null,"netconn_domain":null,"netconn_inbound":null,"netconn_protocol":null,"netconn_community_id":null,"childproc_name":null,"childproc_hash":null,"childproc_pid":null,"childproc_guid":null,"childproc_username":null,"childproc_publisher":null,"childproc_reputation":null,"crossproc_name":null,"crossproc_guid":null,"crossproc_hash":null,"crossproc_action":null,"crossproc_publisher":null,"crossproc_reputation":null,"crossproc_target":null,"scriptload_count":null,"scriptload_reputation":null,"scriptload_effective_reputation":null,"scriptload_publisher":null}
二、任务要求
依据OPM溯源模型,将该数据集处理成为,源节点,目标节点,边的溯源图数据。
//如果你从未接触过溯源相关的东西,在刚看到这个数据集的时候,有可能会很迷茫。再加上如果你在本科阶段很少写代码,那么这可能就是一个艰巨的任务。
三、分析数据集
//我这里分别使用的ChatGPT 4o mini和Kimi来完成接下的几步。(注意Kimi在内网内,目前可以免费使用;ChatGPT 4o mini需要一点魔法上网的技巧,当然它可以免注册免费使用,不要被淘宝上付费的骗了)
1.ChatGPT 4o mini
问1:让AI帮我们初步分析一下数据集,找出我们需要关注的位置,也帮我们更好地理解该数据集
答1:
问2:进一步找到具体的数据项
答2:
问3:因为我这个数据集的type类型不止有filemod这种,所以我这里还让它给我写了一个找出所有类型的代码
答3:
import json
# 读取数据集文件
def read_json_file(filename):
types_set = set()
with open(filename, 'r') as file:
for line in file:
record = json.loads(line)
event_type = record.get('type')
if event_type:
types_set.add(event_type)
return types_set
# 主程序
if __name__ == "__main__":
filename = 'dataset.json' # 替换为实际的数据集文件名
unique_types = read_json_file(filename)
# 打印所有唯一的type类型
for event_type in unique_types:
print(event_type)
PS:在本文的末尾,我会附上Windows上配置anaconda环境的方法,以及针对于很少跑Python代码的宝宝,附上如何跑AI输出的这些脚本的注意事项。
问4:我让ChatGPT写了一个输出找到该类型的第一条数据(因为数据太多了,自己找有些时候那种占比很低的类型找不到)。这个地方的type可以更换成别的,都很好用的。
答4:
import json
def find_first_filemod_entry(filename):
with open(filename, 'r') as file:
for line in file:
record = json.loads(line)
if record.get('type') == 'endpoint.event.filemod':
return record
return None
# 主程序
if __name__ == "__main__":
filename = 'dataset.json' # 替换为实际的数据集文件名
first_filemod_entry = find_first_filemod_entry(filename)
if first_filemod_entry:
print(json.dumps(first_filemod_entry, indent=4))
else:
print("No 'endpoint.event.filemod' type found in the dataset.")
2.Kimi(用它的原因是,它目前不要钱,灵动AI用来写一些脚本其实也还行,但是要钱)
//问法还是和上面一样的,我这里只截取Kimi的回答
答1:
答2:(这条我觉得Kimi答的更好一点)
答3:
import json
from collections import Counter
# 假设数据集是一个名为 dataset.json 的文件
filename = 'dataset.json'
# 读取JSON数据
with open(filename, 'r') as file:
data = json.load(file)
# 初始化计数器
type_counter = Counter()
# 遍历数据集中的每个条目
for item in data:
# 增加对应类型的计数
type_counter[item['type']] += 1
# 打印每种类型及其数量
for type, count in type_counter.items():
print(f"Type: {type}, Count: {count}")
答4:
import json
# 假设数据集是一个名为 dataset.json 的文件
filename = 'dataset.json'
# 读取JSON数据
with open(filename, 'r') as file:
data = json.load(file)
# 初始化一个标志变量,用于标记是否已经找到第一条符合条件的数据
found = False
# 遍历数据集中的每个条目
for item in data:
# 检查条目的类型是否为 endpoint.event.filemod
if item.get('type') == 'endpoint.event.filemod':
# 输出找到的第一条符合条件的数据
print(json.dumps(item, indent=4))
# 设置标志变量为 True
found = True
break # 找到后即退出循环
# 如果没有找到符合条件的数据,则打印提示信息
if not found:
print("No data found with type 'endpoint.event.filemod'.")
四、数据预处理程序
1.ChatGPT 4o mini
问1:我们依据上一步的分析,具体地告诉AI,我需要处理成为的数据集是怎样的
答1:
import json
import uuid
from urllib.parse import quote
def process_record(record):
# 处理 `type` 为 `endpoint.event.filemod` 的记录
if record.get('type') != 'endpoint.event.filemod':
return None
# 提取字段
src_uuid = record.get('process_guid')
src_name = record.get('process_path')
dst_name = record.get('filemod_name')
# 处理 dst_name 成为 UUID 形式
# 这里使用 UUID 的哈希作为示例,实际情况下可能需要根据具体需求处理
dst_uuid = str(uuid.uuid5(uuid.NAMESPACE_DNS, dst_name))
# 提取 `action` 并获取第一项
actions = record.get('action', '').split(' | ')
operation_type = actions[0] if actions else None
# 截取 `backend_timestamp` 到秒
backend_timestamp = record.get('backend_timestamp', '')
timestamp = backend_timestamp.split('.')[0] # 截取到秒
# 构造结果字典
processed_record = {
'src_uuid': src_uuid,
'src_name': src_name,
'dst_name': dst_name,
'dst_uuid': dst_uuid,
'operation_type': operation_type,
'timestamp': timestamp
}
return processed_record
def preprocess_jsonl_file(input_filename, output_filename):
with open(input_filename, 'r') as infile, open(output_filename, 'w') as outfile:
for line in infile:
record = json.loads(line)
processed_record = process_record(record)
if processed_record:
outfile.write(json.dumps(processed_record) + '\n')
# 主程序
if __name__ == "__main__":
input_filename = 'input_dataset.jsonl' # 替换为实际的数据集文件名
output_filename = 'processed_dataset.jsonl' # 替换为处理后数据的文件名
preprocess_jsonl_file(input_filename, output_filename)
在有了脚本后,就可以更换一下,input_filename和output_filename跑了。
2.Kimi
问1:同上
答1:
import json
import uuid
from datetime import datetime
# 假设数据集是一个名为 dataset.jsonl 的文件
filename = 'dataset.jsonl'
# 打开文件并逐行读取
with open(filename, 'r') as file:
for line in file:
# 将每行的JSON字符串转换为字典
data = json.loads(line)
# 检查数据类型是否为 endpoint.event.filemod
if data.get('type') == 'endpoint.event.filemod':
# 提取所需的信息
src_uuid = data.get('process_guid')
src_name = data.get('process_path').replace('\\', '\\\\') # 转义反斜杠
dst_name = data.get('filemod_name')
operation_type = data.get('action').split(' | ')[0] if data.get('action') else None
timestamp = data.get('backend_timestamp').split('.')[0] # 截取到秒
# 将文件名处理成uuid形式
dst_uuid = str(uuid.uuid5(uuid.NAMESPACE_DNS, dst_name))
# 打印提取和处理后的信息
print(f"src_uuid: {src_uuid}")
print(f"src_name: {src_name}")
print(f"dst_uuid: {dst_uuid}")
print(f"dst_name: {dst_name}")
print(f"operation_type: {operation_type}")
print(f"timestamp: {timestamp}")
print("-" * 40) # 分隔线
问2:因为Kimi答的脚步,输出的样式不是我想要的,所以这里我追加一问,试图驯服。
答2:
import json
import uuid
from datetime import datetime
# 假设数据集是一个名为 dataset.jsonl 的文件
filename = 'dataset.jsonl'
output_filename = 'processed_data.csv'
# 打开输出文件并准备写入
with open(output_filename, 'w') as outfile:
# 写入CSV文件的标题行
csv_header = "src_uuid,src_name,dst_uuid,dst_name,operation_type,timestamp\n"
outfile.write(csv_header)
# 打开数据集文件并逐行读取
with open(filename, 'r') as file:
for line in file:
# 将每行的JSON字符串转换为字典
data = json.loads(line)
# 检查数据类型是否为 endpoint.event.filemod
if data.get('type') == 'endpoint.event.filemod':
# 提取所需的信息
src_uuid = data.get('process_guid')
src_name = data.get('process_path')
dst_name = data.get('filemod_name')
operation_type = data.get('action').split('|')[0] if data.get('action') else ''
timestamp = datetime.strptime(data.get('backend_timestamp'), "%Y-%m-%d %H:%M:%S %z").strftime("%Y-%m-%d %H:%M:%S")
# 将文件名处理成uuid形式作为dst_uuid
dst_uuid = str(uuid.uuid5(uuid.NAMESPACE_DNS, dst_name))
# 构建CSV行数据
csv_row = f"{src_uuid},{src_name},{dst_uuid},{dst_name},{operation_type},{timestamp}\n"
# 写入处理后的数据到CSV文件
outfile.write(csv_row)
print(f"Data has been processed and saved to {output_filename}")
五、结果分析
1.ChatGPT 4o mini(PS:这是我之前跑的ChatGPT给的代码,和这个博客中的略有区别,但大体相同,在写博客的时候,存数据集的那个移动硬盘不在身边,所以Kimi的没有测试)
src_name,src_uuid,dst_name,dst_uuid,action,timestamp
c:\program files\vmware\vmware tools\tpautoconnsvc.exe,7DMF69PK-05debeef-000009b8-00000000-1d8984c85f4a992,c:\windows\system32\spool\drivers\w32x86\tp ps driver 642d4d86fc304982923cb27485a07b19.ppd,639f300d-a182-5f56-9154-e0cd0bbd5f4a,ACTION_FILE_CREATE,2022-07-19 07:24:57.2128941 +0000 UTC
c:\windows\system32\spoolsv.exe,7DMF69PK-05debeef-0000055c-00000000-1d8984c843f9f45,c:\windows\system32\spool\drivers\w32x86\3\new\tp ps driver 642d4d86fc304982923cb27485a07b19.ppd,4684e834-7f6b-5834-acd0-a8c8f1668bd6,ACTION_FILE_CREATE,2022-07-19 07:24:57.227895 +0000 UTC
c:\windows\system32\spoolsv.exe,7DMF69PK-05debeef-0000055c-00000000-1d8984c843f9f45,c:\windows\system32\spool\drivers\w32x86\3\new\tp ps driver 642d4d86fc304982923cb27485a07b19.ppd,4684e834-7f6b-5834-acd0-a8c8f1668bd6,ACTION_FILE_MOD_OPEN,2022-07-19 07:24:57.228895 +0000 UTC
c:\windows\system32\spoolsv.exe,7DMF69PK-05debeef-0000055c-00000000-1d8984c843f9f45,c:\windows\system32\spool\drivers\w32x86\3\new\tp ps driver 642d4d86fc304982923cb27485a07b19.ppd,4684e834-7f6b-5834-acd0-a8c8f1668bd6,ACTION_FILE_RENAME,2022-07-19 07:24:57.228895 +0000 UTC
附录(IF 你并不知道如何在Windows上跑Python代码)
我这里使用的anaconda(Anaconda 是一个开源的 Python 和 R 语言的发行版,专为数据科学和机器学习工作流设计。它包括了 Python 解释器、常用的数据科学库(如 NumPy、Pandas、SciPy、Matplotlib)、以及 Conda 包管理器。)
Windows上安装anaconda的方法(下载下安装包,然后安装……这个很简单的,注意的是,anaconda自身是带有Python解释器的,就不大需要再安装Python了,当然如果你要用的Python和anaconda自带的版本不同的话,就要考虑再安装)
官网下载地址:Download Anaconda Distribution | Anaconda
实在不会可以参考这个:手把手教你如何在 Windows 安装 Anaconda - 哔哩哔哩 (bilibili.com)
一些注意事项和我个人使用的时候是怎么弄的(不一定是最好的方法)
1.我应该怎么用anaconda?
一般来说我是直接使用它那个命令行Anaconda Powershell Prompt(如果你要切换目录之类的操作,最好以管理员身份运行),进去后,它刚开始是全黑的,enter一下就好了
然后cd到你存放脚本的目录,python 你的脚本.py 就能够用了
当然我们一般不在base下面跑,一般会create一个环境来跑,像这样:
这个创建环境的过程,一般问啥你就y(yes)就行了
创建好了就是这个样子:
进入我的环境,括号里的内容从base变成了你的环境名就成功了
2.我应该怎么跑我的脚本,报错说缺包怎么办?
假设你不知道要安装什么包,这个时候可以询问AI
例如:
问1:
答1:
因此我们进入我们创建的test环境后,再输出这行指令就行了,具体地为:
conda activate test
conda install tqdm
结束
假设这篇文章能够帮助到你,这会让我十分高兴。