Page 1 of 1

Can't Call WinAPI from mCode

Posted: 25 Jul 2020, 12:09
by 1100++
I'm trying to use the function described here to write a machine code function that calls QueryPerformanceCounter() and returns the result. This might seem unnecessary, but, as it turns out, I was able to get better performance by wrapping QueryPerformanceCounter() in my own DLL function and calling that, than by calling the function directly using DllCall(). Anyway, I compiled my DLL with Visual Studio and had the compiler output readable machine code so I could use the function with mCode(). When I compiled a simple function to retrieve a number in memory and called it with mCode(), it worked perfectly. However, when I try to call the mCode() version of my QueryPerformanceCounter() wrapper, I get a blank result. Here's my code:

Code: Select all

#NoEnv
SetBatchLines -1

GetInt64 := mCode("558bec8b4d088b550c8b04118b5411045dc20800", "488b0411c3")	; Retrieves the 64-bit integer at the address + offset specified by the caller

qpc := mCode("558bec83ec0ca10000000033c58945fc8d45f450ff1500000000"
	. "8b4dfc8b45f433cd8b55f8e8000000008be55dc3", "4883ec38488b05000000004833c44889442428488d4c2420"
	. "ff1500000000488b442420488b4c24284833cce8000000004883c438c3")	; Should call QueryPerformanceCounter() and return the result

VarSetCapacity(num, 32, 0), NumPut(32, num, 7, "Int64")

MsgBox % DllCall(GetInt64, "Ptr", &num, "Ptr", 7, "Int64")	; Correctly displays the number 32

MsgBox % DllCall(qpc, "Int64")	; Returns a blank result
return

mCode(x86_code, x64_code := "", a86_code := "") {
	static mCodeFn := (A_PtrSize = 8 ? Func("[email protected]") : A_IsUnicode ? Func("[email protected]") : Func("[email protected]")).Bind(DllCall("GetProcessHeap", "Ptr"))
		, hCrypt := DllCall("LoadLibrary", "Str", "Crypt32.dll", "Ptr")
	return x86_code == "" ? 0 : mCodeFn.Call(x86_code, x64_code, a86_code)
}

[email protected](process_heap, ByRef x86_code, ByRef x64_code, ByRef a86_code) {
	If !DllCall("Crypt32\CryptStringToBinary", "Ptr", &x86_code, "uInt", 0, "uInt", 4, "Ptr", 0, "uInt*", length, "Ptr", 0, "Ptr", 0)
		return
	code_buffer := DllCall("HeapAlloc", "Ptr", process_heap, "uInt", 8, "Ptr", length, "Ptr")
	If DllCall("Crypt32\CryptStringToBinary", "Ptr", &x86_code, "uInt", 0, "uInt", 4, "Ptr", code_buffer, "uInt*", length, "Ptr", 0, "Ptr", 0)
		return code_buffer
	DllCall("HeapFree", "Ptr", process_heap, "uInt", 0, "Ptr", code_buffer)
}

[email protected](process_heap, ByRef x86_code, ByRef x64_code, ByRef a86_code) {
	code_version := x64_code == "" ? &x86_code : &x64_code
	If !DllCall("Crypt32\CryptStringToBinary", "Ptr", code_version, "uInt", 0, "uInt", 4, "Ptr", 0, "uInt*", length, "Ptr", 0, "Ptr", 0)
		return
	code_buffer := DllCall("HeapAlloc", "Ptr", process_heap, "uInt", 8, "Ptr", length, "Ptr")
    DllCall("VirtualProtect", "ptr", code_buffer, "Ptr", length, "uInt", 0x40, "uInt*", old_protection)
	If DllCall("Crypt32\CryptStringToBinary", "Ptr", code_version, "uInt", 0, "uInt", 4, "Ptr", code_buffer, "uInt*", length, "Ptr", 0, "Ptr", 0)
		return code_buffer
	DllCall("HeapFree", "Ptr", process_heap, "uInt", 0, "Ptr", code_buffer)
}

[email protected](process_heap, ByRef x86_code, ByRef x64_code, ByRef a86_code) {
	code_version := a86_code == "" ? &x86_code : &a86_code
	If !DllCall("Crypt32\CryptStringToBinary", "Ptr", code_version, "uInt", 0, "uInt", 4, "Ptr", 0, "uInt*", length, "Ptr", 0, "Ptr", 0)
		return
	code_buffer := DllCall("HeapAlloc", "Ptr", process_heap, "uInt", 8, "Ptr", length, "Ptr")
	If DllCall("Crypt32\CryptStringToBinary", "Ptr", code_version, "uInt", 0, "uInt", 4, "Ptr", code_buffer, "uInt*", length, "Ptr", 0, "Ptr", 0)
		return code_buffer
	DllCall("HeapFree", "Ptr", process_heap, "uInt", 0, "Ptr", code_buffer)
}
Also, here are the C++ functions I'm trying to use:

Code: Select all

#include <windows.h>

__int64 GetInt64(char* address, intptr_t offset) {
	return *(__int64*) (address + offset);
}

__int64 qpc() {
	LARGE_INTEGER q;
	QueryPerformanceCounter(&q);
	return q.QuadPart;
}
What am I doing wrong?

Re: Can't Call WinAPI from mCode

Posted: 25 Jul 2020, 13:23
by boiler
I haven’t seen an MCode compiler that supports #include yet.

Re: Can't Call WinAPI from mCode

Posted: 25 Jul 2020, 14:02
by swagfag
this is because u have to provide a function pointer to any external function(s) ur mcode is calling.
as it stands, ur mcode has no notion of what a QueryPerformanceCounter is or where its implementation resides. pass a function ptr as a parameter

Re: Can't Call WinAPI from mCode

Posted: 25 Jul 2020, 14:09
by 1100++
I tried that and it still didn't work.

Re: Can't Call WinAPI from mCode

Posted: 25 Jul 2020, 18:05
by swagfag
i doubt that