首页 > Windows开发 > 模拟Windows登录用户进行特殊操作

模拟Windows登录用户进行特殊操作

SYSTEM权限(服务启动程序)下如何读写当前登录用户相关的数据(桌面、开始菜单、注册表等等)?管理员权限如何提升到SYSTEM权限进行一些特殊的操作(一些关键的注册表位置、创建一个SYSTEM权限的进程等等)?一个非常关键的API就是ImpersonateLoggedOnUser,可以让当前线程模拟登陆用户进行操作(当然还可以从管理员模拟SYSTEM权限),用完之后记得调用RevertToSelf。

没有进行什么总结了,懒得写了⊙﹏⊙,贴几个地址吧:
服务应用程序如何访问当前登录用户的信息
模拟用户登录
创建高权限进程
从管理员身份获得 SYSTEM 权限的四种方法
如何读取指定用户的 HKEY_CURRENT_USER 注册表键
DLL注入到system进程后(在SYSTEM权限下弹MessageBox?)

照着从管理员权限到SYSTEM权限写了段代码:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <TlHelp32.h>
#include <AclAPI.h>
 
#pragma comment(lib, "advapi32.lib")
 
#define CHECK_NULL_RET(bCondition) if (!bCondition) goto Exit0
#define INVALID_PROCESS_ID -2
 
BOOL EnableProcessPrivilege(LPCTSTR lpszPrivName, BOOL bEnable = TRUE)
{
    HANDLE hToken; 
    TOKEN_PRIVILEGES tkp;
    BOOL bRet = FALSE;
 
    bRet = OpenProcessToken(GetCurrentProcess(), 
                TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
    CHECK_NULL_RET(bRet);
 
    bRet = LookupPrivilegeValue(NULL, lpszPrivName, &tkp.Privileges[0].Luid);
    CHECK_NULL_RET(bRet);
    tkp.PrivilegeCount = 1;  
    tkp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED; 
 
    bRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
    CHECK_NULL_RET(bRet);
    bRet = TRUE;
 
Exit0:
    CloseHandle(hToken);
    return bRet;
}
 
DWORD GetProcessPidByName(LPCTSTR lpszProcName)
{
    DWORD dwPid = INVALID_PROCESS_ID;
    HANDLE hSnapshot = INVALID_HANDLE_VALUE;
    PROCESSENTRY32 pe32 = {0};
    pe32.dwSize = sizeof(PROCESSENTRY32);
 
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (hSnapshot != INVALID_HANDLE_VALUE)
    {
        Process32First(hSnapshot, &pe32);
        do 
        {
            if (!lstrcmpi(lpszProcName, pe32.szExeFile))
            {
                dwPid = pe32.th32ProcessID;
                break;
            }
            pe32.dwSize = sizeof(PROCESSENTRY32);
        } while (Process32Next(hSnapshot, &pe32));
        CloseHandle(hSnapshot);
    }
 
    return dwPid;
}
 
BOOL AdjustPrivilege(HANDLE hToken, DWORD dwAccess)
{
    BOOL bRet = FALSE;
    PSECURITY_DESCRIPTOR pOldSd = NULL, pNewSd = NULL;
    DWORD dwLen = 0;
    DWORD dwReturn = 0;
    DWORD dwRet = 0;
    BOOL bAcl = FALSE, bDefAcl = FALSE;
    PACL pOldAcl = NULL;
    PACL pNewAcl = NULL;
    PACL pSacl = NULL;
    static TCHAR szUserName[1024] = {0};
    EXPLICIT_ACCESS ea = {0};
    DWORD dwDaclSize = 0;
    DWORD dwSaclSize = 0;
    DWORD dwOwnerSize = 0;
    DWORD dwPrimaryGroupSize = 0;
    PSID pSidOwner = NULL;
    PSID pPrimaryGroup = NULL;
 
    GetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, 
        pOldSd, NULL, &dwLen);
    pOldSd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
        HEAP_ZERO_MEMORY, dwLen);
    CHECK_NULL_RET(pOldSd);
    bRet = GetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION,
        pOldSd, dwLen, &dwReturn);
    CHECK_NULL_RET(bRet);
    bRet = GetSecurityDescriptorDacl(pOldSd, &bAcl, &pOldAcl, &bDefAcl);
    CHECK_NULL_RET(bRet);
 
    dwReturn = sizeof(szUserName) / sizeof(szUserName[0]);
    GetUserName(szUserName, &dwReturn);
    BuildExplicitAccessWithName(&ea, szUserName,
        dwAccess, GRANT_ACCESS, NULL);
    dwRet = SetEntriesInAcl(1, &ea, pOldAcl, &pNewAcl);
    CHECK_NULL_RET((dwRet == ERROR_SUCCESS));
 
    MakeAbsoluteSD( pOldSd,
                    pNewSd,
                    &dwLen,
                    pOldAcl,
                    &dwDaclSize,
                    pSacl,
                    &dwSaclSize,
                    pSidOwner,
                    &dwOwnerSize,
                    pPrimaryGroup,
                    &dwPrimaryGroupSize);
    pOldAcl = (PACL)HeapAlloc(
                        GetProcessHeap(),
                        HEAP_ZERO_MEMORY,
                        dwDaclSize);
    CHECK_NULL_RET(pOldAcl);
    pSacl = (PACL)HeapAlloc(
                        GetProcessHeap(),
                        HEAP_ZERO_MEMORY,
                        dwSaclSize);
    CHECK_NULL_RET(pSacl);
    pSidOwner = (PSID)HeapAlloc(
                        GetProcessHeap(),
                        HEAP_ZERO_MEMORY,
                        dwOwnerSize);
    CHECK_NULL_RET(pSidOwner);
    pPrimaryGroup = (PSID)HeapAlloc(
                        GetProcessHeap(),
                        HEAP_ZERO_MEMORY,
                        dwPrimaryGroupSize);
    CHECK_NULL_RET(pPrimaryGroup);
    pNewSd = (PSECURITY_DESCRIPTOR)HeapAlloc(
                        GetProcessHeap(),
                        HEAP_ZERO_MEMORY,
                        dwLen);
    CHECK_NULL_RET(pNewSd);
 
    bRet = MakeAbsoluteSD(  pOldSd,
                            pNewSd,
                            &dwLen,
                            pOldAcl,
                            &dwDaclSize,
                            pSacl,
                            &dwSaclSize,
                            pSidOwner,
                            &dwOwnerSize,
                            pPrimaryGroup,
                            &dwPrimaryGroupSize);
    CHECK_NULL_RET(bRet);
 
    bRet = SetSecurityDescriptorDacl(
                pNewSd, bAcl, pNewAcl, bDefAcl);
    CHECK_NULL_RET(bRet);
    bRet = SetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pNewSd);
    CHECK_NULL_RET(bRet);
    bRet = TRUE;
 
Exit0:
    if (pOldSd != NULL) HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, pOldSd);
    if (pOldAcl != NULL) HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, pOldAcl);
    if (pSacl != NULL) HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, pSacl);
    if (pSidOwner != NULL) HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, pSidOwner);
    if (pPrimaryGroup != NULL) HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, pPrimaryGroup);
    if (pNewSd != NULL) HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, pNewSd);
 
    return bRet;
}
 
BOOL PrivilegeExecStart(LPCTSTR lpszProcName, LPTSTR lpszCmdLine)
{
    BOOL bRet = FALSE;
    HANDLE hProcess = INVALID_HANDLE_VALUE;
    HANDLE hToken = NULL;
    HANDLE hNewToken = NULL;
    DWORD dwPid = 0;
    STARTUPINFO si = {0};
    PROCESS_INFORMATION pi = {0};
 
    bRet = EnableProcessPrivilege(SE_DEBUG_NAME, TRUE);
    CHECK_NULL_RET(bRet);
 
    dwPid = GetProcessPidByName(lpszProcName);
    CHECK_NULL_RET((dwPid != INVALID_PROCESS_ID));
 
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);
    CHECK_NULL_RET(hProcess);
 
    bRet = OpenProcessToken(hProcess, READ_CONTROL | WRITE_DAC, &hToken);
    CHECK_NULL_RET(bRet);
 
    bRet = AdjustPrivilege(hToken, TOKEN_ALL_ACCESS);
    CHECK_NULL_RET(bRet);
 
    bRet = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken);
    CHECK_NULL_RET(bRet);
 
    bRet = DuplicateTokenEx(
                hToken, 
                TOKEN_ALL_ACCESS,
                NULL,
                SecurityImpersonation,
                TokenPrimary,
                &hNewToken);
    CHECK_NULL_RET(bRet);
 
    si.cb = sizeof(STARTUPINFO);
    bRet = ImpersonateLoggedOnUser(hNewToken);
    CHECK_NULL_RET(bRet);
    bRet = CreateProcessAsUser(
                hToken,
                lpszCmdLine,
                NULL,
                NULL,
                NULL,
                FALSE,
                NULL,
                NULL,
                NULL,
                &si,
                &pi);
    CHECK_NULL_RET(bRet);
    bRet = TRUE;
 
Exit0:
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    CloseHandle(hToken);
    CloseHandle(hNewToken);
    CloseHandle(hProcess);
 
    return bRet;
}
 
BOOL PrivilegeExecStop(void)
{
    return RevertToSelf();
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    TCHAR szCmdLine[MAX_PATH] = TEXT("C:\\Windows\\regedit.exe");
    if (PrivilegeExecStart(TEXT("lsass.exe"), szCmdLine))
    {
        PrivilegeExecStop();
    }
    return 0;
}

效果截图:
从管理员权限获取SYSTEM权限


觉得文章还不错?点击此处对作者进行打赏!


本文地址: 程序人生 >> 模拟Windows登录用户进行特殊操作
作者:代码疯子(Wins0n) 本站内容如无声明均属原创,转载请保留作者信息与原文链接,谢谢!


更多



  1. 2012年8月21日22:19 | #1

    不错,这种研究应该很有意思。 [em021]

    [回复]

    代码疯子 回复:

    @the5fire, 小技巧而已,谈不上研究 [em020]

    [回复]

  2. angle1b622
    2012年9月12日23:26 | #2

    在win7 下试验了下怎么不能提升权限呢?希望博主给指点下

    [回复]

    代码疯子 回复:

    @angle1b622, OpenProcessToken READ_CONTROL | WRITE_DAC 的时候提示拒绝访问 具体原因还不清楚

    [回复]

  3. huiyin
    2012年10月18日16:17 | #3

    WIN7下要如何才能做到呢?

    [回复]

    代码疯子 回复:

    @huiyin, 抱歉,我也不知道,当初测试的时候是XP,现在没什么时间找原因了

    [回复]

    huiyin 回复:

    @代码疯子, 原因我找到了,是因为WIN7的机制不同,Win7采用了会话0隔离的安全模型。无论用户是否通过控制台进行登录,只有系统服务运行在会话0当中,而其余的应用程序都运行在会话1当中,这就将应用程序与系统服务之间进行了相对隔离。当某个恶意程序试图攻击操作系统时,也无法直接与Win 7的系统服务进行通信。

    [回复]

    代码疯子 回复:

    @huiyin, 这就是说在Win7下不可行咯?谢谢你对本文的继续关注。我原来写这篇文章纯粹是为了体验下ImpersonateLoggedOnUser这个API,其实对ACL不甚了解

    [回复]

    huiyin 回复:

    @代码疯子, WIN7上也是可以的。WTSGetActiveConsoleSessionId获得用户会话ID,在原基础上,创建模拟令牌后,用SetTokenInformation,把会话ID加上即可。WINDOWS2008 R2 就不知道什么原因了,还未找到相关资料

    [回复]

    jinchx 回复:

    @huiyin, “创建模拟令牌后,用SetTokenInformation,把会话ID加上即可。” 具体怎么做呢?
    而且本来楼主的代码在创建模拟令牌时会返回 Error 5,又怎么在创建后加上会话ID呢?
    我目前对这些几乎不了解,只是目前需要实现以其他用户身份启动进程。求指导

    [回复]

    23424 回复:

    @huiyin, 希望能指教,不知目前此方法还可行不?

    [回复]

  1. 本文目前尚无任何 trackbacks 和 pingbacks.