Search code examples
javascriptfirefox-addonjsctypes

Address to WCHAR_T to pass to ReadProcessMemory


I'm having trouble passing a WCHAR_T to ReadProcessMemory

This is how to succesfully pass a pointers address to ReadProcessMemory, I can do it with structures:

    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);

But now I need to do with WCHAR_T, so this is what I have:

    var chars = SendMessage(hToolbar, TB_GETBUTTONTEXTW, local_tbb.idCommand, ctypes.voidptr_t(0));
    console.log('chars=', chars, chars.toString(), uneval(chars));

    if (chars && parseInt(chars.toString()) > 0) {
        var remote_buf = ralloc_alloc(parseInt(chars.toString()));
        var charsRe = SendMessage(hToolbar, TB_GETBUTTONTEXTW, local_tbb.idCommand, ctypes.voidptr_t(remote_buf));
        console.log('charsRe=', charsRe);

        var local_buf = ctypes.jschar; //WCHAR_T
        var retRead = ralloc_read(remote_buf, local_buf.address()); ///PROBLEM LINE
        console.log('retRead=', retRead);

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

        console.log('Button Text = ', local_buf, local_buf.toString());
    } else {
        console.log('Button Text = NONE');
    }

So my problem is on line:

var retRead = ralloc_read(remote_buf, local_buf.address());`

and it is specifically on the local_buf.address()

Errors in my experimenting that get thrown are:

  • expected type pointer, got ctypes.jschar
  • local_buf.address is not a function

So how to pass WCHAR_T as reference?

Edit: Here is my ralloc_read implemetnation:

function ralloc_read(remote_address, local_buffer) {
    var found_addr;
    for (var i = 0; i < buffers.length; i++) {
        if (buffers[i][0] == remote_address) {
            found_addr = buffers[i]
            break;
        }
    }
    if (!found_addr) {
        return null;
    }
    /*using the found remote address(found_addr[0]), 
     *i read size bytes (found_addr[1]) into my local_buffer*/
    //console.info('found_addr[0]', found_addr[0].toString());
    var rez = ReadProcessMemory(proc, found_addr[0], local_buffer, found_addr[1], 0);
    return rez;
}

Solution

  • If ralloc_read calls ReadProcessMemory, then you'll need to allocate a jschar array that will receive the result.

    var local_buf = ctypes.jschar.array()(chars);
    ralloc_read(remote_buf, local_buf.address());
    var str = local_buf.readString();
    

    Edit However, the allocation call is wrong:

    ralloc_alloc(parseInt(chars.toString()));
    

    This will allocate chars bytes, e.g. chars = 11, 11 bytes. A wchar_t/jschar however is not 1 byte but 2 bytes.

    ctypes.jschar.size
    // 2
    

    So you'll actually need to allocate a remote memory buffer that is larger:

    ralloc_alloc(parseInt(chars.toString()) * ctypes.jschar.size);
    // That would be ralloc_alloc(count * sizeof(wchar_t*)) in C/C++
    

    The local_buf stuff is correct, though as js-ctypes arrays will automatically calculate the required storage if it knows the size of the array element type, so a ctypes.jschar.array()(11) buffer will actually have 11 elements of size 2 bytes, i.e. 11 items * 2 bytes/item == 22 bytes.