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

时间:2018-12-01 17:58:28

标签: windows winapi

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

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

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

你们中的每个人都知道我可以使用的SecurityDescriptor字符串组合,这样才能真正保护新创建的桌面,以便除创建者进程及其在受保护的桌面中运行进程的子进程以外的其他应用程序都不能在那里切换和创建流程?

任何建议或提示都非常受欢迎。

假设:

  • 具有标准(非管理员)特权的用户
  • 系统受SRP / AppLocker保护
  • 没有恶意软件进程被视为单独的进程,而只是作为被攻击进程(例如,在浏览器,办公室或pdf查看器中)的漏洞利用的一部分。

这是我当前正在使用的代码:

#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;
}

0 个答案:

没有答案