分析恶意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 线程 

  进程是执行代码的容器, 线程才是Windows操作系统真正要执行的内容。线程是被CPU执行的独立指令序列, 而需要等待其他线程。一个进程包含一个或多个线程,它们各自执行进程中的一部分代码。一个进程中的所有线程共享内存空间,但每一个都有自己的处理器、寄存器、栈。

  CreateThread函数可以用来创建新线程。函数的调用者指定一个起始地址,这个起始地址经常被叫做start函数。执行从这个起始地址开始直到这个函数返回。

  恶意代码可以通过多种方式使用CreateThread。
 
  比如CreateThread时将起始地址设置为Loadlibrary的地址,传递给CreateThread的参数是要被加载库的名字,新的DLL被加载到这个进程的内存中, 然后DllMain被调用。
 
  再比如恶意代码可以为输入和输出创建两个线程,一个用来在套接字或管道上监听,并输出到一个进程的标准输入里;另一个从标准输出取数据,并发送到套接字或管道上。
4.4 使用互斥量间的进程协作

  互斥量(mutex),在内核中也称为互斥门(mutant)。 互斥量是全局对象,用于协调多个进程和线程,最主要用于控制共享资源的访问。互斥量经常被恶意代码使用,它们经常使用硬编码的名字。恶意代码通常创建一个互斥量,并试图通过同一个名字来打开一个已存在的互斥量,进而确定一次只运行恶意代码的一个实例。

  线程通过对WaitForSingleObject的调用,获取对互斥量的访问,并且任何后续线程试图获取对它的访问时,都必须等待。 完成对互斥量的使用后,需要使用ReleaseMutex函数释放。 

posted @   无事闲逛  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示