View previous topic :: View next topic |
Author |
Message |
AJarOfLube Newbie cheater
Reputation: 0
Joined: 30 Dec 2015 Posts: 12
|
Posted: Wed Dec 30, 2015 5:25 am Post subject: Has anyone figured out how to hack Game Maker Studio games? |
|
|
Of course you can search/edit values, but I'm more interested in reducing damage, increasing gold pickup, etc.
The problem with GMS games is that they appear to be compiled down to some sort of bytecode, which makes the usual "find code which writes to this address" not work, because that code also writes to 1000's of other addresses.
I've tried to trace backwards to determine where the actual bytecode instruction to write that memory value is loaded, but I'm apparently not skilled enough.
So has anyone successfully been able to write interesting hacks for any of these games?
Examples of games written in GMS:
- Hotline Miami
- Risk of Rain
- Nidhogg
- Hero Siege
- Stealth Bastard
- Valdis Story
- Super Crate Boy
- Gunpoint
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25785 Location: The netherlands
|
Posted: Wed Dec 30, 2015 5:48 am Post subject: |
|
|
You may be able to look at the stack to figure out what is being accessed.
e.g there may be a local path to a string that describes what's being affected
You in find what accesses this address in more infom click on s and then lock the stackview.
You can then do a structure spider on that address (as a shadow address)
_________________
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 |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Wed Dec 30, 2015 8:12 am Post subject: |
|
|
Hotline miami 1.0: I've posted a godmode and ammo table on this forum. Basically the game's scripts were included in text form and compiled during the startup splash screen, I just did some text processing at that stage.
Hotline miami 1.1: vulnerability patched, pretty sure it's not even the same game engine as v1.0 .
Relic hunter 0: Also in gamemaker, I targeted the data.win file in which the variable names are present. If 2 variables have the same name then the engine thinks they are the same, so if a class has a variable named IsInvincible and another named CanMove and you rename one into the other you're basically in godmode as long as you can move... Unless IsInvincible is set to 0 after movement is enabled in which case you're target practice.
My colleagues (Bl00dWolf and deama1234) found out that the ID of a variable is stored as a dword 0x10 bytes after a its value. Unfortunately this ID changes with each patch.
12 better than 6 demo: I stumbled on the string "getting variable oind=%d, varind=%d, arrind=%d - global=%08x(%d)(%d)" so I went for the ID.
oind is variable+0x14 (object index?)
varind is variable+0x10 (same kind of ID as in relic hunter)
arrind is variable+0xC (array index)
This varind can also be found on the stack; when I hooked the fld qword [e**] that reads your variable, I had it at esp+0x24.
I don't know what game you're targeting but so far all the varinds I saw were in the 0x187** format... curious to know how much of a coincidence it is.
_________________
DO NOT PM me if you want help on making/fixing/using a hack. |
|
Back to top |
|
 |
deama1234 Master Cheater
Reputation: 3
Joined: 20 Dec 2014 Posts: 328
|
Posted: Wed Dec 30, 2015 9:56 am Post subject: |
|
|
Yes, game studio games are a pain the ass. I think even then that ID we managed to find still controlled 5 more addresses, so I had to "predict" which one would be the health.
Basically, game studio games will squeeze out your creative juices when you try to hack them.
|
|
Back to top |
|
 |
AJarOfLube Newbie cheater
Reputation: 0
Joined: 30 Dec 2015 Posts: 12
|
Posted: Wed Dec 30, 2015 6:21 pm Post subject: |
|
|
I'm not asking about a specific game, just in general. I've tried hacking a few, with no success.
However, this tip:
Quote: | My colleagues (Bl00dWolf and deama1234) found out that the ID of a variable is stored as a dword 0x10 bytes after a its value. |
was very helpful, and allowed me to write my first GMS-game hacks. Yay!
It would be nice to know more about the format, but unfortunately I'm not skilled enough. For instance, right now I can't make a "x2 gold pickup" hack, because by the time the bytecode to set the gold gets executed, the amount to pick up has already been added to the total value (presumably using a previous bytecode), and I have no idea how to back-trace it. I can't use 'trace' because I don't know where to start, and I can't break on read because the value is read every frame. Any suggestions?
|
|
Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Wed Dec 30, 2015 7:12 pm Post subject: |
|
|
If the original code is a generic x2 gain is: Code: | //currently st(0)=old money+money gain
fsub qword [edi] //now st(0)=money gain
fadd st(0),st(0) //now st(0)=money gain*2
fadd qword [edi] //now st(0)=money gain*2+old money
fstp qword [edi] //original code |
Also my previous post was meant to give game-specific hacks but examples of various approaches you can use in gamemaker games. Game names are here to express where/when the method was found, and to give you the possibility to find the table and look at how it is done exactly.
_________________
DO NOT PM me if you want help on making/fixing/using a hack. |
|
Back to top |
|
 |
AJarOfLube Newbie cheater
Reputation: 0
Joined: 30 Dec 2015 Posts: 12
|
Posted: Wed Dec 30, 2015 7:15 pm Post subject: |
|
|
That doesn't work because GMS always clears the value before setting it
|
|
Back to top |
|
 |
Gniarf Grandmaster Cheater Supreme
Reputation: 43
Joined: 12 Mar 2012 Posts: 1285
|
Posted: Wed Dec 30, 2015 8:09 pm Post subject: |
|
|
Ah fuck, I had completely forgotten that. In this case you'll have to keep track of the money yourself. Something like: Code: | label(SaveMoney)
alloc(MyMoney,4)
//currently st(0)=old money+money gain
cmp dword [MyMoney],-1 //check if MyMoney has been initialized
je SaveMoney //jump if not
fsub dword [MyMoney] //now st(0)=money gain
fadd st(0),st(0) //now st(0)=money gain*2
fadd dword [MyMoney] //now st(0)=money gain*2+old money
SaveMoney:
fst dword [MyMoney]
fstp qword [edi] //original code
...
jmp returnhere
MyMoney:
dd -1 | The first time money is written will initialize the hack and after you should have x2 money gain.
If you want x2 gain right from the first go, I suggest hooking the function that reads money and comparing with your stored copy at every frame.
_________________
DO NOT PM me if you want help on making/fixing/using a hack. |
|
Back to top |
|
 |
AJarOfLube Newbie cheater
Reputation: 0
Joined: 30 Dec 2015 Posts: 12
|
Posted: Wed Dec 30, 2015 10:48 pm Post subject: |
|
|
I take it back, the ID method does not work, it's causing frequent crashes. The IDs must not be unique, as @deama1234 mentioned.
@deama1234, how did you work around this? How did you "predict" whether the current variable represents health?
|
|
Back to top |
|
 |
deama1234 Master Cheater
Reputation: 3
Joined: 20 Dec 2014 Posts: 328
|
Posted: Thu Dec 31, 2015 11:04 am Post subject: |
|
|
Let's see if I remember...
I was trying to get god mode to work in relic hunters zero; but the instruction writing to health was writing to a bunch of other addresses. I managed to find some "ID" (if you can call it that) that managed to narrow down the addresses to like 5 or 10. I don't remember exactly but I think I found out that only the HP is being written to when you just stand still and don't move; so what I did was once the user activated the cheat, it would change the HP to something like 100.459789523; this way I could search for that specific value, then "nop" the instruction trying to change it. Since that is a unique value, it would only ever work on that; the other addressses could just go about their business.
I don't think it works anymore cause after every update the "ID" just kept changing; as well as it's location in the data structure...
It took a while to find that "ID" btw.
If you can't find an "ID", then maybe you can try narrowing it down? Like if you've got 1000 addresses being written to, half of them have a value of 0.53234, and the other ones 10; then you can try and narrow that down by just making it scan for only the "10" ones, or whatever you need.
|
|
Back to top |
|
 |
AJarOfLube Newbie cheater
Reputation: 0
Joined: 30 Dec 2015 Posts: 12
|
Posted: Thu Dec 31, 2015 2:41 pm Post subject: |
|
|
I believe the same code writes to every GameMakerScript variable, it's just their setter function. Ideally we'd reverse engineer the bytecode (I'm assuming the code isn't compiled at runtime anymore, like @Gniaf says it used to be) so we could inject our own, but that sounds way over my head and I don't think anyone else has the motivation.
Instead I'm going to try to find the bytecode instruction that loads variables, and try to determine how it distinguishes the health variable from other variables. There must be a data-structure somewhere mapping all variables from name to ID or something.
|
|
Back to top |
|
 |
h3x1c Master Cheater
Reputation: 17
Joined: 27 Apr 2013 Posts: 306
|
Posted: Fri Jan 01, 2016 3:46 am Post subject: |
|
|
Would it help if we created a really, really small/simple GameMaker game that consisted only of a health value we could modify, and perhaps money or something? I'm not sure how much noise that would cut down on with that instruction, but perhaps it'd make this easier than with a full-fledged GameMaker game.
I actually have a legitimate copy of GameMaker Studio I could do something like this with. Thoughts?
EDIT:
Alright, I just went ahead and made a little test game with GameMaker. It's got health, gold, a timer, music, and a background image. How to enable/disable and increment/decrement is noted in the app.
A quick way to the instruction of interest is to search for health (it's a double). Then, find what writes to it. The FSTP instruction is the one of interest. Show that in the disassembler, then right-click on the instruction in there and choose to show all addresses that instruction accesses. You can then start futzing with values and see how each memory address is used (one is used for minutes, one is used for seconds, one is used for health, and so on).
Maybe it'll be a good start for us. I've got to get some sleep, else I'd continue trying to pin stuff down with this! Download links for the app and source at the bottom of the post.
EDIT 2: Since Rydian also created one, here's a screen shot so you can see if you even want to mess with mine or not prior to downloading.
Game Download: GameMaker Test Game for Cheat Engine
Source Code Download: GameMaker Test Game for Cheat Engine (Source) (Sound file replaced with blank.)
_________________
Last edited by h3x1c on Fri Jan 01, 2016 11:49 am; edited 1 time in total |
|
Back to top |
|
 |
Rydian Grandmaster Cheater Supreme
Reputation: 31
Joined: 17 Sep 2012 Posts: 1358
|
Posted: Fri Jan 01, 2016 4:22 am Post subject: |
|
|
Made this with the early access branch, 1.99.466 (latest until they release a fix for the current startup issue).
There's two versions in the zip, the interpreted kind you'd get out of a base export, and the "compiled" YYC version.
The built-in health changes seem to not work in YYC for some reason, not surprised but it's not noted in the docs.
- The left text object uses a local variable named custom_score.
- The middle test object uses the standard health variable on objects.
- The right test object uses global.custom_score.
http://rydian.net/trainers/hack_test.zip
Project folder included.
(I'm late 'cause installing and updating VSExpress2012 took multiple restarts.)
_________________
|
|
Back to top |
|
 |
h3x1c Master Cheater
Reputation: 17
Joined: 27 Apr 2013 Posts: 306
|
Posted: Fri Jan 01, 2016 9:58 am Post subject: |
|
|
Rydian wrote: | Made this with the early access branch, 1.99.466 (latest until they release a fix for the current startup issue). |
Did you try uninstalling that one Windows update? That fixed the problem for me with startup (though I'm not exactly a fan of uninstalling updates for things like this, lol).
_________________
|
|
Back to top |
|
 |
Rydian Grandmaster Cheater Supreme
Reputation: 31
Joined: 17 Sep 2012 Posts: 1358
|
Posted: Fri Jan 01, 2016 10:57 am Post subject: |
|
|
h3x1c wrote: | Rydian wrote: | Made this with the early access branch, 1.99.466 (latest until they release a fix for the current startup issue). |
Did you try uninstalling that one Windows update? That fixed the problem for me with startup (though I'm not exactly a fan of uninstalling updates for things like this, lol). | I turned off the news feed in the launcher, that's what causes it.
_________________
|
|
Back to top |
|
 |
|