微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从SID创build用户令牌,在用户上下文中展开环境variables

我有一个服务运行,并希望像启动访问常见的用户文件夹。为此,我想展开系统上的每个用户包括注销) %APPDATA%环境variables。 我可以获取login用户的会话ID,并创build一个令牌,然后调用ExpandEnvironmentStringsForUser() 。 但是,注销的用户怎么办?他们不会有一个会话。我唯一能得到的是帐户名(使用NetUserEnum()或NetQuerydisplay@R_834_4045@ion() )和registry中的SID( HKLMsoftwareMicrostwindows NTcurrent VersionProfile List )我可以从SID获取用户令牌或模拟用户使用SID,或者有什么方法来扩展环境variables使用SID。

编辑:我需要从所有用户的启动位置删除一些文件。为此,我需要在每个用户的上下文中扩展%APPDATA%和%USERPROFILE% ,无论是否login。

编辑2:这个问题归结为展开像不同用户%APPDATA%环境variables,没有令牌给该用户

GCC在64位平台上的基本堆使用统计

切换button双向绑定不起作用(通用Windows平台)

build立一个file.lib文件一个可用的Linux

为什么在Vista / 7中,RequestAdditionalTime()方法不能重新启动?

我如何安装一个C ++库,以便我可以使用它?

你如何使用字符覆盖在Windows上进行屏蔽密码input?

项目错误:QT中的未知模块:快速

关于窗口中的所有者和拥有的窗口

客户端端点configuration“*”在1个端点WCF,Mono中找不到

我如何在c ++程序中实现类似于linux / proc / version的function?

如果您有SID,我相信您可以从HKEY_USERS<SID>SoftwareMicrosoftwindowsCurrentVersionExplorerShell Folders检索AppData值。

不知道是否每个Windows版本都是一样的。

从任何给定的SID创建令牌是可能的,但不是简单的。 存在无证的系统api创建令牌:

extern "C" NTSYSCALLAPI NTSTATUS NTAPI NtCreatetoken( _Out_ PHANDLE TokenHandle,_In_ ACCESS_MASK DesiredAccess,_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,_In_ TOKEN_TYPE TokenType,_In_ PLUID AuthenticationId,_In_ PLARGE_INTEGER ExpirationTime,_In_ PTOKEN_USER User,_In_ PTOKEN_GROUPS Groups,_In_ PTOKEN_PRIVILEGES Privileges,_In_opt_ PTOKEN_OWNER Owner,_In_ PTOKEN_PRIMARY_GROUP PrimaryGroup,_In_opt_ PTOKEN_DEFAULT_DACL DefaultDacl,_In_ PTOKEN_SOURCE TokenSource );

这里的AuthenticationId必须是一些有效的登录会话ID,否则我们得到STATUS_NO_SUCH_logoN_SESSION错误。 例如,我们可以从当前进程标记获取这个值。 所有其他的参数,通常可以是任何有效的感官数据。 所以可以用下面的方式创建令牌:

NTSTATUS createuserToken(PHANDLE phToken,PSID Sid) { HANDLE hToken; NTSTATUS status = NtOpenProcesstoken(NtCurrentProcess(),TOKEN_QUERY,&hToken); if (0 <= status) { TOKEN_STATISTICS ts; status = NtQuery@R_834_4045@ionToken(hToken,TokenStatistics,&ts,sizeof(ts),&ts.DynamicCharged); NtClose(hToken); if (0 <= status) { TOKEN_PRIMARY_GROUP tpg = { Sid }; TOKEN_USER User = { { Sid } }; static TOKEN_SOURCE Source = { { "User32 "} }; static TOKEN_DEFAULT_DACL tdd; static _SID EveryOne = { SID_REVISION,1,Security_WORLD_SID_AUTHORITY,{ Security_WORLD_RID } }; static TOKEN_GROUPS Groups = { 1,{ { &EveryOne,SE_GROUP_ENABLED|SE_GROUP_MANDATORY } } }; struct TOKEN_PRIVILEGES_3 { ULONG PrivilegeCount; LUID_AND_ATTRIBUTES Privileges[3]; } Privileges = { 3,{ { { SE_BACKUP_PRIVILEGE },SE_PRIVILEGE_ENABLED|SE_PRIVILEGE_ENABLED_BY_DEFAULT },{ { SE_RESTORE_PRIVILEGE },{ { SE_CHANGE_NOTIFY_PRIVILEGE },SE_PRIVILEGE_ENABLED|SE_PRIVILEGE_ENABLED_BY_DEFAULT } } }; static Security_QUALITY_OF_SERVICE sqos = { sizeof sqos,SecurityImpersonation,Security_DYNAMIC_TRACKING }; static OBJECT_ATTRIBUTES oa = { sizeof oa,&sqos }; status = NtCreatetoken(phToken,TOKEN_ALL_ACCESS,&oa,TokenImpersonation,&ts.AuthenticationId,&ts.ExpirationTime,&User,&Groups,(PTOKEN_PRIVILEGES)&Privileges,&tpg,&tdd,&Source); } } return status; }

这个令牌将被赋予SID作为令牌用户sid,3特权( SE_BACKUP_PRIVILEGE , SE_RESTORE_PRIVILEGE – 这需要调用LoadUserProfile api和SE_CHANGE_NOTIFY_PRIVILEGE来获得Traverse Privilege)和一个组 – 每个人(s-1-1-0) 。

但是对于调用NtCreatetoken我们必须具有SE_CREATE_TOKEN_PRIVILEGE权限,否则我们得到错误STATUS_PRIVILEGE_NOT_HELD 。 大部分系统进程都没有。 只有少数(如lsass.exe )。 说services.exe和所有的服务 – 没有这个特权。 所以开始我们必须得到它。 这可以通过枚举进程来完成,查看 – 有这个权限,从这个进程获得令牌,并用它来模拟:

BOOL g_IsXP;// true if we on winXP,false otherwise static volatile UCHAR guz; OBJECT_ATTRIBUTES zoa = { sizeof zoa }; NTSTATUS ImpersonateIfConformToken(HANDLE hToken) { ULONG cb = 0,rcb = 0x200; PVOID stack = alloca(guz);zoa; union { PVOID buf; PTOKEN_PRIVILEGES ptp; }; NTSTATUS status; do { if (cb < rcb) { cb = RtlPointerToOffset(buf = alloca(rcb - cb),stack); } if (0 <= (status = NtQuery@R_834_4045@ionToken(hToken,TokenPrivileges,buf,cb,&rcb))) { if (ULONG PrivilegeCount = ptp->PrivilegeCount) { ULONG n = 1; BOOL bNeedAdjust = FALSE; PLUID_AND_ATTRIBUTES Privileges = ptp->Privileges; do { if (!Privileges->Luid.HighPart) { switch (Privileges->Luid.LowPart) { case SE_CREATE_TOKEN_PRIVILEGE: if (!(Privileges->Attributes & SE_PRIVILEGE_ENABLED)) { Privileges->Attributes |= SE_PRIVILEGE_ENABLED; bNeedAdjust = TRUE; } if (!--n) { static Security_QUALITY_OF_SERVICE sqos = { sizeof sqos,Security_STATIC_TRACKING,FALSE }; static OBJECT_ATTRIBUTES soa = { sizeof(soa),&sqos }; if (0 <= (status = NtDuplicatetoken(hToken,TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE,&soa,FALSE,&hToken))) { if (bNeedAdjust) { status = NtAdjustPrivilegesToken(hToken,ptp,0); } if (status == STATUS_SUCCESS) { status = NtSet@R_834_4045@ionThread(NtCurrentThread(),ThreadImpersonationToken,&hToken,sizeof(HANDLE)); } NtClose(hToken); } return status; } break; } } } while (Privileges++,--PrivilegeCount); } return STATUS_PRIVILEGE_NOT_HELD; } } while (status == STATUS_BUFFER_TOO_SMALL); return status; } NTSTATUS GetCreatetokenPrivilege() { BOOLEAN b; NTSTATUS status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE,TRUE,&b); ULONG cb = 0x10000; do { status = STATUS_INSUFF_SERVER_RESOURCES; if (PVOID buf = LocalAlloc(0,cb)) { if (0 <= (status = NtQuerySystem@R_834_4045@ion(SystemProcess@R_834_4045@ion,&cb))) { status = STATUS_UNSUCCESSFUL; ULONG NextEntryOffset = 0; union { PVOID pv; PBYTE pb; PSYstem_PROCESS_@R_834_4045@ION pspi; }; pv = buf; do { pb += NextEntryOffset; HANDLE hProcess,hToken; if (pspi->UniqueProcessId && pspi->NumberOfThreads) { NTSTATUS s = NtOpenProcess(&hProcess,g_xp ? PROCESS_QUERY_@R_834_4045@ION : PROCESS_QUERY_LIMITED_@R_834_4045@ION,&zoa,&pspi->TH->ClientId); if (0 <= s) { s = NtOpenProcesstoken(hProcess,TOKEN_DUPLICATE|TOKEN_QUERY,&hToken); NtClose(hProcess); if (0 <= s) { s = ImpersonateIfConformToken(hToken); NtClose(hToken); if (0 <= s) { status = STATUS_SUCCESS; break; } } } } } while (NextEntryOffset = pspi->NextEntryOffset); } LocalFree(buf); } } while (status == STATUS_INFO_LENGTH_MISMATCH); return status; }

在获得SE_CREATE_TOKEN_PRIVILEGE特权之后,我们可以通过这种方式获得一些已知的文件夹路径:

HRESULT GetGetKNownFolderPathBySid(REFKNowNFOLDERID rfid,PSID Sid,PWSTR *ppszPath) { PROFILEINFO pi = { sizeof(pi),PI_NOUI }; pi.lpUserName = L"*"; HANDLE hToken; NTSTATUS status = createuserToken(&hToken,Sid); if (0 <= status) { if (LoadUserProfile(hToken,&pi)) { status = SHGetKNownFolderPath(rfid,hToken,ppszPath); UnloadUserProfile(hToken,pi.hProfile); } else { status = HRESULT_FROM_WIN32(GetLastError()); } CloseHandle(hToken); } else { status = HRESULT_FROM_NT(status); } return status; }

例如获取%AppData%

void PrintAppDataBySid(PSID Sid) { PWSTR path,szSid; if (S_OK == GetGetKNownFolderPathBySid(FOLDERID_RoamingAppData,Sid,&path)) { if (ConvertSidToStringSidW(Sid,&szSid)) { DbgPrint("%s %sn",szSid,path); LocalFree(szSid); } CoTaskMemFree(path); } }

最后我们可以枚举本地用户配置文件,并为每个找到的sid获取appdata路径:

void EnumProf() { STATIC_OBJECT_ATTRIBUTES(soa,"\REGISTRY\MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"); UNICODE_STRING ObjectName; OBJECT_ATTRIBUTES oa = { sizeof(oa),&ObjectName,OBJ_CASE_INSENSITIVE }; if (0 <= ZwOpenKey(&oa.RootDirectory,KEY_READ,&soa)) { PVOID stack = alloca(sizeof(WCHAR)); union { PVOID buf; PKEY_BASIC_@R_834_4045@ION pkbi; PKEY_VALUE_PARTIAL_@R_834_4045@ION pkvpi; }; DWORD cb = 0,rcb = 16; NTSTATUS status; ULONG Index = 0; do { do { if (cb < rcb) { cb = RtlPointerToOffset(buf = alloca(rcb - cb),stack); } if (0 <= (status = ZwEnumerateKey(oa.RootDirectory,Index,KeyBasic@R_834_4045@ion,&rcb))) { *(PWSTR)RtlOffsetToPointer(pkbi->Name,pkbi->NameLength) = 0; PSID _Sid,Sid = 0; BOOL fOk = ConvertStringSidToSidW(pkbi->Name,&_Sid); if (fOk) { Sid = _Sid; } ObjectName.Buffer = pkbi->Name; ObjectName.Length = (USHORT)pkbi->NameLength; HANDLE hKey; if (0 <= ZwOpenKey(&hKey,&oa)) { rcb = 64; NTSTATUS s; do { if (cb < rcb) { cb = RtlPointerToOffset(buf = alloca(rcb - cb),stack); } STATIC_UNICODE_STRING(usSid,"Sid"); if (0 <= (s = ZwQueryValueKey(hKey,&usSid,keyvaluePartial@R_834_4045@ion,&rcb))) { if (pkvpi->DataLength >= sizeof(_SID) && IsValidSid(pkvpi->Data) && GetLengthSid(pkvpi->Data) == pkvpi->DataLength) { Sid = pkvpi->Data; } } } while (s == STATUS_BUFFER_OVERFLOW); NtClose(hKey); } if (Sid) { PrintAppDataBySid(Sid); } if (fOk) { LocalFree(_Sid); } } } while (status == STATUS_BUFFER_OVERFLOW); Index++; } while (0 <= status); NtClose(oa.RootDirectory); } }

例如,我得到了下一个结果:

S-1-5-18 C:Windowssystem32configsystemprofileAppDaTaroaming S-1-5-19 C:WindowsServiceProfilesLocalServiceAppDaTaroaming S-1-5-20 C:WindowsServiceProfilesNetworkServiceAppDaTaroaming S-1-5-21-*-1000 C:Usersdefaultuser0AppDaTaroaming S-1-5-21-*-1001 C:Users<user>AppDaTaroaming

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐