# Malware Analysis Practice1
# 1.1、通过修改注册表添加服务的方式实现自启动
# 实验要求
编写代码,编辑注册表的 Run/RunOnce/RunOnceEx 键(任选其一,并明确三个键的区别),达到让某一程序在系统启动后自动运行的目的(可以以计算器、记事本等作为目标程序)。
以服务方式实现自启动,以 DLL 或者 EXE 方式均可。
# 实验环境
Windows 7 或 Windows 10 主机(虚拟机);
代码编辑器;
C/C++ 代码运行所需环境。
# 实验目的
了解恶意代码自启动常用手段。
# 实验步骤和方法
下面为实现自启动计算器功能代码
1 |
|
可以看到代码成功执行

查看注册表,已经 成功 写入

# Run / RunOnce / RunOnceEx 详细区别与实现
# 详细对比表格
| 特性 | Run | RunOnce | RunOnceEx |
|---|---|---|---|
| 执行时机 | 每次用户登录时 | 下一次用户登录时 | 下一次用户登录时 |
| 执行后处理 | 保留在注册表中 | 自动删除 | 自动删除 |
| 执行顺序 | 无特定顺序 | 按字母顺序执行 | 支持定义依赖关系和顺序 |
| 适用场景 | 常驻程序、守护进程 | 一次性安装、清理任务 | 复杂安装、多步骤配置 |
| 错误处理 | 无特殊机制 | 失败可能重试 | 支持错误处理和回滚 |
# 具体代码实现
# 1. Run 键实现(持久化自启动)
1 |
|
# 2. RunOnce 键实现(一次性执行)
1 |
|
# 3. RunOnceEx 键实现(高级一次性执行)
1 |
|
# 1.2、以服务方式实现自启动,以 EXE 方式。
# 实验步骤和方法
下面为实现以服务方式实现自启动计算器,以 EXE 方式的代码。
1 |
|
链接 advapi32.lib 库后在 Developer Command Prompt for VS 2022 中管理员身份下编译得到 exe
1 | cl FileName.cpp advapi32.lib |
在成功编译后运行 FileName.exe,可以看到服务已经安装成功,但是因为计算器 (calc.exe) 本身不是一个服务程序,是普通 GUI 应用程序,后续应该有特殊的服务入口点和服务控制处理器

查看服务管理器,服务已经安装 成功

# 2.1、DLL 文件编写
# 实验要求
编写一个 DLL,使得在动态加载该 DLL 时,能够弹出 “目标 DLL 已加载” 的对话框。同时,为 DLL 添加两个导出函数,分别实现读取文件并打印出来,以及写入文件的功能,并且能够被其他程序动态调用。
# 实验环境
Windows 7 或 Windows 10 主机(虚拟机);
代码编辑器;
C/C++ 代码运行所需环境。
# 实验目的
了解 DLL 的作用和调用其函数的方法。
# 实验步骤和方法
编写 dll 文件,MyFileDLL.cpp, 并且及时将项目属性改为动态链接库
1 |
|
链接 user32.lib 库后编译代码
1 | cl /LD MyFileDLL.cpp user32.lib |
可以看到成功产生 MyFileDLL.dll/lib 文件,说明编译成功

然后创建测试代码 TestDLL.cpp, 并且在编译后产生 exe
1 |
|
运行 TestDLL.exe,看到已经成功加载

DLL 已经 成功 运行并且调用
1 | D:\SOFEWARE\VS\project\Project1111>TestDLL.exe |
# 2.2、DLL 的作用和调用其函数的方法
# 一、DLL 的作用
# 1.1 什么是 DLL
DLL(Dynamic Link Library,动态链接库) 是包含可由多个程序同时使用的代码和数据的库文件。
# 1.2 主要作用
# 代码共享和重用
1 | // 多个程序可以共享同一个DLL中的函数 |
# 模块化开发
1 | // 将系统分解为独立模块 |
# 节省内存和磁盘空间
- 多个程序共享同一个 DLL 的物理内存副本
- 磁盘上只需存储一份 DLL 文件
# 易于更新和维护
1 | // 更新DLL而不重新编译主程序 |
# 支持多语言开发
1 | // C++编写的DLL可以被C#、VB、Python等调用 |
# 二、DLL 的调用方法
# 2.1 动态加载(显式链接)
# 使用 Windows API 函数
1 |
|
# 动态加载的特点
- 灵活性:运行时决定加载哪个 DLL
- 内存效率:需要时加载,不需要时卸载
- 错误处理:可以处理 DLL 加载失败的情况
- 复杂性:需要手动管理函数指针
# 2.2 静态加载(隐式链接)
# 使用导入库 (.lib)
1 | // 方法1:使用 __declspec(dllimport) |
1 | // 方法2:使用导入库链接 |
# 静态加载的特点
- 简单易用:像调用普通函数一样
- 编译时检查:编译器可以检查函数签名
- 自动加载:程序启动时自动加载 DLL
- 缺乏灵活性:DLL 必须在程序目录或系统路径中
# 三、DLL 的创建方法
# 3.1 导出函数的方法
# 方法 1:使用 __declspec (dllexport)
1 | // MathDLL.h |
# 方法 2:使用模块定义文件 (.def)
1 | // MathDLL.def |
# 3.2 DLL 入口函数
1 |
|
# 四、总结
| 特性 | 动态加载 | 静态加载 |
|---|---|---|
| 加载时机 | 运行时按需加载 | 程序启动时自动加载 |
| 灵活性 | 高,可选择性加载 | 低,必须存在 |
| 复杂性 | 高,需要手动管理 | 低,自动管理 |
| 错误处理 | 可处理加载失败 | 程序无法启动 |
| 内存使用 | 按需使用 | 启动时占用 |
DLL 技术的核心价值:
- 模块化:促进代码组织和团队协作
- 可扩展性:支持插件和功能扩展
- 资源优化:共享代码,减少重复
- 维护便利:独立更新组件
通过掌握 DLL 的创建和调用方法,可以构建更加灵活、可维护的软件系统。
# 3、简单多线程服务器
# 实验要求
编写一个简单的 echo 服务器程序(即:客户端与服务器建立连接后,在客户端输入消息,服务器端就会打印输入的消息),在 4444 端口进行监听。每有一个客户端进行连接时候,服务器创建一个子线程,对客户端程序进行服务。需要引入互斥量对共享代码区或全局变量进行互斥访问,要求使用信号传递等待机制。根据要求,客户端代码也需要自行编写。
# 实验环境
Windows 7 或 Windows 10 主机(虚拟机)至少两台;
代码编辑器;
C/C++ 代码运行所需环境。
# 实验目的
了解恶意代码在通信时,会使用到的最基本的技术。练习多线程编程。
# 实验步骤和方法
在主机和虚拟机上完成 mingw32/64 配置,将 bin 加入环境变量
以主机作为服务器端完成
服务器端代码
1 |
|
客户端代码
1 |
|
将两端代码进行编译,得到 server.exe 和 client.exe
1 | # 编译服务器 |
-
首先运行服务器:
1
server.exe
-
然后运行客户端(可以在多台机器或同一台机器的多个终端运行):
1
client.exe


可以看到在 server.exe 和 client.exe 运行后, 成功 实现了网络通信

# 核心代码分析
# 线程同步关键代码
1 | // 互斥量保护共享资源 |
# 客户端服务线程
1 | DWORD WINAPI client_handler(LPVOID data) { |
# 程序特点
- 多线程处理:每个客户端连接都在独立的线程中处理
- 互斥量保护:使用
WaitForSingleObject和ReleaseMutex保护共享变量 - 信号等待机制:互斥量提供了线程间的同步
- 错误处理:完善的错误检测和处理机制
- 资源管理:正确关闭 socket 和清理资源
这个程序演示了恶意代码通信时常用的基本技术:网络通信、多线程处理、线程同步