Search code examples
javascriptwinapifirefox-addonjsctypes

How to read memory at pointer (local_tbb.dwData) to get window handle


I've been lacking sleep so I'm just super over killing this one.

What I'm trying to do is get the handle from a window from a task bar button. Following this tutorial here: http://www.codeproject.com/Articles/10497/A-tool-to-order-the-window-buttons-in-your-taskbar. This is the specific part:

Getting the window handle

This was the really lucky part. I thought to myself: "Where would I keep the window handle?". They must keep it somewhere, to enable the activation of the correct window when a button is selected. The obvious place to keep it would be in a structure for each button, and the obvious place to keep the pointer to this structure would be in the dwData field of each TBBUTTON.

So I had a look at the dwData fields, and they appeared to be pointers. OK so far. Then I had a look at the memory they pointed to, and there they were: the first field stores the window handle Smile | :) )) Microsoft developers aren't so different, after all Smile | :)

So I successfully get the task bar button like this:

anyways this is how i get local_tbb:

remote_tbb = ralloc_alloc(struct_TBButton.size);
var rez = SendMessage(hToolbar, TB_GETBUTTON, i, ctypes.voidptr_t(remote_tbb));
if (!rez) { throw new Error('Failed on SendMessage of TB_GETBUTTON'); }

var local_tbb = new struct_TBButton();
var retRead = ralloc_read(remote_tbb, local_tbb.address());
var freed = ralloc_free(remote_tbb);
console.log('freed', freed);

for (var n in local_tbb) {
    console.log(n, local_tbb[n]);
    try {
        console.log('toString', n, local_tbb[n].toString());
    } catch (ignore) {}
}

and succesfully get the dwData field populated. From this console.log is when it does it on dwData:

"dwData" UInt64 {  }
"toString" "dwData" "1499288"

So now I want to do what that guy said and Then I had a look at the memory they pointed to. So I'm trying to do that.

So I know I have to do something like this, but what IPC command should go into the SendMessage (currently I'm using 0x004A /** WM_COPYDATA **/ but this can't be right) and where should I put in the local_tbb.dwData as address?

    var remote_hwnd = ralloc_alloc(ctypes.voidptr_t.size);
    var smHwndRez = SendMessage(hToolbar, 0x004A /** WM_COPYDATA **/, local_tbb.idCommand, ctypes.voidptr_t(remote_hwnd));
    console.log('smHwndRez=', smHwndRez);

    var local_hwnd = ctypes.voidptr_t;
    var retRead = ralloc_read(remote_hwnd, local_hwnd.address());
    console.log('retRead=', retRead);

    var freed = ralloc_free(remote_hwnd);
    console.log('freed=', freed);

    console.log('local_hwnd = ', local_hwnd, local_hwnd.toString(), uneval(local_hwnd));

Solution

  • Strictly speaking, this is not winapi, as this is not part of the API but undocumented implementation details.

    From what I can gather:

    • Get the TBBUTTON data.
    • The .dwData contains a pointer to multiple(?) HANDLEs (voidptr_ts)
    • So reinterpret .dwData as a voidptr_t, i.e. new ctypes.voidptr_t(.dwData);
    • use ReadProcessMemory to read another pointer from the location .dwData points to. That is (supposed to be) your window handle.

    So something like this:

    var tbb = new TBButton();
    ...
    var dataPtr = new ctypes.voidptr_t(tbb.dwData);
    var handle = new ctypes.voidptr_t();
    // Important: pass the address of |handle|, not |handle| itself.
    if (!ReadProcessMemory(process, dataPtr, handle.address(), ctypes.voidptr_t.size, null)) {
      throw new Error("Failed to read window handle");
    }