分析恶意Windows程序
1. Windows API
1.1 句柄
句柄(Handle),是在操作系统中被打开或被创建的项。
句柄和指针的区别:指针是一个变量,它存储的是另一个变量的地址。句柄是一种指向资源的指针,或者说是指向指针的指针,用于标识和引用某种资源或对象。句柄是一个间接的指针,不直接指向对象的内存地址,而是指向一个指针表格,这个表格中包含了指向实际对象内存地址的指针。
1.2 文件系统函数
恶意代码与系统交互的一个最常用的方式就是创建或修改文件,文件活动可以提示这个恶意代码的行为。
微软提供的访问文件系统的常见函数如下:
CreateFile:可以用来打开已经存在的文件,也可以创建新的文件。
ReadFile和WriteFile:分别可以用来对文件进行读和写,都是将文件作为流来操作。
CreateFileMapping:可以从磁盘上加载一个文件到内存中。
MapViewOfFile:返回一个指向映射的基地址指针,它可以被用来访问内存中的文件。
CreateFileMapping函数和MapViewOfFile函数经常被恶意代码者利用来进行文件映射。因为它们允许将一个文件加载到内存中,以便更加容易地进行操作。然后使用从MapViewOfFile函数返回的指针,在文件中的任意位置进行读取和写入。这个特性在解析一个文件格式时极其顺手,因为你可以简单地跳转到不同内存地址。
文件映射被普遍用来复制 Windows加载器的功能。在获得一个文件的映射以后,恶意代码可以解析PE头,并对内存中的文件进行所有需要的修改,因此使PE文件就像被操作系统加载器加载一样执行起来。
2. Windows注册表
根键,称为HKEY。
Windows注册表被用来保存操作系统与程序的配置信息,比如设置和选项。 和文件系统一样,是基于主机的感染迹象的很好来源,并且能够揭示出恶意代码功能的有用信息。
注册表被划分为下面5个根键:
HKEY _LOCAL_MACHINE (HKLM) 保存对本地机器全局设置。
HKEY CURRENT_USER (HKCU) 保存当前用户特定的设置。
HKEY_CLASSES_ROOT 保存定义的类型信息。
HKEY_CURRENT_CONFIG 保存关千当前硬件配置的设置,特别是与当前和标准配置之间不同的部分。
HKEY_USERS 定义默认用户、 新用户和当前用户的配置。
其中,HKEY_LOCAL_MACHINE\SOFTWARE \Microsoft\Windows\CurrentVersion\Run列举了用户登录时被自动启动的可执行程序 。所以,向Run子键中写入项,是设置程序为自启动的方法。尽管不是一个隐蔽的技术,它仍然经常被恶意代码用来自动启动自身。
RegOpenKeyEx 函数可用于打开指定的注册表项,返回用于操作注册表的句柄,以便进行编辑和查询。它也是一个经常被恶意代码利用的注册表函数。
下面是一个使用RegOpenKeyEx 函数打开指定注册表项的例子:
查看RegOpenKeyEx 函数原型可知,这里想要使用RegOpenKeyEx函数来打开注册表项HARDWARE\DESCRIPTION\System\CentralProcessor, 它属于HKEY_LOCAL_MACHINE的子项,并置访问权限为KEY_QUERY_VALUE(查询)。
3. 网络API
恶意代码通常依赖于网络函数来完成工作,而Windows API函数中有很多可以进行网络通信。
一个网络程序通常有服务端和客户端两个端点。服务器端打开套接字并等待入站连接;客户端连接一个正在等待的套接字。而恶意代码可以是这两端中的任意一个。
WinINet API实现了应用层协议,如HTTP和FTP。可以基于恶意代码打开的连接类型,去分析它的目的。
InternetOpen:用来初始化到互联网的连接。
InternetOpenUrl:用来访问某个URL (可以是一个HTTP页面或一个FTP资源) 。
InternetReadFile和ReadFile:两者工作原理相似,允许程序从一个来自互联网的下载文件中读取数据。
恶意代码可以使用WinINet API,来连接一个远程服务器,获取要执行的进一步指令。
4. 跟踪恶意代码的运行
4.1 DLL
在恶意代码调用其他代码运行的方式中,很常见的一个方式是通过使用DLL程序。这里的方式主要有三种:
①在DLL文件中保存恶意代码
将恶意代码保存到一个DLL文件,当别的程序调用到该DLL文件时,将被加载到另外一个进程中。
②通过使用Windows DLL
几乎所有的恶意代码都使用在每个系统上都可以发现的Windows基础DLL程序。Windows DLL程序包含了需要与操作系统交互的功能。
③通过使用第三方DLL
恶意代码也可以使用第三方DLL来和其他程序交互。当看见从一个第三方DLL导入函数的恶意代码时,可以推断它正在和那个程序交互,来完成它的目标。DLL和EXE都使用PE文件格式。DLL文件看起来几乎和.exe文件一模一样。DLL文件里面只有一个单一标志,指示这个文件是一个DLL,而不是一个.exe。DLL的主函数是D11Main。它没有标记,而且并不是DLL的导出函数,但是它在PE头中被指定为文件的入口点。任何时候一个进程加载或卸载库,会创建一个新线程,或一个已存在的线程结束时,这个函数都会被调用来通知DLL。这个通知允许DLL来管理每个进程或每个线程的资源。
4.2 进程
恶意代码也可以通过创建一个新进程,或修改一个已存在的进程,来执行当前程序之外的代码。其中最常使用的创建新进程函数是CreateProcess。
下面是一个使用CreateProcess函数打开指定注册表项的例子:
这里使用CreateProcess函数创建新的notepad(记事本)进程,并且不继承调用进程的句柄。
4.3 线程
CreateThread函数可以用来创建新线程。函数的调用者指定一个起始地址,这个起始地址经常被叫做start函数。执行从这个起始地址开始直到这个函数返回。
互斥量(mutex),在内核中也称为互斥门(mutant)。 互斥量是全局对象,用于协调多个进程和线程,最主要用于控制共享资源的访问。互斥量经常被恶意代码使用,它们经常使用硬编码的名字。恶意代码通常创建一个互斥量,并试图通过同一个名字来打开一个已存在的互斥量,进而确定一次只运行恶意代码的一个实例。
线程通过对WaitForSingleObject的调用,获取对互斥量的访问,并且任何后续线程试图获取对它的访问时,都必须等待。 完成对互斥量的使用后,需要使用ReleaseMutex函数释放。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律