Skip to content

Instantly share code, notes, and snippets.

@caloni
Created July 9, 2025 13:11
Show Gist options
  • Select an option

  • Save caloni/13a3e806debd752d10b106ec34b4d572 to your computer and use it in GitHub Desktop.

Select an option

Save caloni/13a3e806debd752d10b106ec34b4d572 to your computer and use it in GitHub Desktop.
Win32 GUI "control‑center" that can spawn further copies of itself
// spawn_control_center.cpp – Win32 GUI "control‑center" that can spawn further
// copies of itself under a (parametrizable) Job Object, optionally at Low‑IL, and
// demonstrates ChangeWindowMessageFilterEx + UserHandleGrantAccess so processes can
// PostMessage across UIPI.
//
// Build (VS Developer Prompt):
// cl /EHsc /W4 /nologo /D_UNICODE /DUNICODE spawn_control_center.cpp \
// user32.lib advapi32.lib
//
// Notes / How to use at runtime
// --------------------------------
// 1. Start the EXE once. The initial instance shows its HWND in the upper edit box.
// 2. (Optional) Tick the UI‑limit checkboxes and/or "Low IL" and press **Spawn**.
// – A 2nd copy of the EXE appears (child). Its window caption states whether it is
// running Low or Medium IL, and whether it is inside a Job.
// – The parent grants the child access to its HWND (if the relevant checkbox was
// ticked) via UserHandleGrantAccess.
// – The child allows the registered custom message (WM_FWD) through UIPI if
// the corresponding checkbox was selected.
// 3. Copy a HWND from any instance into the "Target HWND" edit of any other instance
// and press **Send Ping**. The receiver pops a message box proving that the post
// made it across.
//
// This is *not* production‑hardened code; it is meant as a concise playground so you
// can observe Job/UI limits, IL levels and cross‑process window messaging behaviour
// in Process Explorer / ProcMon / Spy++.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commctrl.h>
#include <strsafe.h>
#include <string>
#include <cstdio>
#include <sddl.h>
#include <sstream>
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "advapi32.lib")
// ----------------------------- Constants & globals -----------------------------
// control IDs
enum {
IDC_MYHWND = 1001,
IDC_TEXTHWND = 1002,
IDC_UI_GROUP = 1003,
IDC_UI_DESK = 1004,
IDC_UI_HANDLES = 1005,
IDC_UI_SYSPAR = 1006,
IDC_LOWIL = 1007,
IDC_ALLOWMSG = 1008,
IDC_GRANT = 1009,
IDC_SPAWN = 1010,
IDC_SEND = 1011,
IDC_JOB_NAMES = 1012,
IDC_ALLOWMSG_NOW = 1013,
IDC_GRANT_NOW = 1014,
IDC_JOB_RESTRICT = 1015,
IDC_NOT_ALLOWMSG_NOW = 1016,
IDC_NOT_GRANT_NOW = 1017,
IDC_SEND_COPYDATA = 1018,
};
static const wchar_t *g_clsName = L"SpawnCtrlCenterWndClass";
static UINT g_uMsgFwd; // registered custom message
static const wchar_t *g_uMsgName = L"WM_FWD_{3272E8E2-43C1-4A0A-A5AE-2D0FF6903DF0}";
static const wchar_t *g_pipeName = L"\\\\.\\pipe\\SpawnCtrlCenter";
struct CState {
HWND hwnd; // our main window
HANDLE hJob = nullptr; // if we created/are part of a Job in this instance
bool isLow = false; // did we start at Low IL?
std::wstring title; // window title based on its handle and pid
} g_state;
// ----------------------------- Helper: error exit -----------------------------
void Box(DWORD error, const wchar_t *msg)
{
std::wstring msgS(msg);
wchar_t buf[256];
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error, 0, buf, 256, nullptr);
msgS = msgS + L"\n" + buf;
MessageBoxW(g_state.hwnd, msgS.c_str(), g_state.title.c_str(), error ? MB_ICONERROR : MB_ICONINFORMATION);
}
// ----------------------------- Helper: create Low‑IL token ---------------------
HANDLE MakeLowIntegrityToken()
{
HANDLE hOrigTok = nullptr;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY,
&hOrigTok)) {
Box(GetLastError(), L"OpenProcessToken");
return nullptr;
}
HANDLE hDup = nullptr;
if (!DuplicateTokenEx(hOrigTok, MAXIMUM_ALLOWED, nullptr,
SecurityImpersonation, TokenPrimary, &hDup)) {
Box(GetLastError(), L"DuplicateTokenEx");
return nullptr;
}
PSID pLowSID = nullptr;
if (!ConvertStringSidToSidW(L"S-1-16-4096", &pLowSID)) {
Box(GetLastError(), L"ConvertStringSidToSid");
return nullptr;
}
TOKEN_MANDATORY_LABEL tml = {};
tml.Label.Attributes = SE_GROUP_INTEGRITY;
tml.Label.Sid = pLowSID;
if (!SetTokenInformation(hDup, TokenIntegrityLevel,
&tml, sizeof(tml) + GetLengthSid(pLowSID))) {
Box(GetLastError(), L"SetTokenInformation");
return nullptr;
}
LocalFree(pLowSID);
CloseHandle(hOrigTok);
return hDup; // caller closes
}
// ----------------------------- UI helpers --------------------------------------
void SetDlgItemHex(HWND hDlg, int id, UINT_PTR value)
{
wchar_t buf[32];
StringCchPrintfW(buf, 32, L"0x%p", (void*)value);
SetDlgItemTextW(hDlg, id, buf);
}
UINT_PTR GetDlgItemHex(HWND hDlg, int id)
{
wchar_t buf[64] = {};
GetDlgItemTextW(hDlg, id, buf, 64);
return (UINT_PTR)_wcstoui64(buf, nullptr, 0);
}
// ----------------------------- Spawn child -------------------------------------
void SpawnChild(HWND hDlg, HWND hUiRestrictionsGroup)
{
static int st_jobCount = 0; // static to keep track of job names
WCHAR jobName[64] = {};
GetDlgItemTextW(hDlg, IDC_JOB_NAMES, jobName, 64);
DWORD uiFlags = 0;
if (IsDlgButtonChecked(hUiRestrictionsGroup, IDC_UI_DESK ) == BST_CHECKED) uiFlags |= JOB_OBJECT_UILIMIT_DESKTOP;
if (IsDlgButtonChecked(hUiRestrictionsGroup, IDC_UI_HANDLES) == BST_CHECKED) uiFlags |= JOB_OBJECT_UILIMIT_HANDLES;
if (IsDlgButtonChecked(hUiRestrictionsGroup, IDC_UI_SYSPAR ) == BST_CHECKED) uiFlags |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS;
bool wantJob = uiFlags || jobName[0] != '\0';
bool lowIL = (IsDlgButtonChecked(hDlg, IDC_LOWIL) == BST_CHECKED);
bool allowMsg = (IsDlgButtonChecked(hDlg, IDC_ALLOWMSG)== BST_CHECKED);
bool grantHwnd = (IsDlgButtonChecked(hDlg, IDC_GRANT) == BST_CHECKED);
// Create/prepare Job if requested
HANDLE hJob = nullptr;
HANDLE hJobFull = nullptr;
if (wantJob)
{
PWSTR newJobName = jobName;
if (newJobName[0] == L'\0')
{
// If the combobox is empty, use a new job name
newJobName = new WCHAR[64]; // is this necessary?
StringCchPrintfW(newJobName, 64, L"SpawnJob #%d", ++st_jobCount);
}
hJob = CreateJobObjectW(nullptr, newJobName);
if (!hJob) return Box(GetLastError(), L"CreateJobObject");
hJobFull = OpenJobObjectW(JOB_OBJECT_ALL_ACCESS, FALSE, newJobName);
if( uiFlags )
{
JOBOBJECT_BASIC_UI_RESTRICTIONS ui = { uiFlags };
if (!SetInformationJobObject(hJobFull ? hJobFull : hJob, JobObjectBasicUIRestrictions, &ui, sizeof(ui)))
return Box(GetLastError(), L"SetInformationJobObject");
}
if (newJobName != jobName)
{
// Add the job name to the combobox if it was a new job
LRESULT result = SendMessageW(GetDlgItem(hDlg, IDC_JOB_NAMES), CB_ADDSTRING, 0, (LPARAM)newJobName);
if( result == CB_ERR || result == CB_ERRSPACE ) {
return Box(GetLastError(), L"UpdateJobNames");
}
}
}
// Build command line (pass self HWND + options as args)
wchar_t exePath[MAX_PATH];
GetModuleFileNameW(nullptr, exePath, MAX_PATH);
wchar_t cmd[512];
StringCchPrintfW(cmd, 512, L"\"%s\" --parent %p --allowmsg %d", exePath, g_state.hwnd, allowMsg);
STARTUPINFOW si{ sizeof(si) };
PROCESS_INFORMATION pi{};
DWORD createFlags = CREATE_UNICODE_ENVIRONMENT;
HANDLE hTok = nullptr;
if (lowIL) {
hTok = MakeLowIntegrityToken();
if (!hTok) return Box(GetLastError(), L"MakeLowIntegrityToken");
if (!CreateProcessAsUserW(hTok, nullptr, cmd, nullptr, nullptr, TRUE,
createFlags, nullptr, nullptr, &si, &pi))
return Box(GetLastError(), L"CreateProcessAsUser (low)");
} else {
if (!CreateProcessW(nullptr, cmd, nullptr, nullptr, TRUE,
createFlags, nullptr, nullptr, &si, &pi))
return Box(GetLastError(), L"CreateProcess (medium)");
}
if (wantJob && !AssignProcessToJobObject(hJob, pi.hProcess))
return Box(GetLastError(), L"AssignProcessToJobObject");
if (grantHwnd) {
if (!UserHandleGrantAccess((HANDLE)g_state.hwnd, hJob, TRUE))
return Box(GetLastError(), L"UserHandleGrantAccess");
}
//CloseHandle(hJob);
CloseHandle(pi.hProcess); CloseHandle(pi.hThread);
if (hTok) CloseHandle(hTok);
}
HWND FindSpawnWindow(HWND hDlg)
{
HWND target = (HWND)GetDlgItemHex(hDlg, IDC_TEXTHWND);
if (target == nullptr )
{
target = FindWindowW(g_clsName, nullptr);
if( target != nullptr )
{
wchar_t buf[128];
StringCchPrintfW(buf, 128, L"0x%p", (void*)target);
SetDlgItemText(hDlg, IDC_TEXTHWND, buf);
}
}
return target;
}
// ----------------------------- Send ping ---------------------------------------
void SendPing(HWND hDlg)
{
HWND target = FindSpawnWindow(hDlg);
if (!IsWindow(target)) {
std::wostringstream os; os << L"SendPing HWND " << target << " is invalid";
return Box(ERROR_INVALID_WINDOW_HANDLE, os.str().c_str());
}
if(!PostMessageW(target, g_uMsgFwd, (WPARAM)g_state.hwnd, 0)) {
std::wostringstream os; os << L"SendPing PostMessageW HWND " << target << L".";
return Box(GetLastError(), os.str().c_str());
}
}
bool TrySendCopyDataUsingNamedPipe(HWND hDlg)
{
return false;
}
bool TrySendCopyDataUsingSendMessage(HWND hDlg, std::wstring& error)
{
HWND target = FindSpawnWindow(hDlg);
if (!IsWindow(target))
{
std::wostringstream os; os << L"SendCopyData HWND " << target << " is invalid (INVALID_WINDOW_HANDLE)";
error = os.str();
return false;
}
COPYDATASTRUCT copyData = { 1, 0, nullptr };
if(!SendMessageW(target, WM_COPYDATA, (WPARAM)g_state.hwnd, (LPARAM)&copyData))
{
std::wostringstream os; os << L"SendCopyData PostMessageW HWND " << target << L".";
error = os.str();
return false;
}
return true;
}
void SendCopyData(HWND hDlg)
{
std::wstring error;
if( !TrySendCopyDataUsingSendMessage(hDlg, error))
return Box(GetLastError(), L"TrySendCopyDataUsingSendMessage WM_COPYDATA");
/*WIP
{
std::wstring error2;
if (!TrySendCopyDataUsingNamedPipe(hDlg))
{
}
}
*/
}
void AllowMsgNow(HWND hDlg, bool allow = true)
{
if( ! ChangeWindowMessageFilterEx(g_state.hwnd, g_uMsgFwd, allow ? MSGFLT_ALLOW : MSGFLT_DISALLOW, nullptr) )
return Box(GetLastError(), L"ChangeWindowMessageFilterEx registered message");
if( ! ChangeWindowMessageFilterEx(g_state.hwnd, WM_COPYDATA, allow ? MSGFLT_ALLOW : MSGFLT_DISALLOW, nullptr) )
return Box(GetLastError(), L"ChangeWindowMessageFilterEx WM_COPYDATA");
Box(0, L"ChangeWindowMessageFilterEx");
}
void GrantNow(HWND hDlg, bool allow = true)
{
WCHAR jobName[64] = {};
GetDlgItemText(hDlg, IDC_JOB_NAMES, jobName, 64);
if (jobName[0] != L'\0') {
HANDLE hJob = OpenJobObjectW(JOB_OBJECT_ALL_ACCESS, FALSE, jobName);
if (!hJob) return Box(GetLastError(), L"OpenJobObject");
if (!UserHandleGrantAccess((HANDLE)g_state.hwnd, hJob, allow ? TRUE : FALSE)) return Box(GetLastError(), L"UserHandleGrantAccess");
CloseHandle(hJob);
Box(0, L"UserHandleGrantAccess");
} else {
Box(ERROR_INVALID_PARAMETER, L"Specify a job name");
}
}
void RestrictJob(HWND hDlg, HWND hUiRestrictionsGroup)
{
WCHAR jobName[64] = {};
GetDlgItemTextW(hDlg, IDC_JOB_NAMES, jobName, 64);
if (jobName[0] != L'\0') {
HANDLE hJob = OpenJobObjectW(JOB_OBJECT_ALL_ACCESS, FALSE, jobName);
if (!hJob) return Box(GetLastError(), L"OpenJobObject");
DWORD uiFlags = 0;
if (IsDlgButtonChecked(hUiRestrictionsGroup, IDC_UI_DESK) == BST_CHECKED) uiFlags |= JOB_OBJECT_UILIMIT_DESKTOP;
if (IsDlgButtonChecked(hUiRestrictionsGroup, IDC_UI_HANDLES) == BST_CHECKED) uiFlags |= JOB_OBJECT_UILIMIT_HANDLES;
if (IsDlgButtonChecked(hUiRestrictionsGroup, IDC_UI_SYSPAR) == BST_CHECKED) uiFlags |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS;
JOBOBJECT_BASIC_UI_RESTRICTIONS ui = { uiFlags };
if (!SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &ui, sizeof(ui)))
return Box(GetLastError(), L"SetInformationJobObject");
Box(0, L"SetInformationJobObject");
} else {
Box(ERROR_INVALID_PARAMETER, L"Specify a job name");
}
}
// ----------------------------- Window procedure --------------------------------
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
static HWND st_uiRestrictions = nullptr; // groupbox for UI restrictions
switch (msg)
{
case WM_CREATE:
{
INITCOMMONCONTROLSEX icc{ sizeof(icc), ICC_STANDARD_CLASSES };
InitCommonControlsEx(&icc);
// Store our HWND globally
g_state.hwnd = hwnd;
DWORD pid = GetCurrentProcessId();
std::wostringstream os; os << L"SpawnControlCenter 0x" << g_state.hwnd << " PID " << pid;
g_state.title = os.str();
// ---------------- Controls layout (simplistic) ----------------
CreateWindowExW(WS_EX_CLIENTEDGE, L"edit", L"", WS_CHILD|WS_VISIBLE|ES_READONLY,
10,8, 200,24, hwnd, (HMENU)IDC_MYHWND, nullptr, nullptr);
CreateWindowW(L"static", L"=>", WS_CHILD|WS_VISIBLE,
210,10, 20,20, hwnd, nullptr, nullptr, nullptr);
CreateWindowExW(WS_EX_CLIENTEDGE, L"edit", L"0x0", WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL,
230,8, 200,24, hwnd, (HMENU)IDC_TEXTHWND, nullptr, nullptr);
CreateWindowW(L"static", L"Job:", WS_CHILD|WS_VISIBLE,
10,38, 50,20, hwnd, nullptr, nullptr, nullptr);
CreateWindowExW(WS_EX_CLIENTEDGE, L"combobox", L"", WS_CHILD|WS_VISIBLE|CBS_DROPDOWN|CBS_HASSTRINGS|CBS_SORT,
60,38, 150,150, hwnd, (HMENU)IDC_JOB_NAMES, nullptr, nullptr);
st_uiRestrictions = CreateWindowW(L"button", L"UI Restrictions (Job)",
WS_CHILD|WS_VISIBLE|BS_GROUPBOX,
10,70, 220, 120, hwnd, (HMENU)IDC_UI_GROUP, nullptr, nullptr);
CreateWindowW(L"button", L"DESKTOP", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
20,20, 110,20, st_uiRestrictions, (HMENU)IDC_UI_DESK, nullptr, nullptr);
CreateWindowW(L"button", L"HANDLES", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
20,40, 110,20, st_uiRestrictions, (HMENU)IDC_UI_HANDLES, nullptr, nullptr);
CreateWindowW(L"button", L"SYSPARAM", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
20,60, 110,20, st_uiRestrictions, (HMENU)IDC_UI_SYSPAR, nullptr, nullptr);
CreateWindowW(L"button", L"Apply", WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
20,150, 100,28, hwnd, (HMENU)IDC_JOB_RESTRICT, nullptr, nullptr);
CreateWindowW(L"button", L"Low Integrity", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
10,200, 120,20, hwnd, (HMENU)IDC_LOWIL, nullptr, nullptr);
CreateWindowW(L"button", L"Allow Msg (ChangeWindowMessageFilterEx)", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
140,200, 320,20, hwnd, (HMENU)IDC_ALLOWMSG, nullptr, nullptr);
CreateWindowW(L"button", L"Grant HWND to child (UserHandleGrantAccess)", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
140,225, 380,20, hwnd, (HMENU)IDC_GRANT, nullptr, nullptr);
CreateWindowW(L"button", L"Spawn Child", WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
10,250, 100,28, hwnd, (HMENU)IDC_SPAWN, nullptr, nullptr);
CreateWindowW(L"button", L"Send Ping", WS_CHILD|WS_VISIBLE,
120,250, 100,28, hwnd, (HMENU)IDC_SEND, nullptr, nullptr);
CreateWindowW(L"button", L"CopyData", WS_CHILD|WS_VISIBLE,
120,280, 100,28, hwnd, (HMENU)IDC_SEND_COPYDATA, nullptr, nullptr);
CreateWindowW(L"button", L"Allow Msg", WS_CHILD|WS_VISIBLE,
230,250, 100,28, hwnd, (HMENU)IDC_ALLOWMSG_NOW, nullptr, nullptr);
CreateWindowW(L"button", L"Grant", WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
340,250, 100,28, hwnd, (HMENU)IDC_GRANT_NOW, nullptr, nullptr);
CreateWindowW(L"button", L"Disallow", WS_CHILD|WS_VISIBLE,
230,280, 100,28, hwnd, (HMENU)IDC_NOT_ALLOWMSG_NOW, nullptr, nullptr);
CreateWindowW(L"button", L"Revoke", WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
340,280, 100,28, hwnd, (HMENU)IDC_NOT_GRANT_NOW, nullptr, nullptr);
// show our own HWND
SetDlgItemHex(hwnd, IDC_MYHWND, (UINT_PTR)hwnd);
return 0;
}
case WM_COMMAND:
{
int id = LOWORD(wp);
if (id == IDC_SPAWN)
SpawnChild(hwnd, st_uiRestrictions);
else if (id == IDC_SEND)
SendPing(hwnd);
else if (id == IDC_SEND_COPYDATA)
SendCopyData(hwnd);
else if (id == IDC_ALLOWMSG_NOW)
AllowMsgNow(hwnd);
else if (id == IDC_GRANT_NOW)
GrantNow(hwnd);
else if (id == IDC_NOT_ALLOWMSG_NOW)
AllowMsgNow(hwnd, false);
else if (id == IDC_NOT_GRANT_NOW)
GrantNow(hwnd, false);
else if (id == IDC_JOB_RESTRICT)
RestrictJob(hwnd, st_uiRestrictions);
return 0;
}
case WM_CLOSE:
{
PostQuitMessage(0);
}
default:
if (msg == g_uMsgFwd) {
wchar_t buf[128];
StringCchPrintfW(buf, 128, L"Received ping from HWND 0x%p!", (void*)wp);
Box(0, buf);
StringCchPrintfW(buf, 128, L"0x%p", (void*)wp);
SetDlgItemText(hwnd, IDC_TEXTHWND, buf);
return 0;
} else if (msg == WM_COPYDATA) {
wchar_t buf[128];
StringCchPrintfW(buf, 128, L"Received WM_COPYDATA from HWND 0x%p!", (void*)wp);
Box(0, buf);
StringCchPrintfW(buf, 128, L"0x%p", (void*)wp);
SetDlgItemText(hwnd, IDC_TEXTHWND, buf);
return TRUE;
}
return DefWindowProcW(hwnd, msg, wp, lp);
}
}
bool JobHasBasicUILimits()
{
// Ask for the UI‑restriction block that is attached to the job
JOBOBJECT_BASIC_UI_RESTRICTIONS ui = {};
if (!QueryInformationJobObject(
/*JobHandle*/ nullptr, // “nullptr” → “the job that I’m running in”
JobObjectBasicUIRestrictions, // what we want
&ui, sizeof(ui),
/*ReturnLength*/ nullptr))
{
// If the call fails the process probably just isn’t in a job
// (ERROR_NOT_FOUND or ERROR_INVALID_PARAMETER on older versions)
return false;
}
return ui.UIRestrictionsClass != 0; // any bit means some UI limit is set
}
// Wire format = 3 dwords followed by cbData bytes
// | dwData | cbData | reserved | payload ... |
struct PIPE_DATA_HDR
{
DWORD dwData; // like COPYDATASTRUCT.dwData
DWORD cbData; // size of payload
DWORD reserved; // keep 8‑byte alignment, future use
};
// Helper: send one "WM_COPYDATA‑style" message
inline bool SendPipeMessage(
HANDLE hPipe,
DWORD dwData,
const void* pBuf,
DWORD cbBuf)
{
PIPE_DATA_HDR hdr{ dwData, cbBuf, 0 };
DWORD written = 0;
return WriteFile(hPipe, &hdr, sizeof(hdr), &written, nullptr) &&
WriteFile(hPipe, pBuf, cbBuf, &written, nullptr);
}
// Helper: blocking receive. Returns false on EOF/error.
// *dwData and *payload are filled; caller frees payload with LocalFree.
inline bool RecvPipeMessage(
HANDLE hPipe,
DWORD* dwData,
void** payload,
DWORD* cbBuf)
{
PIPE_DATA_HDR hdr{};
DWORD read = 0;
if (!ReadFile(hPipe, &hdr, sizeof(hdr), &read, nullptr) ||
read != sizeof(hdr))
return false;
void* buf = LocalAlloc(LMEM_FIXED, hdr.cbData);
if (!buf) return false;
if (!ReadFile(hPipe, buf, hdr.cbData, &read, nullptr) ||
read != hdr.cbData)
{
LocalFree(buf);
return false;
}
*dwData = hdr.dwData;
*cbBuf = hdr.cbData;
*payload = buf;
return true;
}
HANDLE CreateLowIntegrityPipe()
{
SECURITY_ATTRIBUTES sa = { sizeof(sa) };
PSECURITY_DESCRIPTOR pSD = nullptr;
// Define low integrity SDDL
LPCWSTR lowIntegritySDDL = L"D:(A;OICI;GA;;;WD)S:(ML;;NW;;;LW)";
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
lowIntegritySDDL, SDDL_REVISION_1, &pSD, nullptr))
{
return nullptr;
}
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = FALSE;
HANDLE hPipe = CreateNamedPipeW(
g_pipeName,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1, 4096, 4096, 0, &sa);
LocalFree(pSD);
return hPipe;
}
DWORD WINAPI PipeProcThread(LPVOID lpThreadParameter)
{
HANDLE hPipe = CreateLowIntegrityPipe();
if (hPipe == INVALID_HANDLE_VALUE)
{
return 1;
}
ConnectNamedPipe(hPipe, nullptr);
// Example: send a greeting
const char msg[] = "Hello from parent!";
SendPipeMessage(hPipe, 1, msg, sizeof(msg));
// Loop receiving data
for (;;)
{
DWORD id, cb;
void* payload;
if (!RecvPipeMessage(hPipe, &id, &payload, &cb))
break;
LocalFree(payload);
}
CloseHandle(hPipe);
return 0;
}
// ----------------------------- WinMain ----------------------------------------
int APIENTRY wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR lpCmdLine, int nCmdShow)
{
// Parse minimal cmdline flags (only ones we need when launched as child)
bool allowMsgThis = false;
if (wcsstr(lpCmdLine, L"--allowmsg 1")) allowMsgThis = true;
// Register message (must be done *before* any ChangeWindowMessageFilterEx)
g_uMsgFwd = RegisterWindowMessageW(g_uMsgName);
wchar_t cap[64];
BOOL inJob = false;
BOOL b = IsProcessInJob(GetCurrentProcess(), nullptr, &inJob);
DWORD il = SECURITY_MANDATORY_MEDIUM_RID;
HANDLE hTok;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hTok)) {
DWORD sz = 0; GetTokenInformation(hTok, TokenIntegrityLevel, nullptr, 0, &sz);
BYTE *buf = new BYTE[sz];
if (GetTokenInformation(hTok, TokenIntegrityLevel, buf, sz, &sz)) {
auto tml = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(buf);
il = *GetSidSubAuthority(tml->Label.Sid,
*GetSidSubAuthorityCount(tml->Label.Sid)-1);
}
delete [] buf; CloseHandle(hTok);
}
StringCchPrintfW(cap, 64, L"Spawn Ctrl Center – %s IL – %sJob - %d",
(il == SECURITY_MANDATORY_LOW_RID ? L"LOW" : L"MED"), inJob ? L"in " : L"no ", GetCurrentProcessId());
MessageBox(nullptr, cap, L"Starting", MB_ICONINFORMATION | MB_OK);
bool highPriv = false;
std::wstring className;
if( il == SECURITY_MANDATORY_LOW_RID || (inJob && JobHasBasicUILimits()) )
{
className = g_clsName + std::wstring(L"_low");
}
else
{
className = g_clsName;
highPriv = true;
}
if( highPriv )
{
CreateThread(NULL, 0, PipeProcThread, nullptr, 0, nullptr);
}
// If launched as child: optional ChangeWindowMessageFilterEx
WNDCLASSEXW wc{ sizeof(wc) };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInst;
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.lpszClassName = className.c_str();
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
RegisterClassExW(&wc);
g_state.isLow = (il==SECURITY_MANDATORY_LOW_RID);
g_state.hwnd = CreateWindowW(className.c_str(), cap,
WS_OVERLAPPEDWINDOW|WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 540, 350,
nullptr, nullptr, hInst, nullptr);
if (allowMsgThis) {
ChangeWindowMessageFilterEx(g_state.hwnd, g_uMsgFwd, MSGFLT_ALLOW, nullptr);
}
// Main loop
MSG m;
while (GetMessageW(&m, nullptr, 0, 0)) {
TranslateMessage(&m);
DispatchMessageW(&m);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment