通过添加启动目录和和修改注册表进行权限维持

添加启动目录

由于启动目录不固定,需要先通过SHGetSpecialFolderPath获取启动路径,再CopyFile把要自启动的程序复制过去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <Windows.h>
#include <shlobj_core.h>

int main()
{
wchar_t StartupFolder[MAX_PATH] = {0};
wchar_t Path[MAX_PATH] = { 0 };

BOOL bRet= SHGetSpecialFolderPath(NULL, StartupFolder, CSIDL_STARTUP, FALSE);
if (!bRet) {
return -1;
}

GetModuleFileName(NULL, (LPWSTR)&Path, MAX_PATH);
wcscat_s(StartupFolder, L"\\Persistance.exe");
MessageBox(NULL, StartupFolder, L"StartupFolder", MB_OK);
if (CopyFile(Path, StartupFolder, FALSE)) {
MessageBox(NULL, L"succeed", L"succeed", MB_OK);
}
return 0;
}

修改注册表

无需管理员权限即可修改HKEY_CURRENT_USER

在HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run中写入程序路径即可实现开机自启动

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//添加自身到注册表启动项
BOOL Regpersist()
{
HKEY hKey;
LPCTSTR szRun = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
if (RegOpenKeyEx(HKEY_CURRENT_USER, szRun, 0, KEY_ALL_ACCESS, &hKey)
== ERROR_SUCCESS)
{
TCHAR szFileName[MAX_PATH] = { 0 };
DWORD dwRet = GetModuleFileName(NULL, szFileName, MAX_PATH);
AfxMessageBox(szFileName);
long lRet = RegSetValueEx(hKey, _T("Login"), 0, REG_SZ, (BYTE*)szFileName, dwRet);
RegCloseKey(hKey);
if (lRet != ERROR_SUCCESS)
return FALSE;
//else // 删除启动;
//{
// long lRet = RegDeleteValue(hKey, "MFCLogin");
// RegCloseKey(hKey);
// if (lRet != ERROR_SUCCESS)
// return FALSE;
//}
}
else
{
MessageBox(_T("打开注册表失败"));
return FALSE;
}
MessageBox(_T("添加成功"));
return TRUE;
}

相关API函数

SHGetSpecialFolderPath

该api用来获取指定的系统路径

1
2
3
4
5
6
BOOL SHGetSpecialFolderPathA(
HWND hwnd,
LPSTR pszPath,
int csidl, //CSIDL_STARTUP
BOOL fCreate
);

RegOpenKey

打开注册表,成功返回ERROR_SUCCESS

1
2
3
4
5
LSTATUS RegOpenKeyA(
HKEY hKey, //指定一个父键句柄 HKEY_CURRENT_USER
LPCSTR lpSubKey,//指向一个字符串,表示要打开的子键名称,_T("Software\\Microsoft\\Windows\\CurrentVersion\\Run")
PHKEY phkResult//返回打开的子键句柄 &hKey
);

RegCloseKey

关闭注册表,成功返回ERROR_SUCCESS

1
2
3
LSTATUS RegCloseKey(
HKEY hKey//打开的子键句柄
);

RegQueryValueEx

注册表键值的查询

成功返回 ERROR_SUCCESS.

1
2
3
4
5
6
7
8
LSTATUS RegQueryValueExA(
HKEY hKey,//指向一个已经被打开或创建的子键句柄
LPCSTR lpValueName,//指定要被查询的键值的名称
LPDWORD lpReserved,//保留,始终NULL
LPDWORD lpType,//返回被查询的值的类型
LPBYTE lpData,//返回被查询数据的缓冲区
LPDWORD lpcbData//缓冲区长度
);

RegSetValueEx

注册表键值的写入

成功返回 ERROR_SUCCESS.

1
2
3
4
5
6
7
8
LSTATUS RegSetValueExA(
HKEY hKey,//指向一个已经被打开或创建的子键句柄 HKEY_LOCAL
LPCSTR lpValueName,//指定要被查询或写入的键值的名称 MFCLogin
DWORD Reserved,//保留,始终为0 0
DWORD dwType,//写入键值的类型 REG_SZ
const BYTE *lpData,//写入键值的缓冲区 路径
DWORD cbData//写入键值缓冲区的长度 sizeof
);

RegEnumValue

注册表键值的枚举

成功返回 ERROR_SUCCESS.

1
2
3
4
5
6
7
8
9
10
LSTATUS RegEnumValueA(
HKEY hKey,//指向一个已经被打开或创建的子键句柄
DWORD dwIndex,//查询的索引值
LPSTR lpValueName,//健名的缓冲区
LPDWORD lpcchValueName,//健名缓冲区的长度
LPDWORD lpReserved,//保留,NULL
LPDWORD lpType,//返回被查询的值的类型
LPBYTE lpData,//被查询键值的缓冲区
LPDWORD lpcbData//被查询键值的缓冲区的大小
);

RegDeleteValue

注册表键值的删除

成功返回 ERROR_SUCCESS.

1
2
3
4
LSTATUS RegDeleteValueA(
HKEY hKey,//指向一个已经被打开或创建的子键句柄
LPCSTR lpValueName//指向欲删除的键值项的名称
);

GetModuleFileName

在开发过程中经常需要获得程序当前的运行目录,这时就可以使用GetModuleFileName

1
2
3
4
5
DWORD WINAPI GetModuleFileName(
HMODULE hModule,//要获取文件名的模块名柄,null表示当前模块
LPTSTR lpFileName,//输出参数,存放取得的文件名 TCHAR lpfilename
DWORD nSize//参数的长度 MAX_PATH
);

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!