Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Calling Lua Functions by auto assembly

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> 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

PostPosted: Fri Jul 07, 2017 7:36 pm    Post subject: Calling Lua Functions by auto assembly Reply with quote

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
View user's profile Send private message
FreeER
Grandmaster Cheater Supreme
Reputation: 53

Joined: 09 Aug 2013
Posts: 1091

PostPosted: Fri Jul 07, 2017 8:03 pm    Post subject: Reply with quote

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
View user's profile Send private message
Filipe_Br
Master Cheater
Reputation: 3

Joined: 07 Jan 2016
Posts: 272
Location: My house

PostPosted: Fri Jul 07, 2017 8:18 pm    Post subject: Reply with quote

I thought about it too, but the strange thing is that before I had tried it and it worked out.
_________________
...
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Fri Jul 07, 2017 8:50 pm    Post subject: Reply with quote

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
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

Joined: 09 May 2003
Posts: 25287
Location: The netherlands

PostPosted: Sat Jul 08, 2017 2:48 am    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
gibberishh
Cheater
Reputation: 1

Joined: 30 Aug 2021
Posts: 37

PostPosted: Thu Jul 14, 2022 7:29 pm    Post subject: Reply with quote

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
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Thu Jul 14, 2022 8:12 pm    Post subject: Reply with quote

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
View user's profile Send private message
gibberishh
Cheater
Reputation: 1

Joined: 30 Aug 2021
Posts: 37

PostPosted: Fri Jul 15, 2022 1:04 am    Post subject: Reply with quote

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
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Fri Jul 15, 2022 2:06 am    Post subject: Reply with quote

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
View user's profile Send private message
gibberishh
Cheater
Reputation: 1

Joined: 30 Aug 2021
Posts: 37

PostPosted: Fri Jul 15, 2022 3:37 am    Post subject: Reply with quote

ParkourPenguin wrote:
If the function is adhering to stdcall calling conventions (such as CELUA_ExecuteFunctionByReference), it uses the stack. You can't use a register.


Excellent. Thank you thank you thank you. Wish the expectations of functions were documented somewhere (or at least somewhere that I could find). It would help newbs like me tremendously even if veterans "just know".

Right now I'm crossing fingers and hoping that push will also work for 32-bit CELUA_GetFunctionReferenceFromName. Coz in DB's 64-bit tutorial that function is expecting the param in rcx.

Guess if I end up figuring this out, I'll write my own 32-bit tutorial Smile

* Apologies, unable to submit a rep point because the forum keeps saying I need to rep a different user before I can submit one for you Sad

_________________
It's not cheating. It's playing by my rules.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites