 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
nvz Newbie cheater
Reputation: 0
Joined: 02 Jul 2016 Posts: 21
|
Posted: Mon Jul 04, 2016 9:13 am Post subject: lua game hacking (luajit) |
|
|
Hi all, sorry for this long post but i was looking for informations about lua hacking, if i'm not
wrong many users here have done it in many games.
In the last month i tried to learn as much as possible, making some tests on Don't Starve game.
I also created my own "game" in Visual Studio with Luajit and hacked it, so i could see
how lua works. Most of my info was from a page that explains the Lua bytecode:
wiki.luajit.org/Bytecode-2.0
in my game the Lua dll is embedded, but i found the gettop, pcall, and loadstring functions,
and they work correctly, altough if i try to call some game functions the game crashes. But if i use
"generic" functions like "print the date" or "print the system time" it works well.
This is probably because i dont know how to get the Lua state and the
"universe" used by Lua (that is usually called "_G" if i am not wrong). So i can access only
the global variables.
The game loads its lua files from a datafile, anyway i was able to extract the Lua files (in bytecode) and decompile
them with the LuaJit Decompiler (luajit-decomp-master is the name of the file i am using). So i have
a lot of infos of what the scripts do. It would be great if i could replace the files inside the datafile,
so i could use my own scripts, but i have not tried yet.
Anyway i was able to create some hack for the game changing the bytecode at runtime (modifyng
the Double type values, or changing some conditional statements, for example from
"check if value is false" to "check if is true".
So i wanted to ask some suggestions on what to do now:
i wanted to get some Lua game like Dragone Age inquisition and learn from other people hacking.
Do you think it will be useful?
Or maybe i should try to learn how to load my own scripts and change the game variables?
I have also many other questions, but for now it would be great if you can suggest "what to do now".
|
|
| Back to top |
|
 |
atom0s Moderator
Reputation: 205
Joined: 25 Jan 2006 Posts: 8587 Location: 127.0.0.1
|
Posted: Mon Jul 04, 2016 1:08 pm Post subject: Re: lua game hacking (luajit) |
|
|
| nvz wrote: | This is probably because i dont know how to get the Lua state and the
"universe" used by Lua (that is usually called "_G" if i am not wrong). So i can access only
the global variables.
|
Just a little correction here, _G in Lua is just the global table within the state that holds the current environment. You'll find function pointers to things registered to the entire current state as well as library tables (for example string, os, io, etc.) that have been registered to the state.
In terms of hacking the Lua instance, you can hook onto the current state once you find the pointer to it. This is normally not too difficult once you can find some of the Lua calls and locate a static usage of the actual lua_State object. Look for simple calls from Lua like lua_pcall, lua_gettop, etc. within the games source code then find a spot that has a static reference to the pointer of the state. You can just pull the states value then and you're set.
One thing you need to be sure of though is if the game uses a custom implementation of Lua, modded implementation, or Lua vs. LuaJit. If you do not use the same implementation you can run into problems with the byte code not aligning properly and corrupting the state. (Once you have the Lua state pointer you can just use it within an injected DLL that includes Lua itself.)
_________________
- Retired. |
|
| Back to top |
|
 |
nvz Newbie cheater
Reputation: 0
Joined: 02 Jul 2016 Posts: 21
|
Posted: Tue Jul 05, 2016 4:38 am Post subject: |
|
|
ty atomos ^^ ok here is what i tried:
in the game i am hacking this gettop and loadstring code is the same of the one in Don't Starve, instead the pcall is different but i found it:
.exe+1CD890 - 8B 44 24 04 - mov eax,[esp+04]
.exe+1CD894 - 8B 4C 24 10 - mov ecx,[esp+10]
.exe+1CD898 - 53 - push ebx
.exe+1CD899 - 56 - push esi
.exe+1CD89A - 8B 70 08 - mov esi,[eax+08]
.exe+1CD89D - 8A 9E 89000000 - mov bl,[esi+00000089]
.exe+1CD8A3 - 80 E3 F0 - and bl,-10 { 240 }
.exe+1CD8A6 - 85 C9 - test ecx,ecx
.exe+1CD8A8 - 74 1C - je .exe+1CD8C6
.exe+1CD8AA - 7E 11 - jle .exe+1CD8BD
in the dontstarve cheat table posted on this forum the pcall is called with
this:
24A60025 - 8B 4C 24 04 - mov ecx,[esp+04]
24A60029 - 6A 00 - push 00 { 0 }
24A6002B - 6A FF - push -01 { 255 }
24A6002D - 6A 00 - push 00 { 0 }
24A6002F - 51 - push ecx
24A60030 - E8 5BD882DC - call .exe+1CD890
so i used loadstring to load a simple script (a=5) and it worked correctly,
it created a Double type in memory that holds 5.00. Then this memory
is not used until i change it with for example a=6, and it correctly writes
6.00 in the same address, so i am sure that's the real address in memory
of the "a" variable. Do you think then that the Lua State is stored in ecx,
after the code mov ecx,[esp+04] ? When pcall is used, that address
stored in ecx is always the same, and is near the memory area that the
Lua scripts use. Anyway i think i'm still working with the "global table",
not sure yet how to get the "private" table. I'll update the post later when i try other things.
|
|
| Back to top |
|
 |
atom0s Moderator
Reputation: 205
Joined: 25 Jan 2006 Posts: 8587 Location: 127.0.0.1
|
Posted: Tue Jul 05, 2016 8:23 pm Post subject: |
|
|
lua_pcall is defined as:
| Code: | | int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc); |
So with the code you pasted above:
| Code: | 24A60025 - 8B 4C 24 04 - mov ecx,[esp+04] <-- lua_State*
24A60029 - 6A 00 - push 00 { 0 } <-- errfunc
24A6002B - 6A FF - push -01 { 255 } <-- nresults (-1 is multiple returns)
24A6002D - 6A 00 - push 00 { 0 } <-- nargs
24A6002F - 51 - push ecx <-- push the state
24A60030 - E8 5BD882DC - call .exe+1CD890 <-- lua_pcall |
Here the state is coming from the stack, so you would have to trace back to the function that called this one and find where it's pushing the state to the function to obtain a decent pointer for it.
_________________
- Retired. |
|
| Back to top |
|
 |
nvz Newbie cheater
Reputation: 0
Joined: 02 Jul 2016 Posts: 21
|
Posted: Wed Jul 06, 2016 5:19 am Post subject: |
|
|
so that's what these argoments do, very useful. So i think i am already
accessing the correct Lua State, the only problem is that everything in the
game is used in "class", "metamethod" etc. and I am not yet sure on how
to call them. For example, i know there are variable called "Velocity" or
"Strength" but if i use them i get error "trying the call a nil value". Probably
because they belong to some object/class.
Two questions: is there a way to "spy" the tables and see what values
they hold? I am trying to use a code found somewhere, that use:
for n,v in pairs(_G) do etc. etc.
but i'm not sure is working. Also, is there a way to get the "print" output
somewhere, right now i have to search inside the memory to read the output when i use the function. In a console application it would be automatic.
Sorry for the noob questions ^^
|
|
| Back to top |
|
 |
atom0s Moderator
Reputation: 205
Joined: 25 Jan 2006 Posts: 8587 Location: 127.0.0.1
|
Posted: Thu Jul 07, 2016 11:49 am Post subject: |
|
|
If you have the state pointer you can override Lua's print function entirely via lua_register(...). Just redirect it to the output method of your choice, such as debug strings (OutputDebugString) and use a tool like DbgView to watch the messages.
For me, I allow prints to be a multiple argument call, I also convert everything to a string by force to ensure it can be printed directly.
| Code: | static int lua_Print(lua_State* L)
{
// Get stack count to print..
auto top = lua_gettop(L);
// Get tostring function from Lua..
lua_getglobal(L, "tostring");
// Loop stack, call tostring on each argument..
for (int x = 1; x <= top; x++)
{
// Push function and argument and convert to string..
lua_pushvalue(L, top + 1);
lua_pushvalue(L, x);
lua_call(L, 1, 1);
// Validate we have a string return..
if (!lua_isstring(L, -1))
return luaL_error(L, "Unable to convert argument for 'print' to string using 'tostring'.");
// Print the returned value..
auto msg = luaL_checkstring(L, -1);
if (msg != nullptr)
::OutputDebugString(msg);
}
return 0;
} |
And to override it:
| Code: | | lua_register(lpLuaStatePointer, "print", lua_Print); |
_________________
- Retired. |
|
| 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
|
|