 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
LuaWeaver How do I cheat?
Reputation: 0
Joined: 16 Oct 2012 Posts: 4
|
Posted: Tue Apr 02, 2013 12:51 pm Post subject: Hacking Love2D |
|
|
Hello. If you didn't know already, Love2D is a game engine which uses the Lua programming language for the games. I'm interested in a couple of things that I've not discovered on my own-
1) Finding the location in memory of the function that is changing a value (I can find what changes it, but not the actual location of the function)
2) Taking that function and calling it (perhaps with different arguments)
and 3) Forcing the function to go to my own function.
If anyone would know how to do this, please tell me how I would achieve these goals (or just give me a gentle nudge in the direction I must go). Thanks in advance.
_________________
--LuaWeaver |
|
Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Tue Apr 02, 2013 1:45 pm Post subject: Re: Hacking Love2D |
|
|
LuaWeaver wrote: | 1) Finding the location in memory of the function that is changing a value (I can find what changes it, but not the actual location of the function) | With "find out what writes to..." you can find the instruction that writes to your variable, then scroll up in CE's memory viewer until you see several (4+) "int 3" or "nop". The function that wrote your variable begins at the first instruction that is not a "int 3" or "nop". However what you'll find that way is the assembly code of the lua interpreter/framework, so if you alter this you're going to disable -for example- all additions within your game -> not good.
If you want to find the lua function that ordered the lua framework to change your variable, well you're wasting your time because lua is a pseudo compiled language ie: when you give a text to lua it first "compiles" it into a pseudo-code and when you play, only the pseudo code is used. Compilation can occur in development studio before releasing, or each time you start the game, or each time you load a map/level/etc, and happens each time you type something in a lua console.
So if you where able to find the location in memory of the lua function that is changing a value, that would be its pseudo code, and the problem is that pseudo code -> text decompilers are still quite buggy as of 2013/04. They work well on laboratory test cases, but on real life scripts, duhhh...nope. They can give useful clues regarding how scripts are made (that information was critical when I hacked Krater), but don't expect to be able to recompile medium-sized and/or complex scripts.
All in all I'd advise banging your head on editing the text luas before the game loads them, if such texts are available.
LuaWeaver wrote: | and 3) Forcing the function to go to my own function.
| That's is called lua hooking. I've never done it personally, but roughtly the idea is that you take a function like:
Code: | function foo()
print("Bar")
end |
and do a hook (replacement) like that:
Code: | OriginalFoo=foo
foo = function()
print("foo is fubared !")
-- OriginalFoo() --if you want to call the original code
end | If you've got access to a lua console within the game it's fairly easy, but if you don't, meh...
One crazy idea -definitely NOT for greenhorn hackers- would be to:
-compile your own application that uses lua. Open source luac (stands for lua compiler) should be enough.
-In its compiled code, find the assembly code of the function luaL_loadstring and copy it.
-Search for luaL_loadstring's code (signature) within your game.
-Hook luaL_loadstring or any other luaL_load* to get the value of the "Lua_State *L".
-Call luaL_loadstring with the proper arguments. Congratulation you just forcefully made yourself a lua console! Now you can do your lua hooking.
|
|
Back to top |
|
 |
LuaWeaver How do I cheat?
Reputation: 0
Joined: 16 Oct 2012 Posts: 4
|
Posted: Tue Apr 02, 2013 2:06 pm Post subject: Re: Hacking Love2D |
|
|
Gniarf wrote: | One crazy idea -definitely NOT for greenhorn hackers- would be to:
-compile your own application that uses lua. Open source luac (stands for lua compiler) should be enough.
-In its compiled code, find the assembly code of the function luaL_loadstring and copy it.
-Search for luaL_loadstring's code (signature) within your game.
-Hook luaL_loadstring or any other luaL_load* to get the value of the "Lua_State *L".
-Call luaL_loadstring with the proper arguments. Congratulation you just forcefully made yourself a lua console! Now you can do your lua hooking. |
Actually, forcing loadstring is one of my goals. However, I am relatively new to this - I'm very good at Lua, however. How would I properly identify luaL_loadstring within luac, and how would I get the Lua_State after that? Then, how would I call luaL_loadstring once more? If you'd kindly reply once more, it's be nice.
Thanks for your reply.
_________________
--LuaWeaver |
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25787 Location: The netherlands
|
Posted: Tue Apr 02, 2013 2:15 pm Post subject: |
|
|
Perhaps it might be of some help to know that the most common implementation of lua_gettop(lua_state*) has an aob of :"8b 4c 24 04 8b 41 08 2b 41 0c c1 f8 04 c3"
_________________
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 |
|
 |
LuaWeaver How do I cheat?
Reputation: 0
Joined: 16 Oct 2012 Posts: 4
|
Posted: Tue Apr 02, 2013 2:31 pm Post subject: |
|
|
Dark Byte wrote: | Perhaps it might be of some help to know that the most common implementation of lua_gettop(lua_state*) has an aob of :"8b 4c 24 04 8b 41 08 2b 41 0c c1 f8 04 c3" |
I have no idea how I would use this, nor can I find a tutorial which will explain it. Mind helping?
_________________
--LuaWeaver |
|
Back to top |
|
 |
mgr.inz.Player I post too much
Reputation: 222
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Tue Apr 02, 2013 4:08 pm Post subject: |
|
|
@DB, interesting. So, there is fancy way to do it with CE?
which opcode access lua_state? Or, is it EAX?
Code: | 8B 4C 24 04 - mov ecx,[esp+04]
8B 41 08 - mov eax,[ecx+08]
2B 41 0C - sub eax,[ecx+0C]
C1 F8 04 - sar eax,04
C3 - ret |
an example would be cool.
Even a simple one like this:
1) we launch CE, and execute this script:
Code: | playerStats = {}
playerStats.Health = 30
if timer~=nil then object_destroy(timer);timer=nil;end
timer = createTimer(nil,true)
timer.Interval = 1000
timer.OnTimer = function (sender)
if playerStats.Health >=100 then
sender.Enabled = false
showMessage('success')
end
end |
2) we launch second CE, attach to first CE, do aobscan. Then .....
then what? Attach debugger, set breakpoint at "ret". Store EAX. We get "lua_state" as EAX right?
Code: |
(...)
lua_state_top = EAX
debug_continueFromBreakpoint(co_run)
(...) |
Then what? We probably need some CE plugin which add registered function otherLua_doString.
something like this:
Code: | otherLua_doString(lua_state_top, 'playerStats.Health = 100') |
_________________
Last edited by mgr.inz.Player on Tue Apr 02, 2013 4:55 pm; edited 1 time in total |
|
Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Tue Apr 02, 2013 4:27 pm Post subject: Re: Hacking Love2D |
|
|
LuaWeaver wrote: | How would I properly identify luaL_loadstring within luac | Compile luac in release mode with debug symbols, debug it (I mean run it under debugger supervision), right click on luaL_loadstring's definition in visual studio->show disassembly. Copy its address and watch it in CE to see the byte code, which should be useful for an aobscan.
LuaWeaver wrote: | and how would I get the Lua_State after that? | Find and hook any frequently used lua_*** function, and store its first argument.
LuaWeaver wrote: | Then, how would I call luaL_loadstring once more? | Use a pair of autoassembler scripts like those:
Code: | [enable]
//code locations
label(FrequentlyUsedLuaFunction_hook)
label(FrequentlyUsedLuaFunction_ReturnHere)
label(InjectedLuaConsole)
label(InjectedLuaConsole_InvalidLuaState)
//variables:
label(LuaStatePointer)
label(LuaCommandToRun)
//locate the functions
aobscan(FrequentlyUsedLuaFunction_aob,...find_those...)
aobscan(lua_loadstring, 8B 54 24 08 83 EC 08 8B C2 56 8D 70 01) //doesn't work on sfxt
alloc(MyCode,1024) //room for MyCode
FrequentlyUsedLuaFunction_aob:
jmp FrequentlyUsedLuaFunction_hook
FrequentlyUsedLuaFunction_ReturnHere:
MyCode:
FrequentlyUsedLuaFunction_hook:
push eax
mov eax,dword [esp+8]
mov dword [LuaStatePointer],eax
pop eax
//paste here the code you overworte at FrequentlyUsedLuaFunction_aob:
/*...
...
...*/
jmp FrequentlyUsedLuaFunction_ReturnHere
InjectedLuaConsole:
cmp dword [LuaStatePointer],0
je InjectedLuaConsole_InvalidLuaState
push LuaCommandToRun
push dword [LuaStatePointer]
call lua_loadstring
add esp, 8 //lua_loadstring is a cdecl 2 argument function
InjectedLuaConsole_InvalidLuaState:
ret
//variables
LuaStatePointer:
dd 0
LuaCommandToRun:
db 'print("fu**bar")'0
registersymbol(LuaCommandToRun) //add a string to your cheat table with address "LuaCommandToRun"
registersymbol(InjectedLuaConsole)
[disable]
dealloc(MyCode)
unregistersymbol(LuaCommandToRun)
unregistersymbol(InjectedLuaConsole)
|
And a second one to run the commands
Code: |
[enable]
createthread(InjectedLuaConsole)
[disable]
createthread(InjectedLuaConsole)
| Unfortunately I tested them on Street Figter x Tekken, but couldn't find lua_loadstring...Looks like that crazy idea doesn't work that easily after all.
Still it should work on games that use a separate lua5.1.dll.
mgr.inz.Player wrote: | then what? Attach debugger, set breakpoint at "ret". Store EAX. We get "lua_state" as EAX right? | Doubtful:
Code: | LUA_API int lua_gettop (lua_State *L) {
return cast_int(L->top - L->base);
}
| I think lua_gettop just returns part of the lua_State, which is a required input.
Last edited by Gniarf on Tue Apr 02, 2013 5:10 pm; edited 3 times in total |
|
Back to top |
|
 |
mgr.inz.Player I post too much
Reputation: 222
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Tue Apr 02, 2013 4:52 pm Post subject: |
|
|
oops, I meant "we get top as EAX".
Anyway, here lua5.1 luaL_loadstring
Code: |
lua5.1-32.luaL_loadstring - 8B 54 24 08 - mov edx,[esp+08]
lua5.1-32.luaL_loadstring+4 - 83 EC 08 - sub esp,08
lua5.1-32.luaL_loadstring+7 - 8B C2 - mov eax,edx
lua5.1-32.luaL_loadstring+9 - 56 - push esi
lua5.1-32.luaL_loadstring+A - 8D 70 01 - lea esi,[eax+01]
lua5.1-32.luaL_loadstring+D - 8D 49 00 - lea ecx,[ecx+00]
lua5.1-32.luaL_loadstring+10 - 8A 08 - mov cl,[eax]
lua5.1-32.luaL_loadstring+12 - 40 - inc eax
lua5.1-32.luaL_loadstring+13 - 84 C9 - test cl,cl
lua5.1-32.luaL_loadstring+15 - 75 F9 - jne lua5.1-32.luaL_loadstring+10
lua5.1-32.luaL_loadstring+17 - 8B 4C 24 10 - mov ecx,[esp+10]
lua5.1-32.luaL_loadstring+1B - 2B C6 - sub eax,esi
lua5.1-32.luaL_loadstring+1D - 52 - push edx
lua5.1-32.luaL_loadstring+1E - 89 44 24 0C - mov [esp+0C],eax
lua5.1-32.luaL_loadstring+22 - 8D 44 24 08 - lea eax,[esp+08]
lua5.1-32.luaL_loadstring+26 - 50 - push eax
lua5.1-32.luaL_loadstring+27 - 68 70340010 - push lua5.1-32.luaL_loadfile+220
lua5.1-32.luaL_loadstring+2C - 51 - push ecx
lua5.1-32.luaL_loadstring+2D - 89 54 24 14 - mov [esp+14],edx
lua5.1-32.luaL_loadstring+31 - E8 2AF0FFFF - call lua5.1-32.lua_load
lua5.1-32.luaL_loadstring+36 - 83 C4 10 - add esp,10
lua5.1-32.luaL_loadstring+39 - 5E - pop esi
lua5.1-32.luaL_loadstring+3A - 83 C4 08 - add esp,08
lua5.1-32.luaL_loadstring+3D - C3 - ret
|
_________________
|
|
Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Tue Apr 02, 2013 5:03 pm Post subject: |
|
|
I'm probably missing something, but what do you want to do with the stack's top? As long as you've got the lua_State* you've got all you need to fire a luaL_loadstring, right?
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25787 Location: The netherlands
|
Posted: Tue Apr 02, 2013 5:07 pm Post subject: |
|
|
Quote: |
Find and hook any frequently used lua_*** function, and store its first argument.
|
lua_gettop is one of the most often called ones
_________________
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 |
|
 |
mgr.inz.Player I post too much
Reputation: 222
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Tue Apr 02, 2013 6:21 pm Post subject: |
|
|
@Dark Byte
mov ecx,[esp+04]
mov eax,[ecx+08]
sub eax,[ecx+0C]
so, Lua_state is in ECX?
Could you test this table? It is for 32bit cheatengine. After loading CT file we allow lua script to launch. CheatEngine should attach to itself. There is timer, ontimer checks if "health" is bigger or equal to 100.
1) tick "script (lua_state hijack)" script
2) set "set to 1 to enable" to 1
No effect. What's wrong?
It doesn't crash (this is a good sign I think).
Description: |
|
 Download |
Filename: |
hijackLua.ct |
Filesize: |
2.17 KB |
Downloaded: |
822 Time(s) |
_________________
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25787 Location: The netherlands
|
Posted: Tue Apr 02, 2013 7:06 pm Post subject: |
|
|
your aa script only loads the script, but it does not execute the function
luaL_loadstring pushes a function on the lua stack that you must execute with lua_call/lua_pcall
check lua_dostring in luahandler.pas
_________________
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 |
|
 |
mgr.inz.Player I post too much
Reputation: 222
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Tue Apr 02, 2013 7:32 pm Post subject: |
|
|
Got this. Made like this:
Code: | push command
push ecx
call lua5.1-32.luaL_loadstring
add esp,08
// and then
push 0
push -1
push 0
push ecx
call lua5.1-32.lua_pcall
add esp,10 |
I think we can finally make any cheat for any Lua based game (single player game), of course if we know table names and etc. I will try this tomorrow with "Don't Starve" as target.
Description: |
Now converted to CE6.2
(previously CE6.2+) |
|
 Download |
Filename: |
hijackLua.ct |
Filesize: |
2.29 KB |
Downloaded: |
845 Time(s) |
_________________
Last edited by mgr.inz.Player on Tue Apr 30, 2013 6:42 pm; edited 2 times in total |
|
Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Tue Apr 02, 2013 7:49 pm Post subject: |
|
|
First thing first: apologies for the mess up, when I saw loadstring I jumped the gun and assumed it automatically ran it, my bad.
...As a fixup I made this:
The lua script is adapted from mgr.inz.Player's.
note: you need to run one lua command after activating the hook for the run script to work.
Description: |
|
 Download |
Filename: |
hijackLua3.ct |
Filesize: |
2.98 KB |
Downloaded: |
955 Time(s) |
|
|
Back to top |
|
 |
mgr.inz.Player I post too much
Reputation: 222
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Tue Apr 30, 2013 6:34 pm Post subject: |
|
|
The problem is that "Don't Starve" doesn't have symbols
and some functions signatures are different than "CE Lua"'s signatures.
But, I found them
OK, now I can use this like this:
Code: | myLuaCommand = 'local a = 2 + 3 * 4'
writeString('ourCommands', myLuaCommand)
writeInteger(getAddress('ourCommands')+#myLuaCommand,0) -- string must end with \0
writeInteger('doit',1) |
This is how I made Don't Starve injected Lua console:
Code: | alloc(newmem,2048)
label(exit)
aobscan(gettopAOB,8B4C24048B41082B410CC1F804C3)
aobscan(loadstringAOB,8b54240883ec088bc2)
aobscan(pcallAOB,8B44241083EC0856)
label(gettopCODE)
registersymbol(gettopCODE)
label(doit)
registersymbol(doit)
label(ourCommands)
registersymbol(ourCommands)
newmem:
cmp dword ptr [doit],0
je short exit
mov dword ptr [doit],0
mov ecx,[esp+04]
push ourCommands
push ecx
call loadstringAOB
add esp,08
mov ecx,[esp+04]
push 0
push -1
push 0
push ecx
call pcallAOB
add esp,10
exit:
mov ecx,[esp+04] // orig
mov eax,[ecx+08] // orig
sub eax,[ecx+0C] // orig
sar eax,04 // orig
ret // orig
doit:
dd 00
ourCommands:
db 0
gettopAOB+a:
gettopCODE:
jmp newmem |
my previous CT file (so we hack Lua used in CE itself, for learning purposes) updated too.
_________________
|
|
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
|
|