oif2003 wrote: ↑
19 Dec 2018, 14:02
That is good to know!
I will keep that in mind when I need to compile C/C++ with GCC.
Correction: C99 enabling is required for C sources, C++ has it enabled by default. But C++ code is not suitable for creating portable mcodes in general.
I optimized Mcode to be super simple (just 2
DllCalls) and fast (esp. for small mcode snippets).
It can be even 1-lined.
This one is for x64 only
and takes mcoded binary as string of base64 chars only.
We really dont need to compute mcode size here.
We just use 1 byte assuming Mcode's binary size
is not larger than 4096 bytes
is rounding it up to the size of the page
btw b/c the memory is being reserved (MEM_RESERVE
) option here, the specified address is rounded down to the nearest multiple of the allocation granularity - great for performance.
Memory allocated is automatically initialized to zero - its good for uninitialized values to be zeroed and static values with zero/uninitialized ones (at the end of data) r removed from the resulting mcode base64 string.
inside the function contains the resulting mcode BINARY size - this might be returned to the caller as well
I havent seen actual mcodes of the size (resulting binary) being greater than 1k. Anyways its a good practice for bigger snippets to be separated and aligned to the page boundary (every separate mcode chunk can be optimized this way. and further optimized with Align
command in Assembler if the need arises).
Code: Select all
;allocates the virtual addr space of the calling process and changes its protection
;If 1st arg=0, size (we use 1 byte for mcodes <4096) is rounded up to the next page boundary
;Memory allocated is auto-initialized to zero
;0x3000=MEM_COMMIT | MEM_RESERVE, 0x40:PAGE_EXECUTE_READWRITE
p:=DllCall("VirtualAlloc", 'ptr',0, 'uint',1, 'uint',0x3000, 'uint',0x40, "PTR")
;0=zero terminated, 1=Base64 w/o hdr, n (out) contains the mcode BINARY size
(DllCall("crypt32\CryptStringToBinary", 'str',_s, 'uint',0, 'uint',1, 'ptr',p, 'uintp',n:=4096, 'ptr',0, 'ptr',0))
|| (DllCall("GlobalFree", 'ptr',p),p:=0) ;cleanup on decrypt FAIL
1-line inline version (too long line thou - needs to be split anyways):
Somehow, for Unicode AHK v2, "str", string
is faster than "wstr", string
. both variants should be equal (no string conversions) but the latter is significantly slower. There might be wrong DllCall
logic behind that.
I havent figured out how to pass widechars. "str", string
= "ptr", &string
, "uchar", char
for ANSI chars. "ushort", wchar
I just want to make sure there is no hidden conversions inside DllCall done.