使用导入表和深度神经网络的自动化 PE32 威胁分类






4.90/5 (8投票s)
在本研究中,我们将证明导入地址表对于恶意软件的分类非常有帮助。
Github 存储库
代码、数据集和文档可在 https://github.com/VISWESWARAN1998/Malware-Classification-and-Labelling 找到。
引言
恶意软件分析可帮助研究人员了解恶意软件的功能。恶意软件分析主要包含两种类型
- 静态恶意软件分析
- 动态恶意软件分析
静态恶意软件分析
- 静态恶意软件分析的首要目标是在不实际运行恶意软件的情况下对其进行分析。
- 它会提供基本见解,但对于复杂的恶意软件会失效。
动态恶意软件分析
- 恶意程序在受控和隔离的环境(如虚拟机)中执行,并对其属性进行分析。
- 尽管它能提供详细的见解,但即使使用自动化工具,分析单个恶意软件也需要大量时间。
关键词:Windows、恶意软件、静态恶意软件分析、动态恶意软件分析、C++、Python、神经网络
导入地址表
导入地址表是可执行文件中的一个节,用于存储可执行文件使用的所有导入函数的地址。
导入地址表包含可执行文件使用的函数信息。这些函数可以帮助您识别恶意软件的某些功能。
以下是一个二进制文件使用的部分函数示例
CredFree
SetSecurityDescriptorDacl
InitializeSecurityDescriptor
CryptDestroyKey
CryptGenKey
CryptEncrypt
CryptImportKey
CryptSetKeyParam
CryptReleaseContext
CommandLineToArgvW
SHGetFolderPathW
正如您所见,像 CryptEncrypt
这样的函数将加密数据,这表现出勒索软件的特性。因此,我们可以使用这些函数来做出预测。通常,未打包的可执行文件包含大量 Import
函数,但只有少数 Import
函数对恶意软件的意图有贡献。我们无法编写有效的条件语句来解决这个问题。因此,我们将使用深度学习模型来解决此类问题。
恶意软件类型
我们将恶意软件分为八种不同类型,如下所述。标签是我们将用于分类的因变量。
表 1
样本类型 | Label |
后门 | 0 |
下载器 | 1 |
键盘记录器 | 2 |
矿工 | 3 |
勒索软件 | 4 |
流氓软件 | 5 |
木马 | 6 |
蠕虫 | 7 |
1. 后门
后门是一种恶意程序,允许远程攻击者访问受害者的计算机。
2. 下载器
下载器的唯一目的是下载另一个恶意程序,有时还会执行它。
3. 键盘记录器
键盘记录器是一种持续监控用户击键的程序。这有助于攻击者窃取电子邮件地址、密码等敏感信息。
4. 矿工
这种恶意程序将使用受害者计算机的资源来挖掘加密货币,用于将其变现给攻击者的钱包。
5. 流氓软件
流氓软件看起来像原始软件(例如反病毒软件),会欺骗用户购买服务,最终将钱支付给攻击者。
6. 木马
木马是一种软件,看起来像合法程序,但在后台执行恶意活动。
7. 勒索软件
一种恶意程序,它会加密用户的文件(图片、文档等),并要求支付赎金才能解密。赎金通常通过比特币、达世币等加密货币收取。
数据集准备
1. 样本采集
为了准备我们的数据集,我们需要实际的恶意软件样本。各种恶意软件样本已从开源 GitHub 存储库收集,主要来自 Virus Share [2] 和 VirusSign。这些存储库已经对大多数恶意软件进行了分类,将用于监督学习。
收集的所有样本都已收集、手动分析并根据恶意软件的类别存储在单独的目录中,这有助于恶意软件的标记。收集的样本类别及其标签如表 1 所示。
2. 提取导入函数
为了准备我们的数据集,我们需要提取恶意软件使用的所有 Import
函数。编写了一个小型 C++ 程序,用于提取目录中所有 PE32 文件中的所有导入。MD5 散列用于防止数据重复。最初,程序将创建三个单独的文件:一个文件用于存储扫描过的恶意软件的散列,用于防止数据重复;一个单独的文件用于存储同一类别所有可执行文件使用的导入;第三个文件用于在 PE32 使用了打包器 [9] – UPX [8] 时发出通知,根据 [14] UPX 是最广泛使用的打包器,而不是自定义打包器。
打包的程序将不用于数据集准备,但会存储在一个单独的文本文件中以供识别。该程序还为每个 PE32 可执行文件创建单独的文件,其中包含其导入及其散列名称。
打包器是一种加密实际程序源代码的程序,当程序被打包时,字符串的大小会减小,导入函数会减少,可执行文件的大小也会减小。当执行打包的可执行文件时,打包器程序首先运行,然后解密可执行文件以执行。打包器也用于合法目的,通过减小可执行文件的大小来节省带宽。
最著名和最常用的打包器是 UPX,它是一个在 GPL 许可下的开源工具,能够压缩可执行文件。
打包的恶意软件可以规避基于签名的检测。例如:基于散列的检测。打包后的可执行文件的散列与原始可执行文件的散列不同。
以下是提取导入的算法,
算法 1:导入提取
for malware in directories
if malware == scanned:
skip
else if malware == packed:
append packed.txt -> malware_hash
skip
imports = get_all_imports(malware)
write malware_hash.txt -> imports
append frequency.txt -> imports
append scanned_file.txt -> malware_hash
预处理过程的可视化表示
后门
后门为远程攻击者提供了访问受害者计算机的权限。从图中,我们可以看到后门对受感染系统中的进程、线程和文件系统拥有完全访问权限。
后门中值得注意的函数导入
函数名 | 描述 |
CreateFile | 创建新文件。 |
GetProcAddress | 用于导入 PE 头中导入的函数之外的其他函数。[15] |
GetTickCount | 此函数不带参数,并返回系统启动后的毫秒数。非常有效的反调试技术,用于检测恶意软件是否在虚拟机中运行。 |
VirtualAlloc | 可用于进程注入。[15] |
这是我们收集的后门样本的频率分布图。
下载器
下载器的唯一目的是下载其他恶意软件。正如您所见,它使用函数为恶意软件创建新文件。Sleep 函数使恶意软件在指定的固定时间内休眠,这通常会减慢动态恶意软件分析的速度,因为在恶意软件不活跃时无法分析其特征。
下载器中值得注意的函数
函数名 | 描述 |
| 用于将下载的有效载荷保存在受害者计算机中 |
| 反调试技术 |
下载器样本的频率分布图
键盘记录器
键盘记录器将记录击键,用于窃取用户凭证。键盘函数是键盘记录程序的主要目标。
键盘记录器中值得注意的函数
函数名 | 函数描述 |
| 用于存储日志。 |
加密货币矿工
加密货币是一种数字货币,难以挖掘且易于验证。挖掘加密货币需要巨大的计算资源。在传统计算机上挖掘著名的加密货币现在是一项非常无利可图的任务,因为资源使用和电力消耗的成本将高于实际挖掘的货币价值。因此,矿工们想出了一个在矿池中挖掘的新方法,即:连接到矿池的每台计算机都会完成一项工作,并根据挖掘到的好份额获得奖励。矿池和加密货币矿工本身并不是恶意软件,但恶意软件作者利用这种方法使用受害者计算机在受害者不知情的情况下挖掘加密货币。这些恶意矿工将利用受害者计算机的资源来挖掘加密货币,这些加密货币将贡献给恶意软件作者的矿池。从而,恶意软件作者从中获利。通常,在使用矿池时,矿工需要稳定的互联网连接(尽管它不消耗太多带宽)来检查池中的其他人是否已经完成了工作。因此,我们可以看到与互联网相关的 Windows 调用频率很高。由于用于挖掘的许多资源会增加利润,因此恶意软件会尝试使用尽可能多的资源来提高恶意软件作者的利润。这可以通过多线程来实现,您可以看到多线程功能的频率也很高。
加密货币矿工中使用的值得注意的函数
函数名 | 函数描述 |
| 反调试技术 |
| 主要处理 HTTP 请求 |
| 处理多线程 |
加密货币矿工的频率分布图
勒索软件
众所周知,勒索软件是一种恶意软件,它使用加密算法加密用户的数据,即文件。通常,并非所有文件(如 DLL、EXE、SYS)都会受到影响。因此,它通常会扫描计算机上适合加密的文件,如文档、图片等。在加密过程中,勒索软件会从受害者系统中读取文件,并用加密数据覆盖原始数据。我们可以看到“ReadFile
”和“WriteFile
”以及其他一些与文件相关的 Windows API 函数的频率较高。
勒索软件使用的值得注意的函数
函数名 | 函数描述 |
CreateThread | 创建新线程 |
| 用于用加密数据覆盖文件 |
勒索软件的频率分布图
流氓软件
这些软件会欺骗或吓唬用户,让他们以为计算机已被感染,并让用户购买潜在不需要的程序。
木马
木马是一种恶意软件,它会向用户隐藏其真实意图,让用户相信他或她正在运行一个合法的程序。
木马使用的值得注意的函数
函数名 | 函数描述 |
| 能够读写文件 |
| 能够访问 Windows 注册表 |
GetProcAddress | 用于导入 PE 头中导入的函数之外的其他函数。[15] |
蠕虫
蠕虫通过网络、电子邮件等传播其副本,其中包含恶意载荷。
蠕虫使用的值得注意的函数
函数名 | 函数描述 |
| 拥有对文件系统的完全访问权限以复制其副本 |
| 拥有对进程的访问权限 |
编译数据集
为了创建我们的数据集,我们需要首先创建其头文件,这在监督学习中用于识别自变量和因变量。通常,我们只需要 Windows 调用,因为许多其他函数因恶意软件而异。Windows 函数调用遵循匈牙利命名法,因此我们将删除不遵循匈牙利命名法的函数调用。唯一的例外是 Berkeley 兼容套接字,恶意软件主要使用这些套接字 [15]。
到目前为止,我们只有单个数据,我们仍然需要将数据(数据集合)与恶意软件标签一起编译成数据集。Import
函数(具有 1728 个特征)用作列名,再加上一个附加列用于包含恶意软件的类型(范围从 0-6)。要生成数据集的行,将迭代每个恶意软件,如果存在 Import
函数,则将该列标记为 1
,如果不存在,则标记为 0
。最后一列将标记为恶意软件的类型。
词干提取是将单词转换为其词根形式。我们将在编译到数据库之前对所有导入执行词干提取。下图是示例
CreateFile
和 CreateFileA
的功能大致相同,因此对函数进行词干提取将提高模型的性能。通过词干提取,我们将 2238 个特征减少到 1858 个。
C++ 程序,用于编译 freqdict 生成的频率文件以生成我们数据集的头
// SWAMI KARUPPASWAMI THUNNAI
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <experimental/filesystem>
#include <fstream>
class header_compiler
{
public:
header_compiler();
void compile();
private:
std::vector<std::string> frequency_file;
std::set<std::string> function_set;
bool check_file_existense();
bool is_string_hungarian(std::string function_name);
bool does_string_has_special_char(std::string function_name);
void add_to_omitted(std::string func_name);
std::string stem(std::string function_name);
};
header_compiler::header_compiler()
{
// Load all the frequency files
frequency_file.push_back("backdoor/frequency.txt");
frequency_file.push_back("downloader/frequency.txt");
frequency_file.push_back("keylogger/frequency.txt");
frequency_file.push_back("miner/frequency.txt");
frequency_file.push_back("ransom/frequency.txt");
frequency_file.push_back("rouge/frequency.txt");
frequency_file.push_back("trojan/frequency.txt");
frequency_file.push_back("worm/frequency.txt");
std::cout << "[$] Loaded all the frequency files!\n";
}
bool header_compiler::check_file_existense()
{
std::vector<std::string>::iterator itr1 = frequency_file.begin();
std::vector<std::string>::iterator itr2 = frequency_file.end();
for (std::vector<std::string>::iterator itr = itr1; itr != itr2; ++itr)
{
if (!std::experimental::filesystem::exists(*itr)) return false;
}
return true;
}
bool header_compiler::is_string_hungarian(std::string function_name)
{
if (function_name.size() > 0)
{
if (isupper(function_name[0])) return true;
}
return false;
}
bool header_compiler::does_string_has_special_char(std::string function_name)
{
for (char ch : function_name)
{
if (ch == '$') return true;
else if (ch == '@') return true;
else if (ch == '[') return true;
else if (ch == ']') return true;
else if (ch == '%') return true;
}
return false;
}
void header_compiler::compile()
{
if (!check_file_existense())
{
std::cout << "[$] A FILE IS MISSING.\n";
return;
}
for (std::string file : frequency_file)
{
std::ifstream loader;
loader.open(file);
if (loader.is_open())
{
std::cout << "[$] Loading: " << file << "\n";
while (!loader.eof())
{
std::string function;
std::getline(loader, function);
if (!is_string_hungarian(function))
{
// Only add lower case functions
// if it's berkely compatible socket functions.
if(function == "send") function_set.insert(function);
else if(function == "recv") function_set.insert(function);
else if(function == "connect") function_set.insert(function);
else if(function == "accept") function_set.insert(function);
else if (function == "listen") function_set.insert(function);
else if (function == "bind") function_set.insert(function);
else if (function == "socket") function_set.insert(function);
else if (function == "getsockname") function_set.insert(function);
else if (function == "closesocket") function_set.insert(function);
else if (function == "nthos") function_set.insert(function);
else if (function == "htons") function_set.insert(function);
else if (function == "inet_ntoa") function_set.insert(function);
else if (function == "inet_addr") function_set.insert(function);
else if (function == "getservbyname") function_set.insert(function);
else if (function == "gethostbyname") function_set.insert(function);
else if (function == "gethostbyaddr") function_set.insert(function);
else add_to_omitted(function);
}
else if (does_string_has_special_char(function)) add_to_omitted(function);
else
{
if (function.size() > 0)
{
std::string stemmed_function = stem(function);
if(stemmed_function.size() > 0) function_set.insert(stemmed_function);
}
}
}
loader.close();
}
}
std::ofstream file;
file.open("header.txt");
if (file.is_open())
{
for (std::string function_name : function_set)
{
file << function_name << "\n";
}
file.close();
}
}
void header_compiler::add_to_omitted(std::string func_name)
{
std::ofstream file;
file.open("omitted.txt", std::ios::app);
if (file.is_open())
{
file << func_name << "\n";
file.close();
}
}
std::string header_compiler::stem(std::string function_name)
{
std::string stemmed = "";
if ((function_name[function_name.size() - 1] == 'A') ||
(function_name[function_name.size() - 1] == 'W'))
{
for (int i = 0; i < function_name.size() - 1; i++)
{
stemmed += function_name[i];
}
std::ofstream file;
file.open("stemmed.txt", std::ios::app);
if (file.is_open())
{
file << function_name << " is stemmed to: " << stemmed << "\n";
}
}
else stemmed = function_name;
return stemmed;
}
int main()
{
header_compiler compiler;
compiler.compile();
std::cout << "Completed!";
int stay;
std::cin >> stay;
}
最终我们的数据集编译器
# SWAMI KARUPPASWAMI THUNNAI
import glob
import csv
def initialize():
with open("header.txt", "r") as file:
headers = file.readlines()
headers = [header.strip() for header in headers]
headers = list(filter(None, headers))
headers.append("RESULT")
return headers
def add_row(row):
with open("dataset.csv", "a", newline="") as file:
writer = csv.writer(file)
writer.writerow(row)
def add_directory(dir_location, result, header):
global compiled_files, omitted_files
files = glob.glob(dir_location+"/*.txt")
for file in files:
if "packed.txt" in file:
print("Omitted Packed")
elif "frequency.txt" in file:
print("Omitted Frequency")
elif "scanned_hash.txt" in file:
print("Omitted Scanned Hash")
else:
row = [0 for i in range(len(header))]
row[len(header)-1] = result
with open(file, "r") as func_file:
print("[*] COMPILING: ", file)
functions = func_file.readlines()
functions = [function.strip() for function in functions]
functions = list(filter(None, functions))
if len(functions) > 5:
for function in functions:
if function[len(function)-1] == "W":
print("Stemming ", function, " To: ", function[:-1])
function = function[:-1]
if function[len(function)-1] == "A":
print("Stemming ", function, " To: ", function[:-1])
function = function[:-1]
try:
row[header.index(function)] = 1
except ValueError:
print(function, " is omitted!")
compiled_files += 1
add_row(row)
else:
print(file, " is omitted!")
omitted_files += 1
print(compiled_files, omitted_files)
if __name__ == "__main__":
header = initialize()
add_row(header)
compiled_files = 0
omitted_files = 0
add_directory("backdoor", 0, header)
add_directory("downloader", 1, header)
add_directory("keylogger", 2, header)
add_directory("miner", 3, header)
add_directory("ransom", 4, header)
add_directory("rouge", 5, header)
add_directory("trojan", 6, header)
add_directory("worm", 7, header)
数据集准备方式的可视化表示
二、相关工作
- 论文 [3] 将恶意二进制文件实际执行在沙盒环境中,并生成行为报告。
- 论文 [4] 使用传统和循环神经网络来分类恶意软件,但它在受保护的环境中执行恶意软件。监督学习所需的标签已从 Virus Total API 获取。
- 论文 [7] 使用深度学习来分类良性和恶意移动应用程序(Android)。提取了 202 个特征,包括权限、敏感 API 调用和动态行为。此处使用的深度学习模型非常有趣。一个半监督模型,在预训练阶段(无监督)使用受限玻尔兹曼机(RBM),然后是常规的监督反向传播阶段。
- 论文 [10] 提出了一种基于最大公共子图检测问题的新恶意软件分类技术。
- 论文 [11] 提取各种特征,如字节熵、PE 元数据、字符串和导入特征。该论文使用神经网络来分类文件是良性的还是恶意的。DNN 的架构有一个输入层,两个隐藏层和一个输出层。隐藏层中使用的激活函数是 Parametric ReLU。输出层中使用的激活函数是 sigmoid 激活函数,因为这是一个二元分类问题。
- 论文 [12] 使用基于 N-gram 的签名生成技术进行恶意软件检测。提取每个文件的 N-gram,用于生成用于检测恶意软件的签名。
- 论文 [13] 使用来自导入地址表的 Windows API 调用,这与我们检测零日恶意软件的方法类似。该论文尝试了 8 种不同的分类器:KNN、NB、神经网络–反向传播、SVM 归一化多项式核、SVM 多项式核、SVM Puk、SVM 径向基函数(RBM)。在 8 种分类器中,SVM 归一化多项式核表现最好,准确率为 98%,而神经网络表现最差,准确率约为 78%。这同样是一个二元分类恶意软件,即分类文件是恶意软件还是良性。
在大多数工作中,恶意软件实际上是被执行的,这会减慢整个过程,因为一次只能运行一个恶意软件来生成有效数据。在我们的案例中,导入的提取无需执行恶意软件,因此可以批量标记大量恶意软件。
构建系统所用的组件
本文广泛使用两种主要编程语言
- C++ 14 – Visual Studio 编译器
- 64 位 Python 3.6
大部分导入提取、预处理和准备将导入编译成数据所需的数据都是使用 C++ 完成的。Python 用于可视化和构建实际的深度学习模型。我们使用 Matplotlib 进行图形可视化,使用 TensorBoard 构建架构图。深度学习模型使用 Keras 和 TensorFlow 后端构建。
此处使用的主要工具和库是
Jupyter Notebook | 用于编程深度学习模型 |
Pandas | 加载数据集 |
Numpy | 用于数值处理 |
Keras [16] 和 TensorFlow | 深度学习库 |
Matplotlib | 图形可视化 |
训练我们的模型
准备好数据集后,我们就可以训练模型了。我们的模型包含 1953 个输入特征。除输出层外,所有层的激活函数是 ReLU,也称为 Rectified Linear Unit,一种非线性激活函数,当输入为负数时输出 0,否则输出相同输入。
这是 ReLU 输出示例输入范围从 -10
到 10
。
前馈神经网络模型包含一个输入层、两个隐藏层和一个最终输出层,每个层都使用 ReLU 作为其激活函数,并带有 20% 的 Dropout [5]。模型经过 150 个 epoch 的训练,达到了 70% 以上的准确率。我们使用 Adam [6] 优化器来降低损失函数。
我们的模型架构
输入层以 one-hot 编码格式接收 1858 个导入表函数的特征。第一个密集层有 1000 个单元,使用偏差和 ReLU 作为激活函数。第一个密集层应用 20% 的 Dropout。第二个密集层与第一个类似,但只有 750 个单元。第三个有 500 个单元,并使用 ReLU 激活函数。最后一个密集层有 8 个单元,并使用 SoftMax 激活函数,这是多类分类常用的激活函数。
这是我们训练模型 100 个 epoch 后的准确率图 – 约 96% 的准确率
以及 150 个 epoch 的损失
四、重要特征分析
数据集有 1858 个特征,即 1858 个维度,并非所有特征在分类恶意软件类型方面都起着主要作用。因此,我们需要一种方法来找出哪些特征在恶意软件分类中起着主要作用。
因此,我们将使用 RFE(递归特征消除)[17] 来消除次要特征。使用 RFE,我们将对数据集中排名前 20 的特征进行排序。我们使用两种监督分类算法,即逻辑回归 – OVR(一对多)和决策树分类器。
以下是两种不同分类器判断出的 20 个重要特征。
逻辑回归 | 决策树分类器 |
CryptReleaseContext | CreateEvent |
ExitThread | CreateFile |
FindNextFile | CreateWindowEx |
FindResource | CryptReleaseContext |
GetAsyncKeyState | EnableWindow |
GetCurrentProcessId | FindNextFile |
GetEnvironmentVariable | GetAsyncKeyState |
GetModuleFileName | GetLastError |
GetModuleHandle | GetShortPathName |
GetStartupInfo | GetVersion |
GetWindowLong | IsDlgButtonChecked |
HeapCreate | MakeSureDirectoryPathExists |
InternetSetOption | MapViewOfFile |
IsClipboardFormatAvailable | OpenProcessToken |
LoadAccelerators | SetClipboardData |
LoadMenu | SetWindowLong |
MakeSureDirectoryPathExists | TlsFree |
SetFilePointer | VariantChangeTypeEx |
UnhandledExceptionFilter | VirtualQuery |
send | closesocket |
五、结论
在本研究中,我们得出的结论是:
- 导入表在恶意软件分类中起着重要作用
- 可以使用深度神经网络自动化恶意软件分类
根据统计数据 [1],每天都会出现数百万种新的恶意软件,在沙盒环境中执行每一种威胁并对其进行分类是不可行的。使用我们的系统,可以批量标记恶意软件,而无需执行它们。
未来,此分类器将与病毒签名生成相结合,以实现对生成签名的有效、可识别的标记。我们还将添加各种已知的打包器来解包 Windows PE32 文件,因为 UPX 并非唯一的可用打包器。
参考文献
- Virus total 统计:https://www.virustotal.com/en/statistics/
- J.-M. Roberts. Virus Share. https://virusshare.com/
- K. Rieck, P. Trinius, C. Willems , T. Holz. Automatic Analysis of Malware Behaviour using Machine Learning.
- B. Kolosnjaji, A. Zarras, G. Webster, and C. Eckert. Deep Learning for Classification of Malware System Call Sequences.
- N. Srivastava, G. Hinton, A. Krizhevsky, I. Sutskever, and R. Salakhutdinov. Dropout: A Simple Way to Prevent Neural Networks from Overfitting. Journal of Machine Learning Research, 15(1):1929{1958, 2014.
- Kingma, Diederik P., and Jimmy Ba. "Adam: A method for stochastic optimization." arXiv preprint arXiv:1412.6980 (2014).
- Yuan, Zhenlong, et al. "Droid-sec: deep learning in android malware detection." ACM SIGCOMM Computer Communication Review. Vol. 44. No. 4. ACM, 2014.
- Oberhumer, M.F., Moln ́ar, L., Reiser, J.F.: UPX: the Ultimate Packer for eXe-cutables (2007), http://upx.sourceforge.net
- Fanglu Guo, Peter Ferrie, and Tzi-cker Chiueh. A Study of the Packer Problem and Its Solutions.
- Park, Younghee, et al. "Fast malware classification by automated behavioral graph matching." Proceedings of the Sixth Annual Workshop on Cyber Security and Information Intelligence Research. ACM, 2010.
- Saxe, Joshua, and Konstantin Berlin. "Deep neural network based malware detection using two dimensional binary program features." 2015 10th International Conference on Malicious and Unwanted Software (MALWARE). IEEE, 2015.
- Santos, Igor, et al. "N-grams-based File Signatures for Malware Detection." ICEIS (2) 9 (2009): 317-320.
- Alazab, Mamoun, et al. "Zero-day malware detection based on supervised learning algorithms of API call signatures." Proceedings of the Ninth Australasian Data Mining Conference-Volume 121. Australian Computer Society, Inc., 2011.
- Morgenstern, Maik, and Hendrik Pilz. "Useful and useless statistics about viruses and anti-virus programs." Proceedings of the CARO Workshop. 2010.
- Sikorski, Michael, and Andrew Honig. Practical malware analysis: the hands-on guide to dissecting malicious software. no starch press, 2012.
- Chollet, François. "Keras." (2015).
- Scikit Learn Docs: https://scikit-learn.cn/stable/auto_examples/feature_selection/plot_rfe_digits.html#sphx-glr-auto-examples-feature-selection-plot-rfe-digits-py
联合作者
1N.Visweswaran, 2M.Jeevanantham, 3C.Thamarai Kani, 4P.Deepalakshmi 5S.Sathiyandrakumar
更多详情可在项目文档中找到。
我已经尽力感谢所有人,有些图片是从互联网上获取的,由于我找不到作者信息,因此没有列出作者,并且没有在论文中使用这些图片。
历史
- 2020-02-02:初始发布
该项目仍处于早期阶段,需要更多样本来进一步证明其立场。