|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Filipe_Br Master Cheater Reputation: 3
Joined: 07 Jan 2016 Posts: 272 Location: My house
|
Posted: Fri Jul 07, 2017 7:36 pm Post subject: Calling Lua Functions by auto assembly |
|
|
When I run this script, the result is "1095059523".
Why is this happening?
Code: | [ENABLE]
loadlibrary(luaclient-i386.dll)
luacall(openLuaServer('CELUASERVER'))
CELUA_ServerName:
db 'CELUASERVER',0
alloc(code, 100)
createthread(code)
label(func)
label(param)
code:
push func
call CELUA_GetFunctionReferenceFromName
push 0
push param
push 1
push eax
call CELUA_ExecuteFunctionByReference
xor eax,eax
ret
func:
db 'print',0
param:
db 'CHEAT ENGINE',0
[DISABLE] |
_________________
... |
|
Back to top |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Fri Jul 07, 2017 8:03 pm Post subject: |
|
|
I can tell you why but not how to correct it, if param was for example dd 4 then you'd correctly see 4, the reason you see 1095059523 is because CHEA translates to the hex values 43,48,45,41 which when read as a 4 byte value is 1,095,059,523. I know the C API has functions to convert from char* to lua string and vice versa but I don't know how to do that in asm here...
|
|
Back to top |
|
|
Filipe_Br Master Cheater Reputation: 3
Joined: 07 Jan 2016 Posts: 272 Location: My house
|
Posted: Fri Jul 07, 2017 8:18 pm Post subject: |
|
|
I thought about it too, but the strange thing is that before I had tried it and it worked out.
_________________
... |
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4289
|
Posted: Fri Jul 07, 2017 8:50 pm Post subject: |
|
|
Code: | decimal: 1095059523
hex: 41454843
bytes: 43 48 45 41 (little-endian)
string: CHEA |
Instead of trying to pass the string itself, pass the address of the string to a custom Lua function (i.e. not print) that passes the parameter to readString and prints the result.
Code: | {$lua}
function printStringFromAddr(address)
local s = readString(address,256)
if not s then
return 1
end
print(s)
return 0
end
{$asm}
loadlibrary(luaclient-i386.dll)
luacall(openLuaServer('CELUASERVER'))
CELUA_ServerName:
db 'CELUASERVER',0
globalalloc(newmem,2048)
globalalloc(funcName,256)
globalalloc(strToPrint,256)
createthread(newmem)
newmem:
push funcName
call CELUA_GetFunctionReferenceFromName
push strToPrint
mov ecx,esp
push 0
push ecx
push 1
push eax
call CELUA_ExecuteFunctionByReference
// eax: 0 = good, 1 = bad; do something with that if you want
add esp,4
ret
funcName:
db 'printStringFromAddr',0
strToPrint:
db 'CHEAT ENGINE',0 |
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25287 Location: The netherlands
|
Posted: Sat Jul 08, 2017 2:48 am Post subject: |
|
|
one thing i have to add: CELUA_GetFunctionReferenceFromName creates a new reference each time it's called, so you may wish to store that somewhere and then check if you already have it or not
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
gibberishh Cheater Reputation: 1
Joined: 30 Aug 2021 Posts: 37
|
Posted: Thu Jul 14, 2022 7:29 pm Post subject: |
|
|
Dark Byte wrote: | one thing i have to add: CELUA_GetFunctionReferenceFromName creates a new reference each time it's called, so you may wish to store that somewhere and then check if you already have it or not |
I'm trying to get my head around the Lua function call from ASM. I also have Dark Byte's 64-bit tutorial open simultaneously.
I need 32-bit help, that's why I'm here.
According to celua.txt, CELUA_ExecuteFunctionByReference expects 4 parameters. DB's tutorial is moving the parameters to specific registers (ecx=id, edx=#param, r8=param, r9=sync). In this post, ParkourPenguin is simply pushing the parameters on to the stack. Also, his ret has no parameters, so I'm assuming that all 4 parameters got popped within the DLL.
In yet another example (https://gist.github.com/push0ebp/5b5ac7e11b0b56b56eb58eed6172c62a), I see push being used for CELUA_ExecuteFunction (not by ref), but also ret 8. Which means 8 stack items are being discarded before returning, right? Or is my understanding of ret wrong?
Q1: Which is better, push or specific registers? (I feel push is better because then I'm not messing with already used registers.)
Q2: For 32-bit, how do I know which registers to use? Or can one use any register and their usage is determined by data type? That can't be right because afaik there is no boolean data type in assembly. Just 0 or 1, which are int (or rather bytes).
Q3: How do I know how many extra things were pushed on to the stack during the whole process so that I can cleanly discard them once I'm done with the function call?
Q4: Would it be better for me to use CELUA_ExecuteFunction since I really need to pass only the function name? What's the difference between the two?
Q5: If my Lua function has no return value, will eax still get overwritten? Should I pass the value of eax to my Lua function and have it return the same value?
At the moment I need a super simple function call: zero parameters, zero returned values. I need to update a dropdown list on a specific event. The asm needs to pass an integer (item count) to CreateList() in Lua (so not async). Lua will then update the ddlist with the values Item 1, Item 2, Item #. << These are literally the list options I need, not sample text. I already have Lua code that is successfully manipulating the list, don't need help with that part.
Right now I am updating the ddlist every 5 seconds using a timer. However, I feel this will be a much better way to execute the code because I need the list to be updated only once every map change in the game, and I've already got asm that is hooked into the map change code.
Thanks
_________________
It's not cheating. It's playing by my rules. |
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4289
|
Posted: Thu Jul 14, 2022 8:12 pm Post subject: |
|
|
r8 / r9 are 64-bit registers. 64-bit code has different calling conventions than 32-bit code.
gibberishh wrote: | Which means 8 stack items are being discarded before returning, right? | 8 bytes get discarded after returning. This cleans up the parameters ebp+8 and ebp+C.
Q1,Q2,Q3: You need to adhere to the correct calling convention, whatever that may be. In 64-bit code (the one with r8 and r9 registers), most windows programs adhere to the windows x64 ABI. In 32-bit code, inter-module calls usually adhere to either cdecl (caller removes parameters) or stdcall (callee removes parameters). My example shows how to call stdcall functions, and that ret 8 function is an example of a stdcall function.
Would the newer alternative {$luacode} be of any interest? The Lua code gets run in a separate thread, so you'll have to use synchronize since only the main thread can safely access the GUI.
https://forum.cheatengine.org/viewtopic.php?t=618134
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
gibberishh Cheater Reputation: 1
Joined: 30 Aug 2021 Posts: 37
|
Posted: Fri Jul 15, 2022 1:04 am Post subject: |
|
|
ParkourPenguin wrote: | r8 / r9 are 64-bit registers. 64-bit code has different calling conventions than 32-bit code.
...
Would the newer alternative {$luacode} be of any interest? |
Thanks, this helps a lot.
One question lingers: I get that the r- registers are 64-bit -- but which corresponding registers to use for 32-bit? I can't find examples or documentation for it anywhere. I see Dark Byte's code using ecx and edx for the first 2 params, so maybe the 32-bit version uses the same. Which registers to use for the other two params?
{$luacode} looks very promising. If I understand correctly from an initial reading, it is just a convenient way of calling CELUA_ExecuteFunctionByReference without having to write all the code for it -- no need to explicitly include the dll, set the params, clean up, etc. I'll look deeper into it.
_________________
It's not cheating. It's playing by my rules. |
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4289
|
Posted: Fri Jul 15, 2022 2:06 am Post subject: |
|
|
gibberishh wrote: | One question lingers: I get that the r- registers are 64-bit -- but which corresponding registers to use for 32-bit? I can't find examples or documentation for it anywhere. | If the function is adhering to stdcall calling conventions (such as CELUA_ExecuteFunctionByReference), it uses the stack. You can't use a register. It's like trying to fit a square peg in a round hole- it's not going to fit, and if you try to make it fit, you'll just break everything.
There do exist many calling conventions that store parameters in registers for 32-bit code, but that's irrelevant in this case since you can't magically change what calling convention a compiled function is using.
See here for more calling conventions:
https://en.wikipedia.org/wiki/X86_calling_convention
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
gibberishh Cheater Reputation: 1
Joined: 30 Aug 2021 Posts: 37
|
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|