间谍软件SpyWare.exe分析报告

一、 样本基本信息 3
二、 样本功能简介 3
三、 样本重要数据结构 4
3.1 CommandStruct 4
3.2 DictElement 5
四、 样本行为分析 5
4.1 注册表行为 5
4.2 文件系统行为 7
4.3 进程线程行为 9
4.4 其他行为 9
五、 SpyWare.exe详细分析 9
5.1 func1执行流程 10
5.2 func2执行流程 11
六、 sampledll.dll详细分析 15
6.1 样本基本信息 15
6.2 样本功能 16
七、 编解码算法分析 16
7.1 data1.dat 16
7.2 data2.dat 17
八、 自我保护技术分析 19
8.1 垃圾指令 19
8.2 反hook 19
8.3 数据混淆 19
8.4 非常规代码加载 19
8.5 开机自启动 19
九、 IOC分析 19
9.1 MD5 19
9.2 PDB 19
十、 分析总结 20
十一、 分析工具 20

样本基本信息

样本类型

PE32+ executable (console) x86-64, for MS Windows
样本名称

SpyWare.exe
样本编译时间

2020/3/19 10:33:41
样本文件大小

23040 B
样本文件MD5

6830540bed6cf922e7d6d6d28ff8daea
样本文件SHA1

76ee383050d5d47a0fd2b85133d0d1821ee21f8a
样本图标

间谍软件样本分析 - 图1
是否加壳

运行状态 间谍软件样本分析 - 图2

样本功能简介

该样本首先将data1.dat文件解码,从中提取出程序其他函数执行所需的参数;然后对data2.dat文件解码,得到一个64位的dll文件,手工加载该dll,调用其导出函数,执行了初始打印字符串、读取指定路径下指定后缀名的文件、打印注册表指定路径下的子建和值、设置注册表自启动项、执行命令等敏感操作,怀疑是间谍软件。
间谍软件样本分析 - 图3

样本重要数据结构

CommandStruct

样本定义结构体CommandStruct,用于存放从解码后的data1.dat中提取的信息,这些信息用于后续函数执行。
间谍软件样本分析 - 图4
结构体定义:
间谍软件样本分析 - 图5
存放的具体信息:
间谍软件样本分析 - 图6

3.2 DictElement

样本定义结构体DictElement,声明结构体数组来实现字典的功能,该字典用于解码data2.dat时的查表操作(详细。
间谍软件样本分析 - 图7
字典定义:
间谍软件样本分析 - 图8

样本行为分析

注册表行为

该样本的注册表行为较多,重点关注:
1. 样本遍历注册表“HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run”和“HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run”项下所有的子项和值项,打印名称。

1)调用sampledll.dll(见附件sampledll.dll)中的导出函数SearchCredential:
间谍软件样本分析 - 图9
2)获得注册表目标项句柄:
间谍软件样本分析 - 图10
3)遍历该项下所有的子项,打印名称:
间谍软件样本分析 - 图11

4)遍历该项下所有的值项,打印名称:
间谍软件样本分析 - 图12
结论:样本收集开机自启动项这一敏感信息。

  1. 样本在注册表“HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run”下设置名称为“ThunderBird”,值为当前样本绝对路径的子项。

1)调用sampledll.dll(见附件sampledll.dll)中的导出函数SetAutoRun:
间谍软件样本分析 - 图13
2)设置子项:
间谍软件样本分析 - 图14
3)设置结果
间谍软件样本分析 - 图15
结论:样本采取的持久化机制,能够实现开机自启动。

文件系统行为

相关行为:
间谍软件样本分析 - 图16

重点关注:

  1. 样本打开并读取了同一目录下的“data1.dat”和“data2.dat”文件,分别将编码的参数信息和dll文件加载到内存中(OpenRead具体流程分析见5.1(1))。

间谍软件样本分析 - 图17

间谍软件样本分析 - 图18

结论:该样本主要依赖外部文件提取关键参数和功能函数,相当于一个解码器和装载器。

  1. 样本遍历“C:\Users\bianca\AppData\Local\Temp”路径,查找所有文件名符合.doc的文件,将内容全部读到统一的内存地址。若不存在符合条件的文件,打印return null。

1)调用sampledll.dll(见附件sampledll.dll)中的导出函数GraspFile:

间谍软件样本分析 - 图19

2)将传入的参数“%TEMP%*.doc”扩展为“C:\Users\bianca\AppData\Local\Temp\.doc*”,提取出路径。
间谍软件样本分析 - 图20

3)遍历路径下所有文件,找到符合要求的文件就调用OpenRead函数将其读入内存,然后再拷贝到指定位置。
间谍软件样本分析 - 图21

结论:样本读取临时存储的文件夹中的文件,收集用户浏览过的网站或者其它保存在这里的记录和登录凭证等敏感信息。

  1. 样本遍历“C:\Users\bianca\Desktop”路径,查找所有文件名符合*.xls的文件,将内容全部读到统一的内存地址(过程同上)。若不存在符合条件的文件,打印return null。

间谍软件样本分析 - 图22

结论:样本读取用户桌面的xls文件,表格文件中通常包含较多个人信息等敏感数据。

进程线程行为

  1. 样本创建一个新的进程,执行命令,向指定文件中写入数据。
    1)调用sampledll.dll(见附件sampledll.dll)中的导出函数Temp:

间谍软件样本分析 - 图23

2)该函数新建进程执行“cmd.exe /c echo content > C:\Windows\TEMP\TempFile”,将“content”字符串存入C:\Windows\TEMP\TempFile文件中。

间谍软件样本分析 - 图24

结论:样本写数据到临时文件夹,该文件夹下有很多浏览网页时存储的垃圾文件,很多恶意代码会存储在该文件夹下,样本有机会和其他恶意代码配合使用,并且存储在该文件夹下不易被注意到,能提高隐蔽性。

其他行为

1)样本调用TestPrint函数打印字符串。
间谍软件样本分析 - 图25
间谍软件样本分析 - 图26

SpyWare.exe详细分析

主样本作为解码器和加载器运行,main函数顺序调用了func1和fucn2两个函数后程序退出。
间谍软件样本分析 - 图27

func1执行流程

间谍软件样本分析 - 图28

  • OpenRead:将与样本相同目录下的data1.dat读入内存;
  • decode:对读入的数据解码;
  • deserializeStruct:从解码后的数据中提取出结构体CommandStruct中各项所需的值。
  1. 首先执行OpenRead函数,在堆上分配一块和data1.dat大小相同的内存,将文件的内容读取到进程的内存空间中,返回指向该区域的指针。

间谍软件样本分析 - 图29

  1. 然后调用decode函数,将内存中的data1.dat数据解码,经识别可知编码方式是base64(详细分析见7.1)。

间谍软件样本分析 - 图30
1)解码前数据:
间谍软件样本分析 - 图31

2)解码后数据(完整解码数据见附录1.txt):
间谍软件样本分析 - 图32

  1. 最后调用deserializeStruct(),遍历解码后的数据,以’\0’为每一项的结束判断依据,从中提取CommandStruct类型的结构体(comm)中元素的值。该函数中存在垃圾指令(见7.2)。以提取结构体中的SearchDir元素为例:

间谍软件样本分析 - 图33

结论:func1主要用于解码和变量赋值。

func2执行流程

间谍软件样本分析 - 图34

  • OpenRead:将与样本同一目录下的data2.dat读入内存
  • ProcessData:对读入的数据解码,得到一个64位的dll文件,该dll的导出的函数包括:GraspFile、SearchGredential、SetAutoRun、Temp、TestPrint
  • Load:进行PE格式校验,然后将已经注入到进程的DLL加载到内存,手工实现LoadLibrary的功能
  • 调用dll导出函数TestPrint():打印”Init Properly\n”
  • 调用dll导出函数GraspFile(Comm.SearchDir):读取指定路径下指定名称的文件
  • 调用dll导出函数GraspFile(Comm.MainPath):读取指定路径下指定名称的文件
  • 调用dll导出函数SearchCredential(Comm.RegistryPath):遍历并打印指定注册表键的子项和值项
  • 调用dll导出函数SetAutoRun(Comm.RegistryPath):设置名称为”ThunderBird”的注册表项,值为当前样本的绝对路径
  • 调用dll导出函数Temp(Comm.CommandString):创建进程执行”cmd.exe /c echo content > C:\Windows\TEMP\TempFile”
  1. 首先调用OpenRead函数,在堆上分配一块和data2.dat大小相同的内存,将文件的内容读取到内存中,返回指向该区域的指针。

间谍软件样本分析 - 图35

  1. 调用ProcessData函数,该函数对内存中的data2.dat的数据解码(详细分析见:7.2)。解码得到的是一个64位dll文件。

间谍软件样本分析 - 图36

1)解码前数据:
间谍软件样本分析 - 图37

  1. 解码后数据(完整解码数据见sampledll.dll):

间谍软件样本分析 - 图38

  1. 运行Load函数,手工将dll文件加载到内存0x500000地址处,模拟LoadLirbrary的功能。主要步骤如下。
    1) 进行格式检查,确保是x64可执行文件
    间谍软件样本分析 - 图39
    2) 考虑系统的内存页大小,对齐粒度
    间谍软件样本分析 - 图40

  2. 在目标加载地址comm.loadaddress处申请内存空间,将Dll文件由文件格式映射为内存格式

间谍软件样本分析 - 图41

  1. 拷贝节区信息到目标地址

间谍软件样本分析 - 图42
5)拷贝PE头部信息到目标地址,更新Dll加载基地址
间谍软件样本分析 - 图43
6)建立导入表
间谍软件样本分析 - 图44
7)在函数入口处执行代码,返回dll句柄
间谍软件样本分析 - 图45

  1. 调用Resolve函数,获得dll导出表中的函数的RVA,调用对应导出函数,相当于手工实现GetProcAddress函数,调用的函数包括TestPrint、GraspFile、SearchCredential、SetAuto和Temp。

  2. 找到dll导出表RVA

间谍软件样本分析 - 图46
2)通过导出表_IMAGE_EXPORT_DIRECTORY结构中的AddressOfFunctions、AddressOfNames、AddressOfNameOrdinals找到目标函数的RVA。
间谍软件样本分析 - 图47
间谍软件样本分析 - 图48
3)调用导出函数
间谍软件样本分析 - 图49
结论:func2主要功能将data2.dat解码得到sampledll.dll,手工实现LoadLibrary和GetProcAddress来调用dll中的相关导出函数,相当于加载器,并且没有直接使用API函数,增强了隐蔽性,某些情况下能够起到动态反调试的作用。

sampledll.dll详细分析

sampledll.dll是SpyWare.exe运行过程中对data2.dat中的数据解码得到的PE文件,将其dump出后分析。

样本基本信息

样本类型

PE32+ executable (DLL) (GUI) x86-64, for MS Windows
样本名称

sampledll.dll
样本编译时间

2020/3/19 10:33:26
样本文件大小

13313 B
样本文件MD5

c69859187f48a77502b2b0bbbe731174
样本文件SHA1

0ddc8418d5293dd88ae329e5c4f899054383f020

样本功能

Dll中导出5个功能函数,实现敏感信息的获取和文件的写入等操作。
间谍软件样本分析 - 图50

编解码算法分析

data1.dat

使用base64编码,在func1调用的decode()函数中进行解码。

  1. 用int()逐字符处理,还原成base64查表前的索引数字,该数字是原始字符串3x8bit拆分成4x6bit后,每6bit对应的十进制数。

间谍软件样本分析 - 图51

  1. 将4x6bit还原成3x8bit,根据编码时结合方式的不同,编码时也做相应的处理,最终返回解码后字符串的长度。

间谍软件样本分析 - 图52

data2.dat

func2调用的ProcessData函数对内存中的data2.dat数据进行解码,逻辑见下图,从0次开始,偶数次读取两个字节,分别左位4为和右移4位后相加得到一个新的字,奇数次直接读取一个字节扩充为一个字,如果该字不大于0xFF,则直接存入解码数组中,否则该字对应的字典项中的Prefix键对应的值,作为此次解码得到的值,连续存到解码数组中两次,上述字典DictElement是每次遍历时创建的,字典元素的键是从0x100开始的循环次数(每循环一次加一),dictionaryArray.prefix是上一次放入解码数组中的元素, dictionaryArray.character是本次放入解码数组中的元素。字典结构定义见3.1。

间谍软件样本分析 - 图53
间谍软件样本分析 - 图54

自我保护技术分析

垃圾指令

func1调用的deserializeStruct函数中包含垃圾代码,如下图所示,使反汇编结果冗长,延长了分析时间,但不影响反编译结果。
间谍软件样本分析 - 图55

反hook

func2在加载dll和调用导出函数的过程中使用的是自定义函数,没有使用系统API,能够避免动态调试时被挂钩,但不影响静态分析。

数据混淆

样本对调用的dll和函数参数都进行了编码处理,在没有获取样本的情况下,两个.dat很难被分析人员分析。

非常规代码加载

先将simpledll.dll的代码作为数据存入内存中,然后再动态载入,减少了dll暴露的可能。

开机自启动

调用dll中的SetAutoRun函数,在注册表”SOFTWARE\Microsoft\Windows\CurrentVersion\Run”下新建值为exe的绝对路径的键,实现开机自启动,起到隐蔽自身和持久驻留的效果。

IOC分析

MD5

SpyWare.exe 6830540bed6cf922e7d6d6d28ff8daea
data1.dat f56494502bbc7c63954323dcac157acc
data2.dat ecc04205681e5db0eadb272c96f93ec8
sampledll.dll c69859187f48a77502b2b0bbbe731174

PDB

C:\test\program\x64\Release\SpyWare.pdb
C:\test\program\x64\Release\sampledll.pdb

分析总结

上述就是对SpyWare.exe样本的分析,从功能上看该样本属于间谍软件,整个样本的体积很小,主要功能由外部dll提供,隐蔽性较好,有持久化驻留的相关设置,主要目的是获取用户敏感信息,后续应该关注该样本变体是否有网络行为,是否有和远程服务器通信的操作。

分析工具

  1. ida Pro 7.0
  2. x64dbg
  3. LordPE