use*_*024 5 c windows security impersonation sandbox
我正在创建一个可能非常容易受到攻击的Windows服务器程序.我想沙箱(jail?)它或者至少以非常低的完整性设置运行我的进程.我可能很高兴刚开始这个过程:
SAFER_LEVEL_HANDLE hSaferLevel = NULL;
HANDLE hToken = NULL;
SaferCreateLevel(SAFER_SCOPEID_USER,SAFER_LEVELID_UNTRUSTED,0,&hSaferLevel,NULL);
SaferComputeTokenFromLevel(hSaferLevel, NULL, &hToken, 0, NULL);
CreateProcessAsUser(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
Run Code Online (Sandbox Code Playgroud)
它可能仍然容易受到一些攻击,但我会更容易入睡这种保护.现在这是问题,我的进程使用一个至少需要正常级别来初始化的DLL.
一旦完成初始化,我ImpersonateLoggedOnUser(hToken)
就没问题,但是对于有人注入代码很容易RevertToSelf()
.一旦我冒充使用权限减少的匿名用户,我试图找到阻止恢复的方法......
HANDLE hProcessToken, hProcess = GetCurrentProcess();
char pNewStateArray[sizeof(TOKEN_PRIVILEGES) + 1 * sizeof(LUID_AND_ATTRIBUTES)] = {};
PTOKEN_PRIVILEGES pNewState = (PTOKEN_PRIVILEGES)pNewStateArray;
OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hProcessToken);
LookupPrivilegeValue(0, SE_IMPERSONATE_NAME, &pNewState->Privileges[0].Luid);
pNewState->Privileges[i].Attributes = SE_PRIVILEGE_REMOVED;
AdjustTokenPrivileges(hProcessToken, FALSE, pNewState, sizeof(pNewStateArray), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL);
Run Code Online (Sandbox Code Playgroud)
但我误解了SeImpersonatePrivilege所做的事情:似乎你仍然可以在禁用或删除权限时模仿较低级别的用户(AdjustTokenPrivileges()
如果我在用户模式下启动我的进程,则调用SeImpersonatePrivilege不起作用).RevertToSelf()
经过几天的论坛浏览,试用和大多数错误,我放弃了试图找到阻止的方法.
我的第二个选择是以某种方式绕过DLL init.
首先,我尝试启动同一程序的两个镜像进程 - 一个在用户模式,一个在匿名模式,尝试在初始化完成后将内存从一个进程复制到另一个进程.在启动器上看起来像这样:
HANDLE hToken = NULL;
SAFER_LEVEL_HANDLE hSaferLevel = NULL;
SaferCreateLevel(SAFER_SCOPEID_USER,SAFER_LEVELID_UNTRUSTED,0,&hSaferLevel,NULL);
SaferComputeTokenFromLevel(hSaferLevel, NULL, &hToken, 0, NULL);
CreateProcess(lpApplicationName, lpCommandLine, pProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformationInit));
CreateProcessAsUser(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformationSafe));
SYSTEM_INFO si;
GetSystemInfo(&si);
LPVOID lpMem = 0;
DWORD memoryPtr = 0;
char memory[256*1024];
while (lpMem < si.lpMaximumApplicationAddress) {
MEMORY_BASIC_INFORMATION info;
if(0 == VirtualQueryEx(GetCurrentProcess(), lpMem, &info, sizeof(info))) break;
if (info.State & MEM_COMMIT) {
ReadProcessMemory(GetCurrentProcess(), info.BaseAddress, &memory[memoryPtr], info.RegionSize, 0);
}
memoryPtr += info.RegionSize;
lpMem = (LPVOID)((DWORD)info.BaseAddress + (DWORD)info.RegionSize);
}
Run Code Online (Sandbox Code Playgroud)
...然后找出一种方法来WriteProcessMemory()
获取内存的精确副本以获取DLL初始化数据集,然后以匿名模式运行.但这些尝试并不顺利.我认为这至多是一个非常错误的解决方案.
我的最后一次尝试是试图找出DLL初始化的方式 - 修改了哪些内存,然后在我的进程的沙盒版本中对其进行硬编码.不幸的是,由于DLL分配了很多不同的块,我也提出了这个项目.另外,我觉得只是考虑硬编码这种数据.
这是我想到的其他场地,但在实际尝试之前放弃了:
在DLL中注入我自己的分配器以找出如何模仿初始化.
找到DLL破坏匿名设置的位置,并对汇编器进行反向工程,以弄清楚如何伪造对该对象的访问.
我不确定我有多大可能得到解决方案,但如果你发现我的陈述中有任何不妥之处或者暗示我如何解决我的问题,你就可以度过我的一天!