当前位置: 首页 > news >正文

Lab 7-1

今天把恶意代码分析的第七章读完了,然后去做了一个课后实验题,遂想来记录一下

PixPin_2026-04-28_14-14-05

假设一个场景,我们现在真的遇到了这个恶意软件
抛开这个问题
我们尝试分析一下
1.首先查壳,程序无壳
2.IDA分析
首先查看导入表,看看有什么有意思地方
PixPin_2026-04-28_14-20-42
PixPin_2026-04-28_14-21-27
PixPin_2026-04-28_14-22-50

我们可以看到有关于网络、服务、线程以及互斥量的相关API,还有一些其他的有趣函数比如Sleep,程序可能在哪里休眠了

我们再去查看一下字符串列表,看看能不能获取什么有趣的消息
PixPin_2026-04-28_14-26-30

我们先回到Main函数
PixPin_2026-04-28_14-27-51

很简短
主要调用了两个函数
StartServiceCtrlDispatcherA我们以前没见过,使用我们需要查文档
打开msdn
对于函数的解释是这样的: 将服务进程的主线程连接到服务控制管理器,这会导致线程成为调用进程的服务控制调度程序线程。
(吐槽: msdn很多解释我真的看不大明白。。。比较难理解,可能是我水平问题)
我猜测可能就是创建了一个服务

BOOL StartServiceCtrlDispatcherA([in] const SERVICE_TABLE_ENTRYA *lpServiceStartTable
);

函数的参数是一个结构体

typedef struct _SERVICE_TABLE_ENTRYA {LPSTR                    lpServiceName;LPSERVICE_MAIN_FUNCTIONA lpServiceProc;
} SERVICE_TABLE_ENTRYA, *LPSERVICE_TABLE_ENTRYA;

我们需要关系的
lpServiceName 要在此服务进程中运行的服务的名称。
lpServiceProc 指向 ServiceMain 函数的指针。
(感觉有点像线程创建函数,需要传一个函数指针)
PixPin_2026-04-28_14-36-46
我们可以判断创建的服务函数就是sub_401040

接下来我们分析sub_401040

PixPin_2026-04-28_14-39-25

OpenMutexA 打开名为HGL345的互斥体
成功打开则退出程序,失败则说明没有名为HGL345的互斥体,根据程序的执行,跳转到创建名为HGL345的互斥体的相关处理
根据书中的知识和我之前学习的知识,互斥体的使用往往涉及到进程或线程之间资源的竞争,线程进程里面有一个概念叫死锁
死锁是指两个或两个以上的进程或线程在执行过程中因相互等待资源而导致所有相关执行单元无法继续执行的阻塞状态。

PixPin_2026-04-29_19-21-57

OpenScCManagerA()我没先前没接触过,所以去查msdn
OpenSCManagerA 用于连接到指定计算机上的服务控制管理器(SCM)并打开其数据库,从而可以对系统服务进行创建、删除、启动、停止等操作。它是 Windows 服务管理 API 的入口函数之一。
可以确定应该是和服务有关的操作
GetCurrentProcess获取当前进程的伪句柄
这里有一个疑问,返回值是一个伪句柄,表示当前进程,但是后面eax直接被复制了,所以这里为什么要获取,并没有使用

GetModuleFileNameA则是获取当前模块的路径
这里我们也可以简单测试一下

#include <windows.h>
#include <stdio.h>
char str[200];
DWORD nSize = 200;
int main()
{GetModuleFileNameA(NULL,str,nSize);printf("%s", str);return 0;
}

PixPin_2026-04-29_19-35-23

PixPin_2026-04-29_19-36-05
CreateServiceA 创建服务对象并将其添加到指定的服务控制管理器数据库。

我们分析一下这个函数的参数

.text:0040109A push    0                     ; lpPassword lpServiceStartName 参数指定的帐户名的密码。
.text:0040109C push    0                     ; lpServiceStartName 运行服务的帐户的名称。
.text:0040109E push    0                     ; lpDependencies
.text:004010A0 push    0                     ; lpdwTagId  指向变量的指针,
.text:004010A2 lea     ecx, [esp+414h+Filename] 
.text:004010A6 push    0                     ; lpLoadOrderGroup 此服务所属的加载排序组的名称。
.text:004010A8 push    ecx                   ; lpBinaryPathName 服务二进制文件的完全限定路径。
.text:004010A9 push    0                     ; dwErrorControl 启动程序将忽略错误并继续启动操作。
.text:004010AB push    2                     ; dwStartType 服务启动选项。
;SERVICE_AUTO_START  0x00000002  服务控制管理器在系统启动期间自动启动的服务。 有关详细信息,请参阅 自动启动服务。
.text:004010AD push    10h                   ; dwServiceType   服务类型
;SERVICE_WIN32_OWN_PROCESS 0x00000010    在其自己的进程中运行的服务
.text:004010AF push    2                     ; dwDesiredAccess 对服务的访问权限。 
;| SC_MANAGER_CREATE_SERVICE (0x0002) | 调用 CreateService 函数以创建服务对象并将其添加到数据库是必需的。
.text:004010B1 push    offset DisplayName    ; "Malservice"    用户界面程序用于标识服务的显示名称。
.text:004010B6 push    offset DisplayName    ; "Malservice" 要安装的服务的名称。
.text:004010BB push    esi                   ; hSCManager  服务控制管理器数据库的句柄,OpenSCManagerA的返回值
.text:004010BC call    ds:CreateServiceA     ; 创建服务对象并将其添加到指定的服务控制管理器数据库。

说明一下这个函数在做什么
简单来说,解释以当前路径创建一下能在系统启动期间自行启动的服务

我们接着往下看
PixPin_2026-04-29_19-50-18
SystemTimeToFileTime 将系统时间转换为文件时间格式。 系统时间基于协调世界时 (UTC) 。

BOOL SystemTimeToFileTime([in]  const SYSTEMTIME *lpSystemTime,[out] LPFILETIME       lpFileTime
);

函数的参数是两个结构体指针

typedef struct _SYSTEMTIME {WORD wYear;WORD wMonth;WORD wDayOfWeek;WORD wDay;WORD wHour;WORD wMinute;WORD wSecond;WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;

大概的作用就设置一个系统时间,比如说现在的时间2026/4/29 然后转化为类似PE时间戳的文件时间,但是这里是16字节,时间戳好像是8字节

CreateWaitableTimerA 创建一个等待的计时器对象
SetWaitableTimer 激活指定的可等待计时器。 当到期时间到达时,计时器将发出信号
WaitForSingleObject 等待指定的对象处于信号状态或超时间隔过

这三个函数一言以蔽之,就是说创建了一个2100年的计数器对象,然后激活,激活之后等`待,根据函数返回值进行后续判断
在此写一个小玩具验证一下吧

#include <stdio.h>
#include <windows.h>int main()
{SYSTEMTIME sysTime;FILETIME fileTime;GetSystemTime(&sysTime);sysTime.wSecond += 5;SystemTimeToFileTime(&sysTime, &fileTime);HANDLE HTime = CreateWaitableTimerA(0,0,0);SetWaitableTimer(HTime, (LARGE_INTEGER*)(&fileTime), 0, 0, 0, 0);;DWORD retCode = WaitForSingleObject(HTime, INFINITE);if (retCode == 0xFFFFFFFF){printf("接收失败!");return 0;}printf("Time Machine Completed!!!!!!!!!");return 0;
}

这一段代码就是获取当前系统的时间,然后设置为5秒后激活,成功则打印
Time Machine Completed!!!!!!!!!
到此我们也进行到了最后一步
PixPin_2026-05-04_14-06-40
如果计数器被激活则跳转到0x0040111A
此处的后续代码很简单,就是创建了20次线程
我们进到线程函数里面分析一下,这个线程函数做了什么事

PixPin_2026-05-04_14-10-47
此处我们直接把书本里面的解释拿出来
PixPin_2026-05-04_14-15-36
这个线程函数的功能就是初始化互联网连接,然后访问http://www.malwareanalysisbook.com这个网站
这里需要注意一点,这个访问网站的部分是一个死循环,没有退出条件
到此整个程序就分析的差不多了

我们现在回到课后实验的问题
PixPin_2026-05-04_14-29-42

  1. 以创建自启动服务的方式实现持久化驻留
  2. 在互斥体分析处详细说明了,保证一次只有一个进程运行

PixPin_2026-05-04_14-35-23
3. HGL345的互斥体,创建的MalService服务
4. 初始化互联网连接后,访问http://www.malwareanalysisbook.com
5. 创建应该可以自启动的名为MalService的服务,然后设置了应该定时器信号,如果时间信号激活,就创建进程的处理,然后访问指定的网址,否则就执行Sleep函数休眠。
6. 不会完成,线程访问网站的部分是一个死循环,没有退出条件

总结

先前我并没有太多分析给恶意代码程序的经历,我为数不多的练习应该就是书本后面的Lab实验题,在刚开始分析的时候,我其实并不知道该怎么下手,感觉就是不知所措,我就是不知道该做什么,感觉脑袋空空的,我感觉知识和实践很割裂,就是学了知识,但是做不出来,不太会用,我真的承认我的想法和思路真的很糟糕,我个人还是比较喜欢尝试的,所以一般但是经过思考然后才会去看答案的分析和别人博客的分析,然后我就知道自己的问题了,方法上的,思路上的等等,这次记录本质是就是一次重做,也算是记录一下过程吧,感觉CrackMe和恶意代码分析还是有些许区别的,但本质上差不多。
额,今天都5.4了吗,来一句迟到的五一快乐。

http://www.jsqmd.com/news/751347/

相关文章:

  • 告别龟速下载!在统信UOS上为Anaconda和pip一键配置清华镜像(2024最新)
  • 机器学习 单变量线性回归模型
  • 如何让GitHub完美显示数学公式:5步安装MathJax插件的完整指南
  • 3分钟解决Minecraft模组语言障碍:MASA全家桶汉化包终极指南
  • 深度解析虚幻引擎多玩家会话管理:5大架构优势与实战应用指南
  • ThinkPHP 路由规则定义后访问 404 找不到模块怎么排查?
  • 5分钟搞定!Obsidian终极图表插件安装指南:让笔记可视化更简单 [特殊字符]
  • 从反向代理到镜像站点:构建稳定AI服务访问的技术实践
  • STM32F103C8T6驱动直流电机:DRV8833的两种PWM接线方案详解与代码实战
  • DeepSeek V4,我在做项目和写软著材料时,顺手用了一段时间
  • AI Weekly 4.27-5.3
  • 别再只用setTimeout了!Vue 3中实现打字机效果的3种更优雅方案(含Composition API实战)
  • 开源GPS自行车码表DIY指南:5个步骤打造专业级离线地图骑行设备
  • ComfyUI TensorRT深度解析:如何实现300% AI绘图加速与专业级性能优化
  • 5分钟上手BilibiliDown:新手也能轻松掌握B站视频下载技巧
  • 暗黑2存档编辑器完全指南:从零开始掌握d2s-editor的5大核心功能
  • Redis缓存三兄弟:雪崩、击穿、穿透的终极防御指南
  • .NET Windows桌面运行时:3个步骤构建现代化Windows应用
  • 技术 JV 的数据主权:接口契约与多租户隔离实践
  • 如何让Windows电脑成为AirPlay 2接收器:完整技术实现指南
  • 通过taotoken模型广场快速对比不同模型的回复效果与风格
  • 从账单明细观测API调用失败产生的token消耗情况
  • 单细胞分析终极指南:SCP完整教程让科研新手也能轻松掌握
  • 莫比乌斯案
  • 如何高效实现1025帧长视频生成:ComfyUI-WanVideoWrapper低显存实战指南
  • Qt5.14.2实战:手把手教你为QML应用添加中英文切换(附完整源码)
  • ProRes技术:优化Transformer预训练的渐进残差预热方法
  • 独立开发者如何借助Taotoken低成本试验不同大模型API效果
  • 免费音频转换终极指南:fre:ac让你5分钟掌握专业级音乐处理
  • CQUPT 2025级 数据科学与大数据技术英才班 周测#04