I'm trying to get information about menu items in an application. Experimentally established that InsertMenuItemW is called. Thanks to the documentation, I set the number of input parameters and wrote this hook.
var InsertMenuItemW = Module.findExportByName("user32.dll", "InsertMenuItemW");
const oInsertMenuItemW = new NativeFunction(InsertMenuItemW, 'pointer', ['pointer', 'pointer', 'pointer', 'pointer']);
Interceptor.replace(oInsertMenuItemW, new NativeCallback((pathPtr, pathPtr1, pathPtr2, pathPtr3) => {
console.log(" "+pathPtr, pathPtr1, pathPtr2, pathPtr3);
const fd = oInsertMenuItemW(pathPtr, pathPtr1, pathPtr2, pathPtr3);
return fd;
}, 'pointer', ['pointer', 'pointer', 'pointer', 'pointer']));
According to the documentation, I can get information about the new menu item by calling MENUITEMINFOA. But I can't figure out how to do it with Frida.
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-insertmenuitemw
Question update
I was advised in the comments to use Memory.alloc.
On the Internet, I found this example where the hook allows you to read downloaded files.
var pGetFileInformationByHandleEx = Module.findExportByName("kernel32.dll", "GetFileInformationByHandleEx");
var fGetFileInformationByHandleEx = new NativeFunction(pGetFileInformationByHandleEx, "bool",["pointer", "uint", "pointer", "uint"]);
function getNameFromHandle(hFile) {
var lpFileInformation = Memory.alloc(0x200);
// 0x2 -> FILE_NAME_INFO
var callRes = fGetFileInformationByHandleEx(hFile, 0x2, lpFileInformation, 0x200);
if (callRes) {
console.log("|_ hFile: " + (lpFileInformation.add(0x4)).readUtf16String());
} else {
console.log("|_ hFile: N/A");
}
}
According to the documentation the third parameter (output).
BOOL GetFileInformationByHandleEx(
[in] HANDLE hFile,
[in] FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
[out] LPVOID lpFileInformation,
[in] DWORD dwBufferSize
);
in the code you can see that we are passing the third parameter:Memory.alloc(0x200);
var callRes = fGetFileInformationByHandleEx(hFile, 0x2, lpFileInformation, 0x200)
But according to the InsertMenuItem documentation the fourth parameter is [in, out]
BOOL GetMenuItemInfoA(
[in] HMENU hmenu,
[in] UINT item,
[in] BOOL fByPosition,
[in, out] LPMENUITEMINFOA lpmii
);
As I understand it, we must pass the lpmi of our InsertMenuItem as the fourth parameter. But how do we get out?
My current code
var InsertMenuItemW = Module.findExportByName("user32.dll", "InsertMenuItemW");
var GetMenuItemInfoW = Module.findExportByName("user32.dll", "GetMenuItemInfoW");
var fGetMenuItemInfoW = new NativeFunction(GetMenuItemInfoW, "bool",["pointer", "pointer", "pointer", "pointer"]);
function getHandle(hmenu, item, fByPosition, lpmi) {
var lpFileInformation = lpmi || Memory.alloc(0x200);
var lpFileInformation2 = Memory.alloc(0x200);
var callRes = fGetMenuItemInfoW(hmenu, item, fByPosition, lpmi);
console.log(lpFileInformation2);
console.log("-----------");
}
const oInsertMenuItemW = new NativeFunction(InsertMenuItemW, 'pointer', ['pointer', 'pointer', 'pointer', 'pointer']);
Interceptor.replace(oInsertMenuItemW, new NativeCallback((hmenu, item, fByPosition, lpmi) => {
//call GetMenuItemInfoW
getHandle(hmenu, item, fByPosition, lpmi);
const fd = oInsertMenuItemW(hmenu, item, fByPosition, lpmi);
return fd;
}, 'pointer', ['pointer', 'pointer', 'pointer', 'pointer']));
InsertMenuItemW
. For the out parameter you will have to allocate memory usingMemory.alloc
.W
version. Usually handling ofW
ide strings (UTF-16) is often more complicated. Not sure about Frida if wide strings are well supported.A
or theW
variety? I don't quite get your reasoning here. Unless you hook the underlying functionality fromwin32u.dll
(previouslyuser32.dll
) these would be different code paths. Also note: ECMAscript uses UTF-32 internally, so I'd expect UTF-16 to be no issue.