在当前Windows会话上创建安全桌面(Winsta0\default)

在当前Windows会话上创建安全桌面(Winsta0\default),windows,winapi,Windows,Winapi,我遇到了谷歌Chrome中使用的“安全桌面”概念和一些密码管理器,如KeePass。在Chrome中,安全桌面是Chrome进程的访问受限桌面,安全性很好,在KeePass中,所谓的安全桌面用于主密码对话框。但在KeePass中,他们似乎只是创建了另一个桌面,而没有设置任何DACL来真正保护它。对我来说,安全桌面是在同一桌面上运行的任何其他进程都无法打开和进入的 我问自己,是否有可能拥有一个单独的桌面,您可以启动一个应用程序,并将其与其他进程分开。这包括例如被攻击者误用以收集击键或屏幕的已捕获应

我遇到了谷歌Chrome中使用的“安全桌面”概念和一些密码管理器,如KeePass。在Chrome中,安全桌面是Chrome进程的访问受限桌面,安全性很好,在KeePass中,所谓的安全桌面用于主密码对话框。但在KeePass中,他们似乎只是创建了另一个桌面,而没有设置任何DACL来真正保护它。对我来说,安全桌面是在同一桌面上运行的任何其他进程都无法打开和进入的

我问自己,是否有可能拥有一个单独的桌面,您可以启动一个应用程序,并将其与其他进程分开。这包括例如被攻击者误用以收集击键或屏幕的已捕获应用程序

通过使用API函数CreateDesktop、ConvertStringSecurityDescriptorSecurityDescriptor和SetUserObjectSecurity,我可以创建另一个桌面并减少访问权限。但是,如果我太严格,我无法在那里启动进程,如果我太粗心,新创建的桌面太开放,因此攻击者可以打开桌面并将其线程切换到其中

你们中有谁知道我可以使用SecurityDescriptor字符串组合,这样新创建的桌面就真正安全了,除了Creator进程及其在安全桌面上运行进程的子进程之外,没有其他应用程序能够在其中切换和创建进程

任何建议或暗示都是非常受欢迎的

假设:

  • 具有标准(非管理员)权限的用户
  • 系统由SRPs/AppLocker保护
  • 任何恶意软件进程都不会仅作为受攻击进程(例如,在浏览器、office或pdf viewer中)中利用漏洞的一部分作为单独进程启动
以下是我目前使用的代码:

#include <windows.h>
#include <stdio.h>
#include <Sddl.h>
#include <AclAPI.h>
#include <time.h>

static const unsigned char nameCharTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-[]()<>@~#.:%&$§=";

// create new desktop or open an already existing one
HDESK CreateHiddenDesktop(CHAR *desktop_name)
{
    CHAR explorer_path[MAX_PATH];
    HDESK hNewDesktop = NULL, hOldDesktop;
    STARTUPINFOA startup_info = { 0 };
    PROCESS_INFORMATION process_info = { 0 };

    ExpandEnvironmentStringsA("%windir%\\notepad.exe", explorer_path, MAX_PATH - 1);

    hNewDesktop = OpenDesktopA(desktop_name, NULL, FALSE, GENERIC_ALL);
    if (!hNewDesktop)
    {
        hNewDesktop = CreateDesktopA(desktop_name, NULL, NULL, 0, GENERIC_ALL, NULL);
        if (hNewDesktop)
        {
            hOldDesktop = GetThreadDesktop(GetCurrentThreadId());

            if (SetThreadDesktop(hNewDesktop))
            {
                BOOL bRet = FALSE;
                PSECURITY_DESCRIPTOR SecDes = NULL;

                // just for us to obtain hex values we can use with ConvertStringSecurityDescriptorToSecurityDescriptor
                DWORD access =  DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER | DESKTOP_CREATEMENU |
                                DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
                                DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS | ACCESS_SYSTEM_SECURITY;
                access = DESKTOP_ENUMERATE | WRITE_DAC | WRITE_OWNER | ACCESS_SYSTEM_SECURITY;
                printf("Access mask in hex: 0x%08x.\n", access);

                //bRet = ConvertStringSecurityDescriptorToSecurityDescriptor(TEXT("D:P(D;OICI;GARCSDWDWO;;;WD)(A;OICI;GAGRGWGXRCSDWDWOWPCCCR;;;CO)"), SDDL_REVISION_1, &SecDes, NULL);
                bRet = ConvertStringSecurityDescriptorToSecurityDescriptor(TEXT("D:P(OD;OICI;0x010c0040;;;WD)(OA;OICI;0xffffffff;;;WD)"), SDDL_REVISION_1, &SecDes, NULL);
                if (bRet)
                {
                    BOOL bSaclDefaulted = FALSE;
                    BOOL bSaclPresent = FALSE;
                    PACL SecACL = NULL;
                    SECURITY_INFORMATION si;

                    si = DACL_SECURITY_INFORMATION;
                    if (SetUserObjectSecurity(hNewDesktop, &si, SecDes)) {
                        printf("SetUserObjectSecurity succeeded.\n");
                    }
                }

                // create process and wait until it is initialized and ready
                startup_info.cb = sizeof(startup_info);
                startup_info.lpDesktop = desktop_name;
                CreateProcessA(explorer_path, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startup_info, &process_info);
                WaitForInputIdle(process_info.hProcess, INFINITE);

                // handles in PROCESS_INFORMATION must be closed with CloseHandle when they are no longer needed.
                CloseHandle(process_info.hProcess);
                CloseHandle(process_info.hThread);

                SetThreadDesktop(hOldDesktop);
            }
        }
    }

    return hNewDesktop;
}

int main(int argc, char **argv) {

    HDESK hOldDesktop, hNewDesktop;
    MSG msg = { 0 };
    char desktopName[128] = { 0 };
    BOOLEAN binNewDesktop = FALSE;

    srand((unsigned int)time(NULL));

    for (int i = 0; i < 8; i++) {
        desktopName[i] = nameCharTable[rand() % (sizeof(nameCharTable)-1)];
    }
    // just for debugging and testing: print the desktop's name
    printf("Desktop's name: %s\n", desktopName);

    hNewDesktop = CreateHiddenDesktop(desktopName);
    hOldDesktop = GetThreadDesktop(GetCurrentThreadId());

    printf("Entering the hidden desktop\n");

    // switch thread into context of new desktop to register hotkeys
    SetThreadDesktop(hNewDesktop);
    SwitchDesktop(hNewDesktop);
    binNewDesktop = TRUE;

    RegisterHotKey(NULL, 0, MOD_CONTROL | MOD_ALT | MOD_NOREPEAT, 0x53); // S = switch desktop
    RegisterHotKey(NULL, 1, MOD_CONTROL | MOD_ALT | MOD_NOREPEAT, 0x51); // Q = quit

    while (GetMessage(&msg, NULL, 0, 0) != 0) {
        if (msg.message==WM_HOTKEY) {
            // switch Desktop hotkey
            if (msg.wParam == 0) {
                if (binNewDesktop) {
                    UnregisterHotKey(NULL, 0);
                    UnregisterHotKey(NULL, 1);
                    SetThreadDesktop(hOldDesktop);
                    SwitchDesktop(hOldDesktop);
                    RegisterHotKey(NULL, 0, MOD_CONTROL | MOD_ALT | MOD_NOREPEAT, 0x53); // S = switch desktop
                    RegisterHotKey(NULL, 1, MOD_CONTROL | MOD_ALT | MOD_NOREPEAT, 0x51); // Q = quit
                    binNewDesktop = FALSE;
                }
                else {
                    UnregisterHotKey(NULL, 0);
                    UnregisterHotKey(NULL, 1);
                    SetThreadDesktop(hNewDesktop);
                    SwitchDesktop(hNewDesktop);
                    RegisterHotKey(NULL, 0, MOD_CONTROL | MOD_ALT | MOD_NOREPEAT, 0x53); // S = switch desktop
                    RegisterHotKey(NULL, 1, MOD_CONTROL | MOD_ALT | MOD_NOREPEAT, 0x51); // Q = quit
                    binNewDesktop = TRUE;
                }
            }
            // switch Quit hotkey
            if (msg.wParam == 1) {
                printf("Exiting hidden desktop\n");
                UnregisterHotKey(NULL, 0);
                UnregisterHotKey(NULL, 1);
                SwitchDesktop(hOldDesktop);

                SetHandleInformation(hNewDesktop, 0, 0);
                SwitchDesktop(hOldDesktop);
                CloseDesktop(hNewDesktop);
                CloseDesktop(hOldDesktop);
                //getchar();
                break;
            }
        }
    }

    return 0;
}
#包括
#包括
#包括
#包括
#包括
静态常量无符号字符名称图表[]=“ABCDEFGHIJKLMNOPQRSTUVXYZABCDFGHIJKLMNOPQRSTUVXYZ0123456789+-[]()@#:%&$§=“;
//创建新桌面或打开现有桌面
HDESK CreateHiddenDesktop(字符*桌面名称)
{
CHAR explorer_path[最大路径];
HDESK hNewDesktop=NULL,hOldDesktop;
STARTUPINFOA startup_info={0};
进程信息进程信息={0};
ExpandEnvironmentStringsA(“%windir%\\notepad.exe”,浏览器路径,最大路径-1);
hNewDesktop=OpenDesktopA(桌面名称,NULL,FALSE,通用名称);
如果(!hNewDesktop)
{
hNewDesktop=CreateDesktopA(桌面名称,NULL,NULL,0,通用名称,NULL);
如果(hNewDesktop)
{
hOldDesktop=GetThreadDesktop(GetCurrentThreadId());
if(设置线程桌面(hNewDesktop))
{
布尔-布雷特=假;
PSECURITY_描述符SecDes=NULL;
//只是为了获得十六进制值,我们可以使用ConvertStringSecurityDescriptor或SecurityDescriptor
DWORD访问=删除|读取|控制|写入| DAC |写入|所有者|桌面|创建菜单|
桌面|创建窗口|桌面|枚举|桌面|钩子控件|
桌面|读取对象|桌面|切换桌面|桌面|写入对象|访问|系统|安全;;
access=桌面|枚举|写入| DAC |写入|所有者|访问|系统|安全;
printf(“十六进制的访问掩码:0x%08x.\n”,访问);
//bRet=ConvertStringSecurityDescriptor安全描述符(文本(“D:P(D;OICI;GARCSDWDWO;;;WD)(A;OICI;GARGWGXRCCSDWDWOWPCCCR;;CO)”),SDDL_修订版_1,&SecDes,NULL);
bRet=ConvertStringSecurityDescriptor安全描述符(文本(“D:P(OD;OICI;0x010c0040;;;WD)(OA;OICI;0xFFFFFF;;;WD)”),SDDL_修订版_1,&SecDes,NULL);
如果(bRet)
{
BOOL bSaclDefaulted=FALSE;
BOOL-bsaclcpresent=FALSE;
PACL SecACL=NULL;
安全信息系统;
si=DACL\u安全信息;
if(SetUserObjectSecurity(hNewDesktop,&si,SecDes)){
printf(“SetUserObjectSecurity成功。\n”);
}
}
//创建进程并等待它初始化并准备就绪
startup_info.cb=sizeof(startup_info);
startup\u info.lpDesktop=桌面\u名称;
CreateProcessA(资源管理器路径、NULL、NULL、FALSE、0、NULL、NULL、启动信息和流程信息);
WaitForInputIdle(process_info.hpprocess,无限);
//当不再需要进程信息中的句柄时,必须使用CloseHandle关闭这些句柄。
CloseHandle(process\u info.hpprocess);
CloseHandle(process_info.hThread);
SetThreadDesktop(hOldDesktop);
}
}
}
返回hNewDesktop;
}
int main(int argc,字符**argv){
HDESK hOldDesktop,hNewDesktop;
MSG={0};
char desktopName[128]={0};
布尔值binNewDesktop=FALSE;
srand((无符号整数)时间(NULL));
对于(int i=0;i<8;i++){
desktopName[i]=nameCharTable[rand()%(sizeof(nameCharTable)-1)];
}
//仅用于调试和测试:打印桌面的名称
printf(“桌面名称:%s\n”,桌面名称);
hNewDesktop=CreateHiddenDesktop(desktopName);
hOldDesktop=GetThreadDesktop(GetCurrentThreadId());
printf(“进入隐藏桌面\n”);
//将线程切换到新桌面的上下文以注册热键
SetThreadDesktop(hNewDesktop);
交换机桌面(hNewDesktop);
binNewDesktop=TRUE;
RegisterHotKey(NULL,0,MOD|u CONTROL | MOD|u ALT | MOD|u NOREPEAT,0x53);/S=切换桌面
RegisterHotKey(NULL,1,MOD|u CONTROL | MOD|u ALT | MOD|u NOREPEAT,0x51);//Q=quit
while(GetMessage(&msg,NULL,0,0)!=0){
如果(消息==WM