Windows 自启动 之 注册表

即使成功植入模块并启动攻击模块,依然不能解决永久驻留的问题。解决永久驻留的第一步便是如何实现伴随系统启动而启动的问题,即开机自启动。这样,即使用户关机重启,病毒木马也能随着系统的启动,而由系统加载到内存中运行,从而窃取用户数据和隐私。因此,开机自启动技术是病毒木马至关重要的技术,也是杀软重点监测的技术。

对于杀软来说,只要把守住自启动的入口,就可以扣病毒木马栀杀在摇篮之中。

本文介绍 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);
}
© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情快捷回复

    暂无评论内容