AHK v2: converting/optimizing scripts Topic is solved
Re: AHK v2: converting/optimizing scripts
You uploaded the .o file so I figure I can maybe just load part (or all) of it to get it to work, but apparently I have failed!
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: AHK v2: converting/optimizing scripts
omg. I made a botch again. =) ok, I re-uploaded the right file. in the same post. .o was output made by ur first script posted concerning TCC combined with AHK
Re: AHK v2: converting/optimizing scripts
All good man, happens to the best of usvvhitevvizard wrote: ↑18 Dec 2018, 16:24omg. I made a botch again. =) ok, I re-uploaded the right file. in the same post. .o was output made by ur first script posted concerning TCC combined with AHK
That's some really nice work, btw. This worked for me:
Code: Select all
b:=FileRead(A_Desktop "\otest.bin", "RAW"), n:=StrLen(b)*2
VarSetCapacity(p, n)
Loop(n//8) ;write program data to memory in 8 byte chunks
i:=A_Index-1, NumPut(NumGet(b,i*8, "int64"), p,i*8, "int64")
DllCall("VirtualProtect", "ptr",&p, "uint",n, "uint",0x40, "uintp",op)
msgbox(DllCall(&p))
msgbox(DllCall(&p))
msgbox(DllCall(&p))
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: AHK v2: converting/optimizing scripts
good to know. but the query is could we get rid of redundant copying from 1 buffer to another? can we just assign 1st buffer address obtained from FileRead?
I believe execution shared with write/read will be prohibited in the future versions of Windows: thats a weak point for security. Malicious code exploiting stack overflows works b/c of that.
Last edited by vvhitevvizard on 18 Dec 2018, 16:38, edited 1 time in total.
Re: AHK v2: converting/optimizing scripts
Very good point, I don't know why that never occurred to mevvhitevvizard wrote: ↑18 Dec 2018, 16:35good to know. but the query is could we get rid of redundant copying from 1 buffer to another? can we just assign 1st buffer address obtained from FileRead?
Code: Select all
p:=FileRead(A_Desktop "\otest.bin", "RAW"), n:=StrLen(p)*2
DllCall("VirtualProtect", "ptr",&p, "uint",n, "uint",0x40, "uintp",op)
msgbox(DllCall(&p))
msgbox(DllCall(&p))
msgbox(DllCall(&p))
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: AHK v2: converting/optimizing scripts
it works! btw I didnt know StrLen works with binary data *2 is to pretend the binary data is widechars array? resulting length was 26 (original file: 25) I wonder how come StrLen skipped some zero DWORDs and made it to the file's end?
it should quit at offset 5-6 (Strlen=3)
Last edited by vvhitevvizard on 18 Dec 2018, 16:49, edited 5 times in total.
Re: AHK v2: converting/optimizing scripts
And since you like this sort of thing:
Anyway, I copied and pasted old code I used and didn't think much of it. I am not sure why it works here.Anyway, maybe it's best to use FileGetSize(f) instead here. Also it works here as long as that parameter is greater than 0.
so we only need:
Code: Select all
DllCall("VirtualProtect",'ptr',&(p:=FileRead(f:=A_Desktop "\otest.bin","RAW")),'uint',FileGetSize(f),'uint',0x40)
loop 3
msgbox(DllCall(&p))
Anyway, I copied and pasted old code I used and didn't think much of it. I am not sure why it works here.
https://msdn.microsoft.com/en-us/librar ... s.85).aspxThe size of the region whose access protection attributes are to be changed, in bytes. The region of affected pages includes all pages containing one or more bytes in the range from the lpAddress parameter to (lpAddress+dwSize). This means that a 2-byte range straddling a page boundary causes the protection attributes of both pages to be changed.
so we only need:
Code: Select all
DllCall("VirtualProtect",ptr,&(p:=FileRead(A_Desktop "\otest.bin","RAW")),uint,1,uint,0x40)
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: AHK v2: converting/optimizing scripts
Indeed. That works for mcodes < 4k bytes (fitting to 1 page). Maybe even more bytes. GetSystemInfo DllCall returns SYSTEM_INFO.dwPageSize about current page size.oif2003 wrote: ↑18 Dec 2018, 16:43so we only need:Code: Select all
DllCall("VirtualProtect",ptr,&(p:=FileRead(A_Desktop "\otest.bin","RAW")),uint,1,uint,0x40)
EDIT: hmm I think we have to calculate size still. depending on where our code chunk is located, we might be close to the page boundary and fail having mapped only 1 of 2 code parts. its a very dangerous lurking error.
but about the last parameter u removed, msdn info says: lpflOldProtect [out]
A pointer to a variable that receives the previous access protection value of the first page in the specified region of pages. If this parameter is NULL or does not point to a valid variable, the function fails.
I tried to replace real pointer with NULL before, it worked but was giving me a distressing feeling of chaos so I kept it intact.
2.
It occurred to me instead of creating a buffer/calling GlobalAlloc and calling VirtualProtect, we can just call VirtualAlloc - the latter just combines both methods.
Last edited by vvhitevvizard on 18 Dec 2018, 17:51, edited 1 time in total.
Re: AHK v2: converting/optimizing scripts
BTW, have you seen this? AHK H v2 comes with MemoryModule (by the same person that wrote the tutorial I linked earlier) that allows you to load DLL directly into memory...
Also, AHK H v2's AutoHotkey.dll looks promising. If I can use another language and only use AHK as a frontend things could get quite interesting!
https://hotkeyit.github.io/v2/docs/MemoryModule.htmMemoryModule was developed by Joachim Bauch and is released under MPL 2.0.
The default windows API functions to load external libraries into a program (LoadLibrary, LoadLibraryEx) only work with files on the filesystem. MemoryModule is a library that can be used to load a DLL completely from memory - without storing on the disk first.
Also, AHK H v2's AutoHotkey.dll looks promising. If I can use another language and only use AHK as a frontend things could get quite interesting!
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: AHK v2: converting/optimizing scripts
haha I was right in the middle of digesting his tutorial. btw I figured out the logic loads the whole DLL even if only 1 imported function is requested by DLL caller
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: AHK v2: converting/optimizing scripts
btw, in ur 2nd code:
remove tcc.__StrPutVar lines and just pass string parameters as "astr" -> DllCall( string2["match"], "astr", haystack, "astr", needle)). This way Unicode AHK will convert the strings to ANSI automagically.
Code: Select all
haystack := "The quick brown fox jumps over the lazy dog."
needle := "fly"
tcc.__StrPutVar(haystack, _haystack)
tcc.__StrPutVar(needle, _needle)
string2 := new tcc('
(
#include <string.h>
int match(char *haystack, char *needle) {
int r = strpbrk(haystack, needle)-haystack+1;
return r > 0 ? r : 0;
}
)', path)
msgbox( 'Found a char from: "' needle '" in "' haystack '" at position: '
. DllCall( string2["match"], "Str", _haystack, "Str", _needle ) )
Spoiler
here goes a new query: trying to enable Unicode support. SOLVED BELOW
Last edited by vvhitevvizard on 19 Dec 2018, 00:29, edited 3 times in total.
Re: AHK v2: converting/optimizing scripts
That was one of those things I was unsure of, and that's why I left them there. I think AStr was also faster, too on some of my tests. Here's a more slim version I was messing around with last night. I changed the Str inside __Get to AStr, removed a few things, and updated some examples. I managed to return wchar_t* in the first example, but I had to use wchar.h
Code: Select all
/*
AHK v2 (64-bit) LIBTCC by oif2003 (16 Dec 2018)
This script allows the use of C code within AHK. C code is compiled and loaded into
memory using libtcc.dll. Function pointers are used for DllCall.
Requires TCC: https://download.savannah.gnu.org/releases/tinycc/tcc-0.9.27-win64-bin.zip
Place script in TCC folder or locate it when prompted. (or set tcc.__defPath)
For more information on TCC: https://bellard.org/tcc/
*/
#singleinstance force
;----------------------------
;define C functions with strings
string1 := new tcc('
(
#include <wchar.h>
wchar_t* hello() {
return L"hello world";
}
)'
)
MsgBox(DllCall(string1["hello"], 'Str'))
haystack := "The quick brown fox jumps over the lazy dog." ,StrPutVar(haystack, _haystack)
needles := "high" ,StrPutVar(needles, _needles)
string2 := new tcc('
(
#include <string.h>
int match(char *haystack, char *needles) {
int r = strpbrk(haystack, needles) - haystack + 1;
return r > 0 ? r : 0;
}
)'
)
pos := DllCall(string2["match"], 'Str', _haystack, 'Str', _needles)
MsgBox('Found "' SubStr(haystack, pos, 1) '" at position ' pos ' in haystack: "' haystack '" using needles: "' needles '"')
;---------------------------
;define C functions in comment blocks
comment1 := new tcc(parseC("Block 1"))
;block tags ("Block 1" here) must not be followed by anything other than a new line
/*_C Block 1
#include <math.h>
int inc() {
static int i = 0;
return ++i;
}
double Csqrt(double x) {
return sqrt(x);
}
*/
MsgBox("Csqrt(" format("{:.3g}", x := 3.14**2) ")"
. " ~ " format("{:.3g}", DllCall(comment1["Csqrt"], 'Double', x, 'Double'))
)
;save function pointer to variable for speed
fp := comment1["inc"], t := A_TickCount
loop 1000000
x := DllCall(fp)
MsgBox("x = " x " (Time elapsed: " A_TickCount - t " ms)" )
;explicitly include User32.dll so MessageBox will work
comment2 := new tcc(parseC("Block 2"),,, "C:\Windows\System32\User32.dll")
/*_C Block 2
#include <stdio.h>
#include <windows.h>
int hello(char name[]) {
char buf[256];
snprintf(buf, sizeof buf, "Hello %s!", name);
MessageBox(0, buf, "Greeting", 0);
}
*/
DllCall(comment2["hello"], 'AStr', A_UserName)
StrPutVar(ByRef s, ByRef v) => (VarSetCapacity(v, StrPut(s, "UTF-8")), StrPut(s, &v, "UTF-8"))
;===============================================================================================================
parseC(tag := "", path:="") { ;reads C code between labels
static script, lastpos := 1
return (
path := path ? path : A_ScriptFullPath
,startLabel := "/*_" "C " tag "`r"
,endLabel := "*/"
,script || script := fileRead(A_ScriptFullPath)
,cStart := InStr(script, startLabel, ,lastpos) + StrLen(startLabel)
,lastpos++ := cEnd := InStr(script, endLabel, , cStart + 1)
,SubStr(script, cStart, cEnd - cStart)
)
}
class tcc {
static __defPath := A_ScriptDir
,__instanceCount := 0
,__hModule := 0
__New(cStr, tccPath := "", opts := "", addfiles*) { ;opts: literal option string, addfiles := variadic array of paths
static _path := "", libtcc
,tcc_add_file := 0x1B2B4
,tcc_compile_string := 0x1CF83
,tcc_free := 0x2FC4
,tcc_new := 0xF703
,tcc_relocate := 0x1C71C
,tcc_set_options := 0xD8E5
,tcc_set_output_type := 0xF5A9
,TCC_OUTPUT_MEMORY := 1
,TCC_RELOCATE_AUTO := 1
tccPath := _path ? _path : (tccPath ? tccPath : tcc.__defPath)
while !FileExist(tccPath "\libtcc.dll")
_path := (tccPath := DirSelect(, , "Locate TCC folder. Close to exit.")) ? tccPath : ExitApp()
(tcc.__hModule) || libtcc := tcc.__hModule := DllCall("LoadLibrary", 'Str', tccPath "\libtcc.dll", 'Ptr')
,this.__context := context := DllCall(libtcc + tcc_new, 'Ptr')
,(opts) && (StrPutVar(opts, options), DllCall(libtcc + tcc_set_options, 'Ptr', context, 'Str', options))
for _, v in addfiles
StrPutVar(v, filename), DllCall(libtcc + tcc_add_file, 'Ptr', context, 'Str', filename)
DllCall(libtcc + tcc_set_output_type, 'Ptr', context, 'UInt', TCC_OUTPUT_MEMORY, 'Int')
,StrPutVar(cStr, _cStr), DllCall(libtcc + tcc_compile_string, 'Ptr', context, 'Str', _cStr, 'Int')
,DllCall(libtcc + tcc_relocate, 'Ptr', context, 'Ptr', TCC_RELOCATE_AUTO, 'Int')
,tcc.__instanceCount++
StrPutVar(ByRef s, ByRef v) => (VarSetCapacity(v, StrPut(s, "UTF-8")), StrPut(s, &v, "UTF-8"))
}
__Get(f) {
static tcc_get_symbol
return DllCall(tcc_get_symbol ? tcc_get_symbol : (tcc_get_symbol := tcc.__hModule + 0x80E2), 'Ptr', this.__context, 'AStr', f, 'Ptr')
}
__Delete() {
static tcc_delete := 0xD543
DllCall(tcc.__hModule + tcc_delete, 'Ptr', this.__context), (--tcc.__instanceCount == 0) && DllCall("FreeLibrary", 'Ptr', tcc.__hModule)
}
}
BTW, AHK H v2 is looking pretty awesome. I've been playing with AutoHotkey.dll, and I might use that for simple GUI's in another language. Still need to test the MemoryModule's Dll loading capabilities.
Update: It works! I loaded AutoHotkey.dll inside another language and used its MemoryModule to manually load a Dll. It worked!
Last edited by oif2003 on 19 Dec 2018, 00:25, edited 1 time in total.
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: AHK v2: converting/optimizing scripts
Code: Select all
#include <wchar.h>
int match(const wchar_t *haystack, const wchar_t *needle) {
int r = wcspbrk(haystack, needle)-haystack+1;
Now my last question: how to inline (expand inside the function) this lib call?
Re: AHK v2: converting/optimizing scripts
A quick look inside wchar.h
Spoiler
and there's also : #include <_mingw.h>- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: AHK v2: converting/optimizing scripts
these headers is a definition of hell =)
I just found a source for wcspbrk
I just found a source for wcspbrk
Code: Select all
/* Find the first occurrence in WCS of any wide-character in ACCEPT. */
wchar_t *
wcspbrk (const wchar_t *wcs, const wchar_t *accept)
{
while (*wcs != L'\0')
if (wcschr (accept, *wcs) == NULL)
++wcs;
else
return (wchar_t *) wcs;
return NULL;
}
Last edited by vvhitevvizard on 19 Dec 2018, 00:53, edited 1 time in total.
Re: AHK v2: converting/optimizing scripts
Hey, I think I will switch over to AutoHotkey H v2 for a little bit. Being able to use AHK features from other programs is pretty awesome and that MemoryModule is pretty slick, too:
I didn't see the Fat Arrow there though, so I will miss that for sure!
Edit: Maybe I missed it in the docs, but Fat Arrow does work!
Code: Select all
msgbox(DllCall(MemoryGetProcAddress(MemoryLoadLibrary(A_Desktop "\\tcc64\\test2.dll"),"hello"), "AStr", A_UserName))
Edit: Maybe I missed it in the docs, but Fat Arrow does work!
Last edited by oif2003 on 19 Dec 2018, 15:15, edited 1 time in total.
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: AHK v2: converting/optimizing scripts
Slick 1-liner of urs as usualoif2003 wrote: ↑19 Dec 2018, 00:47Code: Select all
msgbox(DllCall(MemoryGetProcAddress(MemoryLoadLibrary(A_Desktop "\\tcc64\\test2.dll"),"hello"), "AStr", A_UserName))
I managed to inline this lib function. now its time to tinker with it in assembly )
LOL it has a call to another function wcschr.
pic
so fully expanded inlined C source looks like: No wonder its performance is middling
Code: Select all
#include <string.h>
#include <wchar.h>
inline wchar_t * wcspbrk2 (const wchar_t *wcs, const wchar_t *accept);
inline wchar_t * wcschr (const wchar_t *wcs, const wchar_t wc);
int match(const wchar_t *haystack, const wchar_t *needle) {
int r = wcspbrk2(haystack, needle)-haystack+1;
return r > 0 ? r : 0;
}
//Find the first occurrence in WCS of any wide-character in ACCEPT.
inline wchar_t * wcspbrk2 (const wchar_t *wcs, const wchar_t *accept){
while (*wcs != L'\0')
if (wcschr (accept, *wcs) == NULL)
++wcs;
else
return (wchar_t *) wcs;
return NULL;
}
inline wchar_t * wcschr (const wchar_t *wcs, const wchar_t wc){
do
if (*wcs == wc)
return (wchar_t *) wcs;
while (*wcs++ != L'\0');
return NULL;
}
Re: AHK v2: converting/optimizing scripts
Thanks to HotKeyIt. He really has done some wonderful things with AHK H.
so the rabbit hole continues ... Anyhow, what tools are you using to map those functions? It looks pretty awesome
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: AHK v2: converting/optimizing scripts
old version of IDA. Interactive Debugger. btw it says import table is broken for DLL output of make_c("btest.dll"). ELF works fine
I cant make TCC to inline functions. It accepts inline keyword but ignores it.
Check C listing above - it works in TCC. But in order to tinker with it in assembly I need to move all the 2 lib functions into the caller function
Re: AHK v2: converting/optimizing scripts
Yeah, I think it's time to find a new compiler! Maybe give GCC a shot? joedf has a MCode generator that you can use, too, as a bonus
https://www.autohotkey.com/boards/viewt ... =mcode+gcc
Who is online
Users browsing this forum: Google [Bot] and 37 guests