恶意程序分析—一个混淆过的用户行为监控恶意程序
简介
由于杀软对商业壳比较敏感,并且商业壳检测、脱壳技术比较成熟,病毒作者一般不会去选择用商业的壳来保护自己的恶意代码,所以混淆壳成为了一个不错的选择.混淆壳可以有效对抗杀软,因为这种壳一般不存在通用的检测方法,并且很难去静态的脱壳,所以其恶意代码就不会被发现,从而使自己长时间的存在。
本次学习分析该恶意程序混淆的具体方式及恶意程序的具体行为。
前置知识
壳
加壳过程是用加壳程序对源程序进行压缩、加密、转换指令等操作,然后一般是在程序的开头加上一段壳程序。当加壳程序运行时,在程序开头的壳程序会对加壳程序进行解压缩、解密代码或者数据、解释执行相应代码等过程,壳程序运行完之后一般会将加壳程序恢复成源程序,加壳程序便依旧可以执行相应的功能。
软件的壳分为:加密壳、压缩壳、伪装壳、多层壳等类,目的都是为了隐藏程序真正的OEP。OEP是程序的入口点,当找到了OEP,既可以立即脱壳。
HOOK—计算机病毒对消息钩子的利用
HOOK的概念
HOOK(钩子)是一种特殊的消息处理机制,它可以监视系统或进程的各种事件信息,截取发往目标窗口的信息并进行处理。所以说,我们可以在系统中自定义钩子,用来监视系统中特定事件的发生,完成特定功能,如屏幕取词,监视日志,截获键盘、鼠标输入等等。
钩子的种类很多,每种钩子可以截获相应的消息,如键盘钩子可以截获键盘消息,外壳钩子可以截取、启动和关闭应用程序的消息等。钩子可以分为线程钩子和系统钩子,线程钩子可以监视指定线程的事件消息,系统钩子监视系统中的所有线程的事件消息。因为系统钩子会影响系统中所有的应用程序,所以钩子函数必须放在独立的动态链接库(DLL) 中。
消息钩子的拦截信息步骤
此部分可参考Microsoft官方文档https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa
-
设置钩子回调函数(拦截到消息后所调用的函数)不同的类型的钩子,回调函数参数含义不同,但是参数名相同,均类似以下结构:
LRESULT CALLBACK KeyboardProc( int code, //钩子编码 WPARAM wParam, //虚拟键编码 LPARAM lParam) //按键信息
而这个回调函数在每次消息触发的时候,都会执行一次,为了不影响消息的正常执行,我们需要把消息给传递下去:
LRESULT WINAPI CallNextHookEx( _In_opt_ HHOOK hhk, _In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam);
-
安装钩子(使用SetWindowsHookEx函数)
HHOOK WINAPI SetWindowsHookExW( _In_ int idHook, //钩子的类型 _In_ HOOKPROC lpfn, //Hook函数的地址 _In_opt_ HINSTANCE hmod, //Hook函数所在模块的句柄 _In_ DWORD dwThreadId); //需要被挂钩的线程ID,全局则设置0
-
卸载钩子(使用UnhookWindowsHookEx函数)
钩子使用完毕后如果不卸载,则会占用大量的系统资源,使得系统运行缓慢也提高了被用户发现的可能性,因此需要卸载钩子。
BOOL WINAPI UnhookWindowsHookEx( _In_ HHOOK hhk);//钩子句柄
计算机病毒对消息钩子的利用
计算机病毒经常利用消息钩子实现两种功能:
1.监控用户按键,盗取用户信息。
这样的病毒会启动一个常驻内存的EXE病毒进程,然后安装一个全局键盘消息钩子,钩子回调函数位于病毒进程中,这样系统中任何有按键操作的进程,其按键详细信息都会被病毒进程拦截记录。
2.自启动
这样的病毒会将钩子回调函数放在一个DLL文件中,然后安装一个全局消息(容易触发的消息,如WH_CBT、WH_GETMESSAGE等)钩子,这样凡响应该消息的进程都会自动加载病毒的DLL,病毒也就跟着自动运行了。
调试
调试思路:当加壳过的恶意程序运行时,其必定会自身执行解密操作。我们只需要找到解密完成后的数据将其dump下来分析即可得到恶意程序的本地,然后可以进行后续的静态分析或者继续动态调试分析。
有一些复杂的程序会有多轮混淆,可能新开辟的内存空间里面写入一些机器码执行,然后这段机器码会再开辟内存,再次写入机器码执行……如此多轮以后,才会写入真正的PE文件,这时候就要经过多轮下断点调试了。
本次分析的程序为一个经过混淆的dll注入类型的键盘记录恶意程序,笔者将从OD去混淆及IDA静态分析两方面来进行。
样本存放在了笔者的github Rain_learning仓库下的week36-37中
OD分析混淆原理及PE文件提取
经过初步分析,该程序是经过加密运算进行混淆的,所以肯定会调用诸如VirtualAlloc这类内存分配函数来进行内存的申请,于是思路就是跟踪该类函数,对于该样本是在VirtualAlloc函数处下断点跟踪数据,然后对数据下硬件断点,跟踪提取出解密后的数据。
将样本后缀改为.exe,用OD打开选择否即可
给VirtualAlloc函数下断点 bp VirtualAlloc
此时可以关注右下角开辟空间的大小,因为PE文件肯定远远大于224各字节,所以继续F9去找下一个VirtualAlloc函数
继续F9
可以看到这次开辟的内存空间是较大的,符合PE文件特征
找到调用VirtualAlloc函数的下一条,追踪寄存器窗口一直看到寄存器出现地址开始追踪
这样就找到我们想要的地址了,然后给该地址第一个数据下硬件访问断点,追踪对该数据操作的代码段
下完断点之后直接F9运行到这块内存空间执行写入的代码的地方,然后F8单步执行,发现了常见的PE文件开头4D 5A
继续F8运行,直到数据解密完成就可以提取了
提出完成后的文件如下,之后我们就可以静态分析了。
去混淆前后反汇编代码对比
去混淆前
去混淆后
可以看到去混淆后main函数代码比较清晰,也没有了混淆时的奇怪汇编指令。
IDA静态分析提取样本
直接分析几个关键函数
跟进sub_4643BF
查看几个函数,在sub_44ACDA函数中发现HOOK建立函数
这段代码主要是用来创建一个系统钩子,并在特定事件发生时调用指定的钩子过程函数。钩子函数的作用是拦截系统消息或者监视系统事件,通常用于实现键盘记录、鼠标监控、窗口消息处理等功能。
因此,这段代码可能会被用于实现某些监控或者记录用户操作的功能。
返回winMain函数,继续跟进下面的函数
这段代码主要是用于清理资源的,包括取消注册之前设置的钩子,并进行一些其他的清理工作。
通过上面的分析,正常程序是不会通过加密壳混淆并且注册钩子的,因此可以判定该程序为监控或者记录用户操作的恶意程序。