前文探索了利用大模型辅助恶意代码分析,即LLM赋能Lark工具提取XLM代码的抽象语法树。这篇文章将继续尝试探索利用大模型辅助恶意代码分析,尝试进行恶意代码家族分类实验。在恶意代码分析过程中,大家会遇到各种各样的问题,如何结合LLM和GPT完成复杂任务,更好地为安全工程师合作至关重要。基础性探索文章,还请各位大佬多多指教,写得不足之处请海涵。希望您喜欢,且看且珍惜。
文章目录:
- 一.数据预处理
- 1.提取关键特征列
- 2.恶意家族选择预处理
- 二.数据集划分及统计分析
- 三.大模型构建机器学习代码
- 1.随机森林
- 2.其它方法
- 四.传统机器学习代码对比
- 五.评价及总结
作者的github资源:
- 逆向分析:
- 网络安全:
作者作为网络安全的小白,分享一些自学基础教程给大家,主要是关于安全工具和实践操作的在线笔记,希望您们喜欢。同时,更希望您能与我一起操作和进步,后续将深入学习网络安全和系统安全知识并分享相关实验。总之,希望该系列文章对博友有所帮助,写文不易,大神们不喜勿喷,谢谢!如果文章对您有帮助,将是我创作的最大动力,点赞、评论、私聊均可,一起加油喔!
声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。(参考文献见后)
一.数据预处理
假设存在一个恶意代码家族数据集(如恶意软件、APT攻击、Powershell家族、宏代码家族、Android恶意软件、流量攻击类型家族等),该数据集是将恶意软件脱壳、解混淆处理并提取关键特征所生成的数据集,现需要对其进行大模型赋能的安全分析尝试。
1.提取关键特征列
整个数据集包括6列内容,首先需要利用大模型提取关键的前3列特征。
- 第1列:家族名称
- 第2列:文件名称(MD5)
- 第3列:Word字符串特征
- 第4列:Token特征
- 第5列:API行为特征
- 第6列:AST特征
利用大模型构建提取前3列特征的提示词为:
提示1:
输入CSV文件包含6列,第一列为家族名称,第二列为文件名称,第三列为Word特征,第四列为Token特征,第五列为API行为特征,第六列为AST特征,每行对应一个样本。现需要仅保留前3列内容,从上往下顺序依次遍历,最终输出处理后的CSV文件。请给出对应的Python代码。
生成代码如下所示:
# By: Eastmount CSDN 2025-02-02
import pandas as pd
# 读取CSV文件
file_path = "filtered_final_features_with_ast_rela.csv" # 请替换为您的文件路径
df = pd.read_csv(file_path)
# 仅保留前3列
df_filtered = df.iloc[:, :3]
# 保存处理后的CSV文件
output_file = "filtered_final_features_reduced.csv"
df_filtered.to_csv(output_file, index=False)
print(f"处理后的CSV文件已保存为:{output_file}")
输出结果如下图所示,成功提取前3列特征。
2.恶意家族选择预处理
在某些情况下,存在某类家族或类别数据集较少的情况,此时可以通过数据增强或收集更多的样本丰富数据集。另一种比较暴力的方法是进行删除,不建议大家如此,但该博客是对LLM赋能安全分析的尝试,因此进行恶意家族选择处理。提示词如下:
提示2:
请撰写python代码处理CSV文件数据。输入CSV文件“data.csv”包含3列,第一列为家族名称,第二列为文件名称,第三列为Word特征,每行对应一个样本。现在需要仅保留四个家族的数据集,family_features = [“zloader”, “dridex”, “encdoc”, “qakbot”],家族名称为第一列,不在四个家族的数据删除。具体步骤为:与第一列家族名称进行匹配,匹配成功的整行数据保留。需要注意,输入CSV文件从上往下顺序依次不变,请撰写Python代码实现。
# By: Eastmount CSDN 2025-02-02
import pandas as pd
# 指定要保留的家族名称
family_features = ["zloader", "dridex", "encdoc", "qakbot"]
# 读取CSV文件
file_path = "data.csv" # 请确保data.csv在相应目录下
df = pd.read_csv(file_path)
# 仅保留家族名称匹配的行
df_filtered = df[df.iloc[:, 0].isin(family_features)] # 第一列(家族名称)匹配
# 保存处理后的CSV文件
output_file = "filtered_data.csv"
df_filtered.to_csv(output_file, index=False, encoding="utf-8")
print(f"处理后的CSV文件已保存为:{output_file}")
输出结果如下图所示:
二.数据集划分及统计分析
接下来进行数据集划分,机器学习通常划分为训练集和测试集,深度学习还会划分验证集。数据集划分的提示如下:
提示3:
请撰写python代码处理CSV文件数据。输入CSV文件“filtered_data.csv”包含3列,第一列为家族名称,第二列为文件名称,第三列为Word特征,每行对应一个样本。现在需要按照7:3的比例将整个CSV数据集随机划分为训练集和测试集,保证每个家族均按照该比例,输出训练集文件名称为“filtered_data_train.csv”,测试集文件名称为“filtered_data_test.csv”。需要注意,输入CSV文件从上往下顺序依次不变,请撰写Python代码实现。
此代码可确保每个家族都按照7:3的比例分割,并保持数据的原始顺序,适用于分类任务的数据准备。代码说明:
- 按家族(第一列)分组,确保每个家族独立划分训练集和测试集。
- 使用train_test_split():test_size=0.3(即 30% 的数据作为测试集)。random_state=42 确保可复现性。shuffle=True 确保随机性,避免数据分布不均。
- 保持数据的原始顺序:分组时不排序(sort=False),保证原始顺序不变。每个家族分别划分,然后合并训练集和测试集,最终输出文件。
- 生成两个CSV文件:filtered_data_train.csv(训练集)、filtered_data_test.csv(测试集)。
# By: Eastmount CSDN 2025-02-02
import pandas as pd
from sklearn.model_selection import train_test_split
# 读取CSV文件
file_path = "filtered_data.csv" # 输入文件
df = pd.read_csv(file_path)
# 按家族名称进行分组,分别划分训练集和测试集
train_list = []
test_list = []
for family, group in df.groupby(df.columns[0], sort=False): # 按第一列(家族名称)分组,保持顺序
train, test = train_test_split(group, test_size=0.3, random_state=42, shuffle=True) # 7:3划分
train_list.append(train)
test_list.append(test)
# 合并所有家族的数据
train_data = pd.concat(train_list)
test_data = pd.concat(test_list)
# 保存训练集和测试集
train_output = "filtered_data_train.csv"
test_output = "filtered_data_test.csv"
train_data.to_csv(train_output, index=False, encoding="utf-8")
test_data.to_csv(test_output, index=False, encoding="utf-8")
print(f"训练集已保存为:{train_output}")
print(f"测试集已保存为:{test_output}")
输出结果如下图所示:
此外,我们可以统计各家族数量,提示如下:
提示4:
请撰写python代码处理CSV文件数据。输入CSV文件“filtered_data.csv”包含3列,第一列为家族名称,第二列为文件名称,第三列为Word特征,每行对应一个样本。现在需要撰写代码统计各个家族的数量,即第一列。
# By: Eastmount CSDN 2025-02-02
import pandas as pd
# 读取CSV文件
file_path = "filtered_data.csv" # 输入文件
df = pd.read_csv(file_path)
# 统计每个家族的数量
family_counts = df.iloc[:, 0].value_counts()
# 打印统计结果
print(family_counts)
# 可选:保存统计结果到CSV文件
output_file = "family_counts.csv"
family_counts.to_csv(output_file, header=["Count"])
print(f"各个家族的数量统计已保存至:{output_file}")
输出结果如下图所示:
三.大模型构建机器学习代码
接下来我们将利用大模型GPT4o生成机器学习代码来实现恶意家族特征学习和分类。提示如下:
1.随机森林
提示5:
现在需要撰写Python机器学习代码,构建随机森林模型实现文本分类。输入文本为2个CSV文件,训练集“filtered_data_train.csv”、测试集“filtered_data_test.csv”。每个CSV文件包含3列,第一列为家族名称,第二列为文件名称,第三列为Word特征,每行对应一个样本,总共四个家族。现在需要完成:
(1)分别提取CSV文件的第一列家族名称(标题Family),第三列Word特征(标题WordFeature),然后赋值到训练集、测试集中,家族名称作为类别,Word特征作为文本序列,已采用空格连接。
(2)利用Sklearn构建随机森林模型,并进行训练和测试,需将文本表征为TF-IDF再进行训练学习。
(3)最后实现对测试集文件的预测,并给出评估的结果,包括各个家族的精确率、召回率、F1值和准确率。同时将真实列表结果和预测结果存储至CSV文件中,便于后续分析。
生成代码如下所示:
# By: Eastmount CSDN 2025-02-02
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, accuracy_score
# 读取训练集和测试集
train_file = "filtered_data_train.csv"
test_file = "filtered_data_test.csv"
train_df = pd.read_csv(train_file)
test_df = pd.read_csv(test_file)
# 提取家族名称(类别标签)和Word特征(文本数据)
X_train_text = train_df.iloc[:, 2] # 第三列 WordFeature 作为文本输入
y_train = train_df.iloc[:, 0] # 第一列 Family 作为类别标签
X_test_text = test_df.iloc[:, 2]
y_test = test_df.iloc[:, 0]
# TF-IDF 向量化
vectorizer = TfidfVectorizer()
X_train_tfidf = vectorizer.fit_transform(X_train_text)
X_test_tfidf = vectorizer.transform(X_test_text)
# 训练随机森林模型
rf_model = RandomForestClassifier(n_estimators=100, random_state=42)
rf_model.fit(X_train_tfidf, y_train)
# 预测测试集
y_pred = rf_model.predict(X_test_tfidf)
# 评估模型性能
report = classification_report(y_test, y_pred, output_dict=True)
accuracy = accuracy_score(y_test, y_pred)
# 转换评估结果为DataFrame
report_df = pd.DataFrame(report).T
# 输出评估结果
print(f"模型准确率: {accuracy:.4f}")
print("分类评估报告:")
print(report_df)
# 保存预测结果和真实标签
output_results = pd.DataFrame({
"True_Label": y_test,
"Predicted_Label": y_pred
})
output_results.to_csv("prediction_results.csv", index=False, encoding="utf-8")
report_df.to_csv("classification_report.csv", index=True, encoding="utf-8")
print("预测结果已保存至 prediction_results.csv")
print("分类评估报告已保存至 classification_report.csv")
本地运行代码输出结果如下:
并且将预测结果和真实结果存储至CSV文件中,方便后续深入分析。
2.其它方法
提示6:
请将上述代码替换为逻辑回归模型。
生成代码如下:
# By: Eastmount CSDN 2025-02-02
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, accuracy_score
# 读取训练集和测试集
train_file = "filtered_data_train.csv"
test_file = "filtered_data_test.csv"
train_df = pd.read_csv(train_file)
test_df = pd.read_csv(test_file)
# 提取家族名称(类别标签)和Word特征(文本数据)
X_train_text = train_df.iloc[:, 2] # 第三列 WordFeature 作为文本输入
y_train = train_df.iloc[:, 0] # 第一列 Family 作为类别标签
X_test_text = test_df.iloc[:, 2]
y_test = test_df.iloc[:, 0]
# TF-IDF 向量化
vectorizer = TfidfVectorizer()
X_train_tfidf = vectorizer.fit_transform(X_train_text)
X_test_tfidf = vectorizer.transform(X_test_text)
# 训练逻辑回归模型
lr_model = LogisticRegression(max_iter=1000, random_state=42)
lr_model.fit(X_train_tfidf, y_train)
# 预测测试集
y_pred = lr_model.predict(X_test_tfidf)
# 评估模型性能
report = classification_report(y_test, y_pred, output_dict=True)
accuracy = accuracy_score(y_test, y_pred)
# 转换评估结果为DataFrame
report_df = pd.DataFrame(report).T
# 输出评估结果
print(f"模型准确率: {accuracy:.4f}")
print("分类评估报告:")
print(report_df)
# 保存预测结果和真实标签
output_results = pd.DataFrame({
"True_Label": y_test,
"Predicted_Label": y_pred
})
output_results.to_csv("prediction_results.csv", index=False, encoding="utf-8")
report_df.to_csv("classification_report.csv", index=True, encoding="utf-8")
print("预测结果已保存至 prediction_results.csv")
print("分类评估报告已保存至 classification_report.csv")
输出结果如下图所示:
四.传统机器学习代码对比
下面给出作者Eastmount之前习惯撰写的文本分类传统代码,具体如下:
# -*- coding: utf-8 -*-
import os
import csv
import time
import numpy as np
from sklearn import metrics
import matplotlib.pyplot as plt
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA
from sklearn import neighbors
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report
import warnings
start = time.clock()
warnings.filterwarnings("ignore")
csv.field_size_limit(500 * 1024 * 1024)
#---------------------------第一步 加载数据集------------------------
#训练集
file = "filtered_data_train.csv"
label_train = []
content_train = []
with open(file, "r", encoding="UTF-8") as f:
reader = csv.DictReader(f)
for row in reader:
# 数据元素获取 Family, File Name, Word Feature
label_train.append(row['Family'])
content_train.append(row['Word Feature'])
print(label_train[:2])
print(content_train[:2])
#测试集
file = "filtered_data_test.csv"
label_test = []
content_test = []
with open(file, "r", encoding="UTF-8") as f:
reader = csv.DictReader(f)
for row in reader:
label_test.append(row['Family'])
content_test.append(row['Word Feature'])
print(len(label_train),len(label_test))
print(len(content_train),len(content_test))
#---------------------------第二步 向量转换------------------------
contents = content_train + content_test
labels = label_train + label_test
#计算词频
vectorizer = CountVectorizer(min_df=0.05)
X = vectorizer.fit_transform(contents)
words = vectorizer.get_feature_names()
print("特征词数量:",len(words))
#计算TFIDF
transformer = TfidfTransformer()
tfidf = transformer.fit_transform(X)
weights = tfidf.toarray()
#---------------------------第三步 编码转换------------------------
le = LabelEncoder()
y = le.fit_transform(labels)
X_train, X_test = weights[:1312], weights[1312:]
y_train, y_test = y[:1312], y[1312:]
#---------------------------第四步 分类检测------------------------
clf = RandomForestClassifier(n_estimators=3)
clf.fit(X_train, y_train)
pre = clf.predict(X_test)
print(clf)
print(classification_report(y_test, pre, digits=4))
print("accuracy:")
print(metrics.accuracy_score(y_test, pre))
print("Balanced Accuracy:")
print(metrics.balanced_accuracy_score(y_test, pre, adjusted=False))
#结果存储
f1 = open("rf_test_pre.txt", "w")
for n in pre:
f1.write(str(n) + "n")
f1.close()
f2 = open("rf_test_y.txt", "w")
for n in y_test:
f2.write(str(n) + "n")
f2.close()
#计算时间
elapsed = (time.clock() - start)
print("Time used:", elapsed)
输出结果如下图所示:
五.评价及总结
通过上述分析,大模型确实能很好地实现安全分析,并理解作者的提示,而自己撰写的代码甚至存在训练集和测试集同时生成向量、手动划分数据集等局限。大模型在函数定义调用,代码简洁性方面(无冗余代码)存在一定优势,并且有良好的编程及注释习惯。
然而,大模型在脱壳、解混淆、深层次PE文件分析、漏洞挖掘、恶意代码动态分析等方面存在一定局限性,还需要安全专家来辅助,甚至部分较难的深度学习代码还会报错(与电脑环境关联存在一定局限,和提示也有关系)。总而言之,LLM赋能的恶意代码分析非常不错,效果会更佳,且更好地帮助我们解决实际问题。路漫漫其修远兮,后续会结合DeepSeek进行探索,并描述相关安全问题。
最后,我们给出LLM评估两类代码的效果。
提示7:
上述代码是ChatGPT生成的,现上传的Python代码为作者撰写,请比较两个代码的相似性和区别,评估大模型生成该示例代码的结果。
下面内容为ChatGPT生成。
(1)代码相似性
- 数据加载:两者均读取 训练集 (filtered_data_train.csv) 和 测试集 (filtered_data_test.csv)。
均提取 第一列(家族名称)作为标签,第三列(Word特征)作为文本数据。 - 文本特征转换:ChatGPT 代码 采用 TfidfVectorizer() 直接进行 TF-IDF 向量化。
用户代码 (rf-model.py) 先使用 CountVectorizer 计算词频,再用 TfidfTransformer 计算TF-IDF,最终得到权重矩阵。 - 数据预处理:ChatGPT 代码 直接基于 Pandas DataFrame 操作,使用 train_test_split() 进行数据拆分。
用户代码 手动合并 content_train 和 content_test,然后切片 X_train 和 X_test。 - 分类模型:ChatGPT 代码 使用 RandomForestClassifier(n_estimators=100) 并直接 fit() 训练。
用户代码 采用 RandomForestClassifier(n_estimators=3) 训练。 - 模型评估:两者均使用 classification_report() 和 accuracy_score() 计算精确率、召回率、F1-score 及准确率。
用户代码额外计算 Balanced Accuracy(平衡准确率)。 - 结果存储:ChatGPT 代码 将 classification_report 和预测结果存入 prediction_results.csv。
用户代码 将预测结果和真实标签分别存入 rf_test_pre.txt 和 rf_test_y.txt。
(2)主要区别
(3)ChatGPT 生成代码的评价
✅ 优点:
- 代码更简洁:直接使用 Pandas 处理 CSV,避免了 csv.DictReader() 解析 CSV 的额外步骤。
train_test_split() 自动划分数据集,无需手动索引切片 [:1312]。 - 模型更稳定:采用 n_estimators=100 提高随机森林的稳定性,而用户代码仅 n_estimators=3,可能导致模型表现波动较大。
- 文件存储更规范:prediction_results.csv 统一存储 True_Label 和 Predicted_Label,方便后续分析。
classification_report.csv 提供完整的精确率、召回率、F1 值。
❌ 可能的改进点:
- 未计算 Balanced Accuracy Score:
用户代码计算了 Balanced Accuracy,这一指标在 类别不平衡情况下更合理,可在 ChatGPT 代码中添加:
from sklearn.metrics import balanced_accuracy_score
balanced_acc = balanced_accuracy_score(y_test, y_pred)
print(f"Balanced Accuracy: {balanced_acc:.4f}")
- 未存储 rf_test_pre.txt 和 rf_test_y.txt:
ChatGPT 代码存储的是 CSV 结果,而 rf-model.py 代码存储为 TXT 结果。
总之,ChatGPT 生成的代码 结构更清晰、数据处理更规范、模型稳定性更强,但缺少 Balanced Accuracy 计算,且未按用户原始格式存储 TXT 结果。整体而言,大模型生成的代码在工程实践中具备较强的可用性,但仍可优化以符合具体需求。
写到这里,这篇文章就介绍完毕,祝大家新年快乐。基础性文章,希望对您有所帮助,如果存在不足之处还请海涵。行路难,多歧路。感谢家人的陪伴,小珞和小贝最近长大了很多,调皮又可爱。爱你们喔!
原文始发于微信公众号(娜璋AI安全之家):[系统安全] 六十二.恶意软件分析 (13)LLM赋能实现基于机器学习的恶意家族分类(初探)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论