首页
社区
课程
招聘
[原创]彩虹猫样本分析记录
发表于: 2021-1-28 23:29 3585

[原创]彩虹猫样本分析记录

2021-1-28 23:29
3585

0x01 基本信息

Name:MEMZ.exe

MD5:19dbec50735b5f2a72d4199c4e184960

SHA1:6FED7732F7CB6F59743795B2AB154A3676F4C822

 

样本运行后,效果可见ANYRUN,重启后,会出现如下彩虹猫动画:

 

图片.png

 

首先使用PEiD查壳:

 

PEiD

 

接下来查看其导入表及导入函数:

 

导入表

 

如下各函数与程序运行后效果相关联,播放提示音:

 

 

画面反色:

 

 

控制鼠标:

 

 

借由Procmon对该样本行为进行监控,发现其存在注册表相关操作:

 

procmon

0x02 静态分析

首先可以于Strings窗口看到如下字符串:

 

图片.png

 

start函数进入,首先调用GetCommandLineCommandLineToArgv两个函数获取命令行参数,之后进入if判断有无参数:

 

图片.png

 

知道整体逻辑后,笔者将分析划分为有参部分和无参部分。

0x02.1 有参部分——watchdog

程序对参数的判断有两个:一为"watchdog",一为"main"(详见后文)。本节分析watchdog参数,main参数将与MBR部分一起分析。

 

判断获取的参数是否为watchdog,是则向下执行:

 

图片.png

 

调用CreateThread创建线程:

 

sub_40114A

sub_40114A函数

在该函数中,首先调用GetCurrentProcessGetProcessImageFileName函数获取此执行文件路径,之后进入一死循环。在此循环中, CreateToolhelp32Snapshot用于拍摄进程快照, Process32FirstProcess32Next用于遍历进程,GetProcessImageFileName用于获取进程路径:

 

sub_40114A函数

 

此循环中包含一do-while——对本次获得的进程路径与代码段开头获得的路径进行比较,若相同,则计数器加一,在最后会令v7的值等于计数器v4的值。当再次进入外层循环,若计数器v4的值小于v7(也就是上一次循环的计数器的值),程序会跳转进入到sub_401021

sub_401021函数

首先程序循环20次创建线程,该线程名为StartAddress。
然后通过GetProcAddress获取ntdll.DLLRtlAdjustPrivilegeNtRaiseHardError函数地址。其中RtlAdjustPrivilege用于快速关机(不保存,通知内核驱动后直接关电源)的提权,NtRaiseHardError制造蓝屏。

 

GetCurrentProcessOpenProcessToken用于打开进程Token,LookupPrivilegeValue查找系统权限的特权值然后用AdjustTokenPrivileges调整令牌特权。最后该函数返回ExitWindowsEx,用于关闭系统。

 

sub_401021函数

 

如此可以推断,于sub_40114A函数中调用sub_401021函数就是为了在判断进程减少后(比如用户强行停止程序运行),控制系统蓝屏。

StartAddress

在20次循环中创建的StartAddress线程,IDA于此处存在报错:

 

图片.png

 

该错误是IDA反编译时栈不平衡造成的,IDA遇到ret指令后判断栈指针的值在函数开头和结尾不一致,因此报错:

 

sp-analysis failed

 

StartAddress功能是:获取当前线程的唯一标识符,然后对窗口下钩子,参数是fn

 

StartAddress

 

而这里的回调函数fn的主要作用是生成窗口,且窗口大小随机:

 

回调函数fn

 

接着调用sub_401A55函数,该函数主要作用为调用CryptGenRandom生成一随机数,并将其与0x1A进行除法运算:

 

sub_401A55

 

将得到的数作为lpText下标取字符串传递给MessageBox函数弹出对话框:

 

lpText

 

回到主程序继续分析,创建一个新的窗口,lpParameters参数为sub_401000

 

图片.png

 

如此可以推断StartAddress线程功能为生成大小随机且内容随机的窗口。

sub_401000函数

这个函数对Msg的值做了一个判断:Msg值为16,对应WM_CLOSE;22对应WM_ENDSESSION。当取值符合时,将跳转sub_401021函数触发蓝屏关机,否则交由DefWindowProc这个默认的窗口处理函数(即不处理):

 

sub_401000

0x02.2 无参部分

当程序无参数时,使用MessageBox()函数弹出两个名为MEMZ弹窗——刚执行时出现的两个确认窗口:

 

图片.png

 

两次弹窗确认后,获取进程路径并保存至v10中,接下来五次循环的每一循环中,都会调用ShellExecute——即生成五个相同的进程,参数为watchdog

 

图片.png

 

参照watchdog部分,这五个进程分别创建了一个线程。

 

五次循环结束后,用ShellExecute函数生成一参数为main的进程。而接下来的SetPriorityClass函数用于设定当前进程的优先级——HIGH_PRIORITY_CLASS(0x80,即最高):

 

提权

 

最后程序退出:

 

图片.png

0x02.3 main

首先打开磁盘驱动器(此处\\\\.\\PhysicalDrive0为0号磁盘),若失败则结束进程。然后用LocalAlloc函数从堆中分配0x1000个字节:

 

图片.png

 

其后do-while循环,一共循环303次,每次都向分配空间中写入数据,共写入303字节。而MBR的前446字节为启动代码,写入的303字节会覆盖MBR的启动代码部分。此操作直接破坏了MBR,如此一来无法将控制权转交给操作系统,而是执行病毒写入数据:

 

303字节

 

下一个do-while循环写入了1952个字节,从510偏移处开始向后写入:

 

1952字节

 

需要注意的是,这里前两个字节是0x55AA——MBR结束标志,表明这是一个有效的主引导扇区:

 

图片.png

 

写入完成:

 

图片.png

 

向note.txt中写入如下内容,运行的时候会用记事本打开该文件:

 

图片.png

 

如下do-while共循环10次,每次循环令一个进程陷入休眠,然后再创建一个线程sub_401A2B

 

图片.png

 

每次循环v9值加2,由下图可以看出其对应函数地址:

 

图片.png

 

一共十个函数,能发现样本运行后的各种奇怪行为就是通过这些函数实现的:

 

图片.png

 

图片.png

 

sub_401A2B配合传递参数v9实现图中函数调用:

 

sub_401A2B

0x02.4 程序流程图

程序流程

0x03 MBR动调分析

方法是利用IDA的Remote GDB Debugger连接到虚拟机进行调试:

 

GDB debugger

 

配置Hostname及Port:

 

端口

 

Attach:

 

连接

 

因为计算机启动后,会将主引导程序加载到物理内存地址0x7C00处,故在此处下断点,让程序运行至此处再继续调试:

 

图片.png

 

内存窗口查看:

 

主引导区域

 

0x7C12处是int 13h中断,由寄存器传递参数如下:

 

写入寄存器的数值

 

从0柱面0磁头2扇区开始读,共4个扇区,写入地址经计算为0x7E00

 

int 13中断

 

执行至0x7C12,各寄存器值如图:

 

寄存器的值

 

因此当执行到0x7C14时,剩余的字符已经加载到内存0x7E00处,下图是加载后的内存:

 

加载之后的内存

 

0x7c22开始至0x7c5b是一个循环,由si值的变化中可以判断,通过lodsb读入的字符为MBR之后的1950个字符:

 

判断si值

 

该循环主要通过lodsbstosb向ES:DI指向的存储单元中写入字符,下图为写入后内存的变化:

 

写入后的内存

 

当循环结束,可以观察到内存:

 

y9yoKx.png

 

由此可以判断写入的字符将用于实现界面的字符、动画及音频。

 

0x7C67处是int 10h中断。AH=0x10——颜色中断,触发了闪烁。

 

其寄存器的值如图:

 

寄存器的值

 

在此之前,AL的值被写入端口43h(42h、43h端口均为音频程序的端口号)。这里的作用是将电路初始化,用于接收之后控制音频的计数值:

 

int 10中断

 

从61h端口读取一个字节数据到AL,将AL进行或运算后的值写入61h端口,此时值为00110011,作用是允许扬声器数据,定时器通道3会被启动:

 

图片.png

 

之后的int 15h中断用于等待:

 

图片.png

 

运行到0x7cb0处,这里的42h端口接受AL的值作为控制字,使定时器准备接收计数初值。之后装入AH(计数值)用于建立将要产生的声音频率。此时61h端口的0/1bit均为1,因此当这段程序运行完后,虚拟机发出特定频率的声音。

 

图片.png

 

动画出现前的字符则是依靠0x7C8A处的一段程序完成的。

 

当运行至0x7CA2时,只有当bl的值为0,才会往下执行至0x7CB0并发出特定频率的声音,否则将跳转回0x7C8A继续将字符打印在屏幕上:

 

0x7c2A

 

这段则是依次输出不同颜色的可见字符,形成彩虹猫动画的初始画面:

 

图片.png

 

图片.png

 

当判断di的值为0xFA0时,程序跳转至0x7CF0,运行到0x7D03时因不满足判断会再次跳转回0x7CDC处,并再次依序输出字符形成下一个画面:

 

图片.png

 

图片.png

 

当判断成立继续向下运行则通过端口42h输出音频,并在最后跳转至0x7CDC继续之前的循环。如此循环往复就能形成彩虹猫的动画及音频:

 

图片.png

0x04 Notes

0x04.1 MSG

MSG是Windows程序中的结构体。在Windows程序中,消息是由MSG结构体来表示的。其定义为:

1
2
3
4
5
6
7
8
9
typedef struct tagMSG {
  HWND   hwnd;
  UINT   message;
  WPARAM wParam;
  LPARAM lParam;
  DWORD  time;
  POINT  pt;
  DWORD  lPrivate;
} MSG, *PMSG, *NPMSG, *LPMSG;

第一个成员变量hwnd表示消息所属的窗口;第二个成员变量message指定了消息的标识符。第三、第四个成员变量wParamlParam,用于指定消息的附加信息。最后两个变量分别表示消息投递到消息队列中的时间和鼠标的当前位置。

 

本次样本对Msg的取值判断为:Msg值为16,对应WM_CLOSE(一个窗口或者应用程序应该被关闭时发出WM_CLOSE消息);值为22则对应WM_ENDSESSIONWM_ENDSESSION消息表示Windows即将关闭)。

0x04.2 42h,43h,61h三个端口号

早期的PC系列机中有一个专门用于定时的集成电路,型号是8253/8254。它有三个通道,第一个通道用于控制系统时钟正常运转;第二个通道用于存储器刷新;第三个通道通过一组电路与喇叭相联。

 

若将61H端口的bit0、bit1位都置成1,则相当于既打开了定时器又打开了开关,此时定时器产生的声音信号就会送到放大器推动喇叭发声。

 

打开扬声器的指令为:

1
2
3
IN  AL,61H  
OR  AL,3  
OUT  61H,AL

关闭扬声器的指令为:

1
2
AND  AL,0FCH  
OUT  61H,AL

初始化8253的指令为:

1
2
MOV  AL,0B6H  
OUT  43H,AL

0x04.3 BIOS中断

10H中断是BIOS对显示器和屏幕所提供的服务程序。

 

本次调用功能编号为:AH=0x10。当AL=03H,其作用为触发闪烁/亮显位。

 

13H中断是低端磁盘服务。

 

本次调用功能编号为:AH=0x02。当AL=0x4,CH=0x0,CL=0x2,DH=0x0,ES:BX=0x7E00,其作用为从0柱面0磁头的2扇区开始读4个扇区至0x7E00,

 

15H中断

 

本次调用功能编号为:AH=86H。其作用为等待。

0x05 参考链接


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//