进程提权

本文介绍了Windows系统中进程提权的相关技术,包括OpenProcessToken函数的使用,DesiredAccess参数的意义,以及如何通过AdjustTokenPrivileges调整权限。同时,解释了_TOKEN_PRIVILEGES和_LUID_AND_ATTRIBUTES结构的作用,讲解了LookupPrivilegeValue函数在获取特权值中的应用。参考了MSDN Library及多个技术博客,为深入理解进程提权提供了详细资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

</pre><pre>

HANDLE tokenHandle;
//获得令牌句柄
BOOL bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tokenHandle);
if (bRet){
	TOKEN_PRIVILEGES tokenPri;tokenPri.PrivilegeCount = 1;//tokenPri.Privileges数组的大小
	tokenPri.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;//开启权限Luid所标识的权限
	bRet = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tokenPri.Privileges[0].Luid);//获取权限的标识Luid
	if (bRet){
		bRet = AdjustTokenPrivileges(tokenHandle, FALSE, &tokenPri, sizeof(tokenPri), NULL, NULL);//修改权限}CloseHandle(tokenHandle);
	}
}
return bRet;//提权是否成功

OpenProcessToken原型:

BOOL WINAPI OpenProcessToken(
  _In_   HANDLE ProcessHandle,<span style="white-space:pre">	</span>// 进程句柄
  _In_   DWORD DesiredAccess,<span style="white-space:pre">	</span>// 想要获得的访问权限
  _Out_  PHANDLE TokenHandle<span style="white-space:pre">	</span>// 返回的令牌句柄
);


DesiredAccess的取值及其含义(不太清楚的话直接用TOKEN_ALL_ACCESS就行了)

ValueMeaning
TOKEN_ADJUST_DEFAULTRequired to change the default owner, primary group, or DACL of an access token.
TOKEN_ADJUST_GROUPSRequired to adjust the attributes of the groups in an access token.
TOKEN_ADJUST_PRIVILEGESRequired to enable or disable the privileges in an access token.
TOKEN_ADJUST_SESSIONIDRequired to adjust the session ID of an access token. The SE_TCB_NAME privilege is required.
TOKEN_ASSIGN_PRIMARYRequired to attach a primary token to aprocess. The SE_ASSIGNPRIMARYTOKEN_NAME privilege is also required to accomplish this task.
TOKEN_DUPLICATERequired to duplicate an access token.
TOKEN_EXECUTECombines STANDARD_RIGHTS_EXECUTE and TOKEN_IMPERSONATE.
TOKEN_IMPERSONATERequired to attach an impersonation access token to a process.
TOKEN_QUERYRequired to query an access token.
TOKEN_QUERY_SOURCERequired to query the source of an access token.
TOKEN_READCombines STANDARD_RIGHTS_READ and TOKEN_QUERY.
TOKEN_WRITECombines STANDARD_RIGHTS_WRITE, TOKEN_ADJUST_PRIVILEGES, TOKEN_ADJUST_GROUPS, and TOKEN_ADJUST_DEFAULT.
TOKEN_ALL_ACCESSCombines all possible access rights for a token.

AdjustTokenPrivileges原型:

BOOL WINAPI AdjustTokenPrivileges(
  _In_       HANDLE TokenHandle,<span style="white-space:pre">	</span>//令牌句柄
  _In_       BOOL DisableAllPrivileges,<span style="white-space:pre">	</span>//为FALSE时表示禁用所有权限,为TRUE时表示用NewState所指向的结构体来修改权限
  _In_opt_   PTOKEN_PRIVILEGES NewState,//指向TOKEN_PRIVILEGES结构体的指针
  _In_       DWORD BufferLength,<span style="white-space:pre">	</span>//sizeof(NewState)
  _Out_opt_  PTOKEN_PRIVILEGES PreviousState,<span style="white-space:pre">	</span>// 指向用来保存修改前的TOKEN_PRIVILIGES的结构体,若不想保存修改前的权限,可以为NULL
  _Out_opt_  PDWORD ReturnLength<span style="white-space:pre">	</span>// 指向用来保存<span style="font-family: Arial;">PreviousState大小的DWORD的指针</span>
);

_TOKEN_PRIVILEGES 定义:

typedef struct _TOKEN_PRIVILEGES {
  ULONG               PrivilegeCount; //Privileges数组的大小,一般为1
  LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;


_LUID_AND_ATTRIBUTES 定义:

typedef struct _LUID_AND_ATTRIBUTES {
  LUID  Luid;<span style="white-space:pre">	</span>//权限的唯一标识
  ULONG Attributes; //要对这个权限做什么?
} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES;

Attributes的取值:

属性
描述
SE_PRIVILEGE_ENABLED_BY_DEFAULT
特权默认启用
SE_PRIVILEGE_ENABLED
特权启用.
SE_PRIVILEGE_USED_FOR_ACCESS
特权被用来访问一个对象或服务。
这个标志 被用于 标识有关特权,因为
通过一组客户端应用程序,可能包含不必要的特权

LookupPrivilegeValue原型:

BOOL WINAPI LookupPrivilegeValue(
  _In_opt_  LPCTSTR lpSystemName,//指向系统名称的字符串的指针,一般为NULL,表示从本地系统获取查找权限的名称,
  _In_      LPCTSTR lpName,	 //权限的名称
  _Out_     PLUID lpLuid	 //返回的LUID的指针
);


lpName的取值及其含义:

Constant/valueDescription
SE_ASSIGNPRIMARYTOKEN_NAME TEXT("SeAssignPrimaryTokenPrivilege")

Required to assign the primary token of a process.

User Right: Replace a process-level token.

SE_AUDIT_NAME TEXT("SeAuditPrivilege")

Required to generate audit-log entries. Give this privilege to secure servers.

User Right: Generate security audits.

SE_BACKUP_NAME TEXT("SeBackupPrivilege")

Required to perform backup operations. This privilege causes the system to grant all read access control to any file, regardless of theaccess control list (ACL) specified for the file. Any access request other than read is still evaluated with the ACL. This privilege is required by theRegSaveKey andRegSaveKeyExfunctions. The following access rights are granted if this privilege is held:

  • READ_CONTROL
  • ACCESS_SYSTEM_SECURITY
  • FILE_GENERIC_READ
  • FILE_TRAVERSE

User Right: Back up files and directories.

SE_CHANGE_NOTIFY_NAME TEXT("SeChangeNotifyPrivilege")

Required to receive notifications of changes to files or directories. This privilege also causes the system to skip all traversal access checks. It is enabled by default for all users.

User Right: Bypass traverse checking.

SE_CREATE_GLOBAL_NAME TEXT("SeCreateGlobalPrivilege")

Required to create named file mapping objects in the global namespace during Terminal Services sessions. This privilege is enabled by default for administrators, services, and the local system account.

User Right: Create global objects.

SE_CREATE_PAGEFILE_NAME TEXT("SeCreatePagefilePrivilege")

Required to create a paging file.

User Right: Create a pagefile.

SE_CREATE_PERMANENT_NAME TEXT("SeCreatePermanentPrivilege")

Required to create a permanent object.

User Right: Create permanent shared objects.

SE_CREATE_SYMBOLIC_LINK_NAME TEXT("SeCreateSymbolicLinkPrivilege")

Required to create a symbolic link.

User Right: Create symbolic links.

SE_CREATE_TOKEN_NAME TEXT("SeCreateTokenPrivilege")

Required to create a primary token.

User Right: Create a token object.

You cannot add this privilege to a user account with the "Create a token object" policy. Additionally, you cannot add this privilege to an owned process using Windows APIs.

Windows Server 2003 and Windows XP with SP1 and earlier:Windows APIs can add this privilege to an owned process.

SE_DEBUG_NAME TEXT("SeDebugPrivilege")

Required to debug and adjust the memory of a process owned by another account.

User Right: Debug programs.

SE_ENABLE_DELEGATION_NAME TEXT("SeEnableDelegationPrivilege")

Required to mark user and computer accounts as trusted for delegation.

User Right: Enable computer and user accounts to be trusted for delegation.

SE_IMPERSONATE_NAME TEXT("SeImpersonatePrivilege")

Required to impersonate.

User Right: Impersonate a client after authentication.

SE_INC_BASE_PRIORITY_NAME TEXT("SeIncreaseBasePriorityPrivilege")

Required to increase the base priority of a process.

User Right: Increase scheduling priority.

SE_INCREASE_QUOTA_NAME TEXT("SeIncreaseQuotaPrivilege")

Required to increase the quota assigned to a process.

User Right: Adjust memory quotas for a process.

SE_INC_WORKING_SET_NAME TEXT("SeIncreaseWorkingSetPrivilege")

Required to allocate more memory for applications that run in the context of users.

User Right: Increase a process working set.

SE_LOAD_DRIVER_NAME TEXT("SeLoadDriverPrivilege")

Required to load or unload a device driver.

User Right: Load and unload device drivers.

SE_LOCK_MEMORY_NAME TEXT("SeLockMemoryPrivilege")

Required to lock physical pages in memory.

User Right: Lock pages in memory.

SE_MACHINE_ACCOUNT_NAME TEXT("SeMachineAccountPrivilege")

Required to create a computer account.

User Right: Add workstations to domain.

SE_MANAGE_VOLUME_NAME TEXT("SeManageVolumePrivilege")

Required to enable volume management privileges.

User Right: Manage the files on a volume.

SE_PROF_SINGLE_PROCESS_NAME TEXT("SeProfileSingleProcessPrivilege")

Required to gather profiling information for a single process.

User Right: Profile single process.

SE_RELABEL_NAME TEXT("SeRelabelPrivilege")

Required to modify the mandatory integrity level of an object.

User Right: Modify an object label.

SE_REMOTE_SHUTDOWN_NAME TEXT("SeRemoteShutdownPrivilege")

Required to shut down a system using a network request.

User Right: Force shutdown from a remote system.

SE_RESTORE_NAME TEXT("SeRestorePrivilege")

Required to perform restore operations. This privilege causes the system to grant all write access control to any file, regardless of the ACL specified for the file. Any access request other than write is still evaluated with the ACL. Additionally, this privilege enables you to set any valid user or group SID as the owner of a file. This privilege is required by theRegLoadKey function. The following access rights are granted if this privilege is held:

  • WRITE_DAC
  • WRITE_OWNER
  • ACCESS_SYSTEM_SECURITY
  • FILE_GENERIC_WRITE
  • FILE_ADD_FILE
  • FILE_ADD_SUBDIRECTORY
  • DELETE

User Right: Restore files and directories.

SE_SECURITY_NAME TEXT("SeSecurityPrivilege")

Required to perform a number of security-related functions, such as controlling and viewing audit messages. This privilege identifies its holder as a security operator.

User Right: Manage auditing and security log.

SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege")

Required to shut down a local system.

User Right: Shut down the system.

SE_SYNC_AGENT_NAME TEXT("SeSyncAgentPrivilege")

Required for a domain controller to use the Lightweight Directory Access Protocol directory synchronization services. This privilege enables the holder to read all objects and properties in the directory, regardless of the protection on the objects and properties. By default, it is assigned to the Administrator and LocalSystem accounts on domain controllers.

User Right: Synchronize directory service data.

SE_SYSTEM_ENVIRONMENT_NAME TEXT("SeSystemEnvironmentPrivilege")

Required to modify the nonvolatile RAM of systems that use this type of memory to store configuration information.

User Right: Modify firmware environment values.

SE_SYSTEM_PROFILE_NAME TEXT("SeSystemProfilePrivilege")

Required to gather profiling information for the entire system.

User Right: Profile system performance.

SE_SYSTEMTIME_NAME TEXT("SeSystemtimePrivilege")

Required to modify the system time.

User Right: Change the system time.

SE_TAKE_OWNERSHIP_NAME TEXT("SeTakeOwnershipPrivilege")

Required to take ownership of an object without being granted discretionary access. This privilege allows the owner value to be set only to those values that the holder may legitimately assign as the owner of an object.

User Right: Take ownership of files or other objects.

SE_TCB_NAME TEXT("SeTcbPrivilege")

This privilege identifies its holder as part of the trusted computer base. Some trusted protected subsystems are granted this privilege.

User Right: Act as part of the operating system.

SE_TIME_ZONE_NAME TEXT("SeTimeZonePrivilege")

Required to adjust the time zone associated with the computer's internal clock.

User Right: Change the time zone.

SE_TRUSTED_CREDMAN_ACCESS_NAME TEXT("SeTrustedCredManAccessPrivilege")

Required to access Credential Manager as a trusted caller.

User Right: Access Credential Manager as a trusted caller.

SE_UNDOCK_NAME TEXT("SeUndockPrivilege")

Required to undock a laptop.

User Right: Remove computer from docking station.

SE_UNSOLICITED_INPUT_NAME TEXT("SeUnsolicitedInputPrivilege")

Required to read unsolicited input from a terminal device.

User Right: Not applicable.



参考:

MSDN Library

http://www.cnblogs.com/94cool/archive/2012/10/30/2745785.html

http://blog.youkuaiyun.com/fbmly/article/details/5442965

http://baike.baidu.com/link?url=AzXy27AIFWnhCKzJ-HthRIhqoox4LzO5xRubc-UQ9G_XKrnOHu_PA6eR8IIgFUZy35GR2n-qbkOsEm4Vr_05Ca

<think>我们在讨论C++中的进程技术。进程通常指一个进程获得比当前更高的限,例如从普通用户升到管理员或系统限。在Windows和Linux系统中,实现方式有所不同。由于用户没有指定操作系统,我们将分别讨论两种环境。 ### Windows环境下的进程 在Windows中,通常涉及以下步骤: 1. 获取进程令牌(token) 2. 启用令牌中的限 3. 创建具有限的新进程 #### 示例:使用`CreateProcessWithTokenW`或`CreateProcessAsUser` 以下是一个使用`CreateProcessAsUser`创建具有进程的示例步骤: ```cpp #include <windows.h> #include <iostream> BOOL CreateElevatedProcess(LPWSTR lpszExecutable) { HANDLE hToken; HANDLE hNewToken; // 获取当前进程令牌 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken)) { std::cerr << "OpenProcessToken failed: " << GetLastError() << std::endl; return FALSE; } // 创建主令牌的副本 if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hNewToken)) { std::cerr << "DuplicateTokenEx failed: " << GetLastError() << std::endl; CloseHandle(hToken); return FALSE; } // 设置令牌限,这里启用SE_DEBUG_NAME(通常用于调试限,但注意:实际可能需要其他限) LUID luid; if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { std::cerr << "LookupPrivilegeValue failed: " << GetLastError() << std::endl; CloseHandle(hNewToken); CloseHandle(hToken); return FALSE; } TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hNewToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { std::cerr << "AdjustTokenPrivileges failed: " << GetLastError() << std::endl; CloseHandle(hNewToken); CloseHandle(hToken); return FALSE; } // 创建进程 STARTUPINFOW si = { sizeof(si) }; PROCESS_INFORMATION pi; if (!CreateProcessAsUserW(hNewToken, NULL, lpszExecutable, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { std::cerr << "CreateProcessAsUserW failed: " << GetLastError() << std::endl; CloseHandle(hNewToken); CloseHandle(hToken); return FALSE; } CloseHandle(hNewToken); CloseHandle(hToken); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return TRUE; } int main() { // 示例:启动一个限的cmd.exe if (CreateElevatedProcess(L"C:\\Windows\\System32\\cmd.exe")) { std::cout << "Elevated process started successfully." << std::endl; } else { std::cerr << "Failed to start elevated process." << std::endl; } return 0; } ``` 注意:上述代码需要进程本身已经具有足够的限(例如以管理员身份运行)才能成功复制令牌并创建新进程。如果当前进程没有管理员限,则可能失败。 #### 使用ShellExecuteEx以管理员身份运行程序 另一种常见方法是使用`ShellExecuteEx`函数,并指定`runas`操作,这会触发UAC示,要求用户确认限。 ```cpp #include <windows.h> #include <shellapi.h> #include <iostream> int main() { SHELLEXECUTEINFO sei = { sizeof(sei) }; sei.lpVerb = L"runas"; // 请求限 sei.lpFile = L"notepad.exe"; // 要运行的程序 sei.hwnd = NULL; sei.nShow = SW_NORMAL; if (!ShellExecuteEx(&sei)) { DWORD err = GetLastError(); if (err == ERROR_CANCELLED) { std::cerr << "User denied the elevation." << std::endl; } else { std::cerr << "ShellExecuteEx failed: " << err << std::endl; } return 1; } return 0; } ``` 这种方法会弹出UAC对话框,需要用户交互确认。 ### Linux环境下的进程 在Linux中,通常通过以下方式: 1. 设置SUID位:程序文件设置SUID位后,运行时会以文件所有者的限运行。 2. 使用`sudo`:在代码中调用`sudo`命令执行特定程序(需要用户有sudo限且输入密码)。 3. 能力(Capabilities):Linux内核2.2之后引入的能力机制,允许对进程限进行更细粒度的控制。 #### 示例:设置SUID 假设我们有一个需要的程序,编译后将其所有者设置为root,并设置SUID位。 ```cpp // 示例程序:elevated_program.cpp #include <iostream> #include <unistd.h> int main() { uid_t uid = getuid(); uid_t euid = geteuid(); std::cout << "UID: " << uid << ", EUID: " << euid << std::endl; // 如果设置了SUID,则EUID为0(root) if (euid == 0) { // 执行需要root限的操作 std::cout << "Running with root privileges." << std::endl; } else { std::cerr << "Insufficient privileges." << std::endl; return 1; } return 0; } ``` 编译并设置SUID: ```bash g++ elevated_program.cpp -o elevated_program sudo chown root:root elevated_program sudo chmod u+s elevated_program ``` 然后普通用户运行`./elevated_program`时,有效用户ID(EUID)将是root。 #### 使用能力(Capabilities) 例如,给一个程序赋予`CAP_NET_ADMIN`能力: ```bash sudo setcap cap_net_admin=eip ./program ``` 在程序中,可以使用`prctl`或`cap_get_proc`等函数来管理能力。 ### 安全注意事项 进程操作需要非常谨慎,因为不当使用可能导致安全漏洞。在Windows中,操作通常需要用户交互(如UAC确认)或进程本身已具有较高限。在Linux中,SUID程序必须经过严格测试,避免缓冲区溢出等漏洞,否则可能被利用进行非法。 ### 引用说明 在Windows中,攻击者常通过创建或修改服务来实现升[^1]。此外,Android平台也曾存在通过漏洞实现升的案例[^2]。在代码实现中,第三方库的使用和代码混淆也是常见的技术[^3],但本文主要关注原生C++实现。 §§相关问题§§ 1. Windows中如何绕过UAC实现静默? 2. Linux中SUID程序的安全风险有哪些? 3. 如何防止进程被恶意利用?</think>### C++ 进程技术详解 在 C++ 中实现进程(Privilege Escalation)主要涉及操作系统限管理机制。以下是 Windows 和 Linux 环境下的核心技术与实现方法: --- #### **Windows 环境技术** 1. **令牌限调整 (Token Privilege Adjustment)** 通过修改进程令牌启用特: ```cpp #include <windows.h> BOOL EnablePrivilege(LPCTSTR privilege) { HANDLE hToken; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE; TOKEN_PRIVILEGES tp; LUID luid; LookupPrivilegeValue(NULL, privilege, &luid); tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; BOOL result = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); CloseHandle(hToken); return (result && GetLastError() == ERROR_SUCCESS); } // 使用示例:启用调试限 EnablePrivilege(SE_DEBUG_NAME); ``` 2. **服务控制管理器 (Service Control Manager)** 创建高限服务实现: ```cpp SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); SC_HANDLE svc = CreateService( scm, "MySvc", "My Service", SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, "C:\\malware.exe", NULL, NULL, NULL, NULL, NULL ); StartService(svc, 0, NULL); ``` > 攻击者常通过创建/修改服务实现限维持[^1] 3. **UAC 绕过技术** 利用白名单程序: ```cpp SHELLEXECUTEINFO sei = { sizeof(sei) }; sei.lpVerb = "runas"; // 触发UAC弹窗 sei.lpFile = "cmd.exe"; sei.nShow = SW_SHOW; ShellExecuteEx(&sei); ``` > 静默绕过需利用如`CMSTP.exe`等白名单程序 --- #### **Linux 环境技术** 1. **SUID/SGID 利用** 设置二进制文件的 SUID 位: ```bash chmod u+s /path/to/binary # 设置SUID ``` ```cpp // 检查并利用SUID if (geteuid() == 0) { // 有效UID为0 (root) system("/bin/bash"); } ``` 2. **能力(Capabilities)机制** 赋予程序特定特: ```cpp #include <sys/capability.h> cap_t caps = cap_get_proc(); cap_value_t cap_list[] = {CAP_NET_RAW}; cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET); cap_set_proc(caps); ``` 3. **内核漏洞利用** 如 Dirty COW 漏洞利用: ```cpp // 伪代码示例 void exploit() { map_writeable("/etc/passwd"); // 修改敏感文件 add_root_user(); // 添加root用户 } ``` --- ### **安全实践与防御** 1. **最小限原则** 始终以最低必要限运行进程 2. **输入验证** 严格过滤外部输入,防止注入攻击 3. **沙箱隔离** 使用容器或沙箱技术限制进程限 4. **代码签名** 验证可执行文件的数字签名 > 注意:技术可能违反安全策略,仅限授测试使用。Android 平台也曾因媒体服务器漏洞导致零[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值