即使成功植入模块并启动攻击模块,依然不能解决永久驻留的问题。解决永久驻留的第一步便是如何实现伴随系统启动而启动的问题,即开机自启动。这样,即使用户关机重启,病毒木马也能随着系统的启动,而由系统加载到内存中运行,从而窃取用户数据和隐私。因此,开机自启动技术是病毒木马至关重要的技术,也是杀软重点监测的技术。
对于杀软来说,只要把守住自启动的入口,就可以扣病毒木马栀杀在摇篮之中。
本文介绍 4种 Windows 开机自启动技术,它包括:
- 注册表
- 快速启动目录
- 计划任务
- 系统服务
0x1 注册表
RegOpenKeyEx 函数
- 打开一个指定的注册表键。
https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexw
LSTATUS RegOpenKeyEx(
[in] HKEY hKey,
[in, optional] LPCSTR lpSubKey,
[in] DWORD ulOptions,
[in] REGSAM samDesired,
[out] PHKEY phkResult
);
RegSetValueEx 函数
- 在注册表项下设置指定值的数据和类型。
https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvalueexw
LSTATUS RegSetValueEx(
[in] HKEY hKey,
[in, optional] LPCSTR lpValueName,
DWORD Reserved,
[in] DWORD dwType,
[in] const BYTE *lpData,
[in] DWORD cbData
);
01 实现原理
Windows每次开机都会从一些注册表键下获取键值中的程序路径,并创建进程启动程序。所以想实现注册表开机自启动,只需要在这个注册表键下添加自己想要设置的程序路径即可。
Windows的Run和RunOnce注册表项可以让用户登陆系统时自动启动一些程序。
其中涉及到的注册表项如下:
- HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
- HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
- HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
- HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
在这四种项中添加的自启动程序的规则不一样:
注册表项 | 解释 |
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run | 表示任何账户每一次登陆到Windows系统都会自动启动在这个项下面注册的程序 (管理员权限) |
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce | 表示任何账户下一次登陆到Windows系统会自动启动在这个项下面注册的程序,以后就不会自启了 |
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run | 表示当前账户每一次登陆到Windows系统都会自动启动在这个项下面注册的程序 (用户权限) |
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce | 表示当前账户下一次登陆到Windows系统会自动启动在这个项下面注册的程序,以后就不会自启了 |
一般来说,在HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
项下注册自启动项,不使用HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
,原因是因为修改该注册表的值需要管理员权限。
API | 功能 |
RegCreateKey | 创建一个KEY,并返回相应的HKEY |
RegOpenKey | 打开注册表,得到一个HKEY,用来作为下面这些函数的第一个参数 |
RegOpenKeyEx | 同RegOpenKey类似,一般很少用,增加了一个访问控制类型参数 |
RegSetValue | 设置一个HKEY的默认值 |
RegSetValueEx | 设置一个HKEY除默认值以外其它的值 |
RegQueryValue | 获取一个HKEY的默认值 |
RegQueryValueEx | 获取一个HKEY除默认值以外其它的值 |
RegDeleteKey | 删除一个KEY,此KEY不能包含子KEY |
SHDeleteKey | 删除一个KEY以及所有子KEY |
RegDeleteValue | 删除KEY里面的值 |
RegCloseKey | 关闭注册表 |
02 实现代码
- 普通 User ==> HKEY_CURRENT_USER
#include <iostream>
#include <Windows.h>
using namespace std;
BOOL Reg_CurrentUser(LPCWSTR lpszFileName, LPCWSTR lpszValueName)
{
// 默认权限
HKEY hKey;
// 打开注册表键
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &hKey))
{
printf("[!] RegOpenKeyEx not found, try create keyvalue");
if (ERROR_SUCCESS != ::RegCreateKeyW(HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey))
{
printf("[!] RegCreateKeyW failed, error is : %d\n\n", GetLastError());
return FALSE;
}
else
{
printf("[*] RegCreateKeyW successfully!\n\n");
}
}
else
{
printf("[*] RegOpenKeyEx successfully!\n\n");
}
// 修改注册表值,实现开机自启
if (ERROR_SUCCESS != RegSetValueEx(hKey, lpszValueName, 0, REG_SZ, (BYTE*)lpszFileName, (wcslen(lpszFileName) + 1) * 2))
{
RegCloseKey(hKey);
printf("[!] RegSetValueEx failed, error is : %d\n\n", GetLastError());
return FALSE;
}
else
{
printf("[*] RegSetValueEx successfully!\n\n");
}
// 关闭注册表键
RegCloseKey(hKey);
return TRUE;
}
int main()
{
LPCWSTR lpszFileName = L"C:\\MyCode\\CPlus\\test.exe";
LPCWSTR lpszValueName = L"test";
Reg_CurrentUser(lpszFileName, lpszValueName);
}
- Administrator ==> HKEY_LOCAL_MACHINE
64bit系统的注册表分32 位注册表项和64位注册表项两部分
- 在64bit系统下,通过regedit中查看到指定路径下的注册表项均为64位注册表项,而32位注册表项被重定位到:HKEY_LOCAL_MACHINE\Software\WOW6432Node
应用程序操作注册表的时候也分32bit方式和64bit方式
- 运行于64bit系统下的32bit应用程序默认操作32位注册表项(即被重定向到 WOW6432Node 下的子项);而64bit应用程序才是操作的直观子项。
- 比如,同在64bit系统下,使用如下代码访问注册表:::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(“Software\\Sobey\\MPC “), 0, KEY_ALL_ACCESS, &hKey)
- 如果应用程序为32bit,那么实际访问的注册表位置为(默认操作):HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Sobey\MPC
- 而如果应用程序为64bit,那么实际访问的注册表位置将会是(默认操作):HKEY_LOCAL_MACHINE\SOFTWARE\Sobey\MPC
#include <iostream>
#include <Windows.h>
using namespace std;
BOOL Reg_LOCALMACHINE(LPCWSTR lpszFileName, LPCWSTR lpszValueName)
{
// 默认权限
HKEY hKey;
// 打开注册表键
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &hKey))
{
printf("[!] RegOpenKeyEx not found, try create keyvalue");
if (ERROR_SUCCESS != ::RegCreateKeyW(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey))
{
printf("[!] RegCreateKeyW failed, error is : %d\n\n", GetLastError());
return FALSE;
}
else
{
printf("[*] RegCreateKeyW successfully!\n\n");
}
}
else
{
printf("[*] RegOpenKeyEx successfully!\n\n");
}
// 修改注册表值,实现开机自启
if (ERROR_SUCCESS != RegSetValueEx(hKey, lpszValueName, 0, REG_SZ, (BYTE*)lpszFileName, (wcslen(lpszFileName) + 1) * 2))
{
RegCloseKey(hKey);
printf("[!] RegSetValueEx failed, error is : %d\n\n", GetLastError());
return FALSE;
}
else
{
printf("[*] RegSetValueEx successfully!\n\n");
}
// 关闭注册表键
RegCloseKey(hKey);
return TRUE;
}
int main()
{
LPCWSTR lpszFileName = L"C:\\MyCode\\CPlus\\test.exe";
LPCWSTR lpszValueName = L"test";
Reg_LOCALMACHINE(lpszFileName, lpszValueName);
}
暂无评论内容