diff options
Diffstat (limited to 'tools/testcon/mainwindow.cpp')
-rw-r--r-- | tools/testcon/mainwindow.cpp | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/tools/testcon/mainwindow.cpp b/tools/testcon/mainwindow.cpp index 06ce0a0..0c3d3e8 100644 --- a/tools/testcon/mainwindow.cpp +++ b/tools/testcon/mainwindow.cpp @@ -45,9 +45,10 @@ #include <QtCore/QLibraryInfo> #include <QtCore/qt_windows.h> #include <ActiveQt/QAxScriptManager> -#include <ActiveQt/QAxSelect> #include <ActiveQt/QAxWidget> #include <ActiveQt/qaxtypes.h> +#include <memory> +#include <sddl.h> QT_BEGIN_NAMESPACE @@ -118,10 +119,75 @@ QList<QAxWidget *> MainWindow::axWidgets() const return result; } -bool MainWindow::addControlFromClsid(const QString &clsid) + +/** RAII class for temporarily impersonating low-integrity level for the current thread. + Intended to be used together with CLSCTX_ENABLE_CLOAKING when creating COM objects. + Based on "Designing Applications to Run at a Low Integrity Level" https://msdn.microsoft.com/en-us/library/bb625960.aspx */ +struct LowIntegrity { + LowIntegrity() + { + HANDLE cur_token = nullptr; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &cur_token)) + abort(); + + if (!DuplicateTokenEx(cur_token, 0, NULL, SecurityImpersonation, TokenPrimary, &m_token)) + abort(); + + CloseHandle(cur_token); + + PSID li_sid = nullptr; + if (!ConvertStringSidToSid(L"S-1-16-4096", &li_sid)) // low integrity SID + abort(); + + // reduce process integrity level + TOKEN_MANDATORY_LABEL TIL = {}; + TIL.Label.Attributes = SE_GROUP_INTEGRITY; + TIL.Label.Sid = li_sid; + if (!SetTokenInformation(m_token, TokenIntegrityLevel, &TIL, sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(li_sid))) + abort(); + + if (!ImpersonateLoggedOnUser(m_token)) // change current thread integrity + abort(); + + LocalFree(li_sid); + li_sid = nullptr; + } + + ~LowIntegrity() + { + if (!RevertToSelf()) + abort(); + + CloseHandle(m_token); + m_token = nullptr; + } + +private: + HANDLE m_token = nullptr; +}; + +bool MainWindow::addControlFromClsid(const QString &clsid, QAxSelect::SandboxingLevel sandboxing) { QAxWidget *container = new QAxWidget; - const bool result = container->setControl(clsid); + + bool result = false; + { + std::unique_ptr<LowIntegrity> low_integrity; + + if (sandboxing == QAxSelect::SandboxingProcess) { + // require out-of-process + container->setClassContext(CLSCTX_LOCAL_SERVER); + } else if (sandboxing == QAxSelect::SandboxingLowIntegrity) { + // impersonate "low integrity" + low_integrity.reset(new LowIntegrity); + // require out-of-process and + // propagate integrity level when calling setControl + container->setClassContext(CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING); + } + + result = container->setControl(clsid); + } + if (result) { container->setObjectName(container->windowTitle()); m_mdiArea->addSubWindow(container); @@ -154,7 +220,8 @@ void MainWindow::appendLogText(const QString &message) void MainWindow::on_actionFileNew_triggered() { QAxSelect select(this); - while (select.exec() && !addControlFromClsid(select.clsid())) { } + while (select.exec() && !addControlFromClsid(select.clsid(), select.sandboxingLevel())) { + } } void MainWindow::on_actionFileLoad_triggered() @@ -327,7 +394,7 @@ void MainWindow::on_actionControlPixmap_triggered() return; QLabel *label = new QLabel; - label->setPixmap(QPixmap::grabWidget(container)); + label->setPixmap(container->grab()); QMdiSubWindow *subWindow = m_mdiArea->addSubWindow(label); subWindow->setWindowTitle(tr("%1 - Pixmap").arg(container->windowTitle())); label->show(); |