记一次持续化隐藏服务的程序分析
本文最后更新于 2025年5月26日 上午
- 当计算机重启后,这个程序如何确保它继续运行(达到持久化驻留) ?
调用了CreatService函数,创建了一个服务,并设置为开机自启动。
分析过程:

==StartServiceCtrlDispatcherA== 函数将服务进程的主线程连接到服务控制管理器,这会导致线程成为调用进程的服务控制调度程序线程。
它的参数是一个结构体类型的指针

这里传入的第一个参数是一个字符串的指针,定义了服务名为MalService,第二个参数,sub_401040是服务要运行的函数的地址。
进入执行的函数,发现有创建服务

函数原型:
1 | |
- 为什么这个程序会使用一个互斥量?
在函数的开始,使用互斥量,判断该服务是否存在;通过互斥体确保程序唯一运行实例,防止多个服务实例同时运行,避免资源冲突、数据竞争等问题导致服务崩溃。

- 可以用来检测这个程序的基于主机特征是什么?
硬编码的字符串,如HGL345(互斥量的名称)、MalService(运行的服务名称)
- 检测这个恶意代码的基于网络特征是什么?;这个程序的目的是什么
这里使用Internet Explorer 8.0访问了http://www.malwareanalysisbook.com

这个进程的目的:通过无限循环持续发起HTTP请求,用于对目标URL进行拒绝服务攻击(DoS)或资源耗尽攻击。
该服务函数创建了20个线程,每个线程都无限循环发起http请求且连接不终止,且每次都强制从服务器加载,不使用缓存。

- 这个程序的目的是什么?
1 | |
先把SystemTime结构体初始化,将里面的年、月、星期、日、时、分、秒、毫秒都置为0
然后将年份设置为2100年,再将这个事件转化为文件时间,创建一个定时器,触发时间为文件时间,当时间到达时,触发该触发器。
触发后会执行后续的创建线程与dos攻击操作,最后无限休眠,阻止进程正常退出。
- 修改使得绕过时间触发机制运行StartAddress
WaitForSingleObject函数当接收到信号时,返回0;其他的信号80h,102h,0xffffffff分别代表互斥体被遗弃、等待超时、函数调用失败。将接收到信号,因此,将无限等待的时间改为0,此时接收到非0信号,将jnz改为jz

这么做发现无法实现既定逻辑,经调试发现,eax的返回值为0,信号触发了,这不符合逻辑,往调试发现Filetime的值为0,往上调试去看filetotime函数的执行,发现SystemTimeToFileTime执行完之后,Filetime仍然为0


查询后得知,由于月份被置为0,这是一个无效的日期,导致返回了0
调试发现edx异或前就是0,直接+1,使得日期有效。

发现还是无效,查看修改后的伪c代码,month被设置为高位的edx

而汇编是这么显示的,需要将month对应的位置设置为1 ,改为[esp+6]


成功设置为1,但是函数返回还是为0

自行编译了一个符合且能运行的,调试发现正常。

重新patch,将其他部分nop掉

还是不行,仿照下方,直接word字节赋值1

还是不行,猜测edx为1导致的异常,将inc edx nop掉,还是不行。。
直接只把wMonth设置为1,还是不行,因为字节太长了,把下面的lea ecx影响到了,无法正常赋值。

将赋值nop掉,调整参数的赋值,腾出空间给wMonth赋值

还是不行,调试发现是周(0-6)这里是22,天(1-该月天数)这里是c000,不对.

重新修改后,把参数设置成功

- 修改internet explorer版本以及攻击的网址
虚拟机的版本为6.0,改为6.0,地址改为baidu

ida找到二者对应的虚拟地址分别为0x0405050 、0x0405074,去010editor中修改方便一点,可以直接在右侧输入字符串来修改,不用自行转化ascii码

由于直接将网址的长度变短了,导致Internet字符串的寻址错误,只有后半段了,这里用的是立即数寻址,在上侧补充上该有的0

用0重新补充,使得5074的位置时字符串的开头I

这次解析正常

成功
