GameMaker Variable Names and Indexes

Post here (make sure thread doesn't exist first) any type of tutorials: text, images, videos or oriented discussions on specific games. No online-related discussions/posts OR warez!
Post Reply
aSwedishMagyar
Table Makers
Table Makers
Posts: 670
Joined: Mon Jul 06, 2020 3:19 am
Reputation: 1190

GameMaker Variable Names and Indexes

Post by aSwedishMagyar »

Now we can finally get all the names of variables associated with each object!

Got inspired to return to this after seeing Geo use the VMBuffer to get the offsets (pretty cool that you managed to make sense of them BTW). My method is hopefully the correct/best way and similar to UE4’s FNames where an index is used to retrieve the variable name. It’s probably not new as I think as there may have been people who figured this or at least pieces of this out way before me but I didn’t find any real tutorial on it so I’m claiming “First”.

This first method is for GameMaker .exe’s with virtual functions.
Find the Name list by doing a string search for ‘prototype’ or ‘@@array@@’ or ‘GameObjects’. Make sure it is aligned by 4 byte for x32 or 8 byte for x64, otherwise you might get too many results (should be no more than 3-5). Check each result by searching for the address ( 4byte hex for x32 and 8byte hex for x64) and then searching for something within 3-4 x pointer size and that address (see picture).

Image
Image

It should be located within the .exe. Then you can do an assembly scan for that address like this:

Image
Image

That will get you an instruction that you can do a search for to reliably grab the base.

After that you just read through the whole list (the number of names is typically -0xC from the base) and create a lookup table for each index (the index is just it's position in the array). I’ll go over how to use it later.

Code: Select all

function collectNames()
    local base = getAddressSafe('NameList')
    local num = readInteger(base-0xC)
    base = readPointer(base)
    if base == nil then return end
    nameList = {}
    for i = 0,num do
    	local nAddr= readPointer(base+i*8)
		local name = readString(nAddr,50)
        if name then nameList[i] = name end
    end
    print("NameList Table Parsed")
end
This next method is for pre-compiled .exes (ones where the referenced string will find the function).
Same principle as before but we now have the index stored next to the pointer to the string, so you will need to go two points back when searching for the address (search for address of string, then search for address of pointer to string).
The base you find should be a pointer to the .exe’s directory (as a string) and is accessed by something when you either alt-tab/pause or exit to menu so try one of those before doing an assembly scan (it takes longer with a precompiled .exe). This base will have the NameList at either +54 or +94 (haven’t checked for x64 games but you should be able to tell which one it is). Once you find the base and register it, just loop through the name/index pairs generating a lookup table that uses the index you read as the key --> nameList[index] = name.

Image

Notice how there is a pointer to a small struct with the pointer to the string ("___struct___0") and the index (100000) at each entry.

Code: Select all

function collectNames()
    local base = getAddressSafe('[NameList]')
    if base == nil then return end
    nameList = {}
    local num = readInteger(base+0x8C)
    base = readPointer(base+0x94)
    for i = 0,num do
    	local cAddr = readPointer(base+i*4)
        local index = readInteger(cAddr+4)
        local nAddr = readPointer(cAddr)
	local name = readString(nAddr,50)
        if name then nameList[index] = name end
    end
    print("NameList Table Parsed")
end
Okay, now that we have found the names and created a dictionary, you can finally start checking out what is in each variable list.
The variable array is typically at +2C-->+10 from the object’s instance base (see my previous post on Objects and their instances to understand how to get to it). The number of variables in the array is at +2C->+8 from the object’s instance base.
Each variable’s pointer is separated by +C (the game does a lea ecx[eax+eax*2] and then multiplies by 4) for x32 or +10 (game does a shift left by 4) for x64. The name index is at +4 or +8 for x32 and x64 respectively so just read out the name from your dictionary using the index.
*Note that for some games, the index is the full value read out and others you will need to add or subtract 100000 to it (if the names are blank when populated, just add or subtract 100000 to the index you read from the object).

Image

And there you have it, the entire list of variables for this object (there are way more than what is shown in the picture).

I'll eventually try to get around to making a template table like Cake-san's UE4 table but I think anyone who is interested enough can make sense of this to get what they want (despite my poor explanation of it).

Happy Hacking,
aSwedishMagyar

User avatar
ApeDemon66
Expert Cheater
Expert Cheater
Posts: 226
Joined: Sat Mar 03, 2018 7:31 am
Reputation: 180

Re: GameMaker Variable Names and Indexes

Post by ApeDemon66 »

aSwedishMagyar wrote:
Thu Oct 07, 2021 5:07 am
This first method is for GameMaker .exe’s with virtual functions.
Find the Name list by doing a string search for ‘prototype’ or ‘@@array@@’ or ‘GameObjects’. Make sure it is aligned by 4 byte for x32 or 8 byte for x64, otherwise you might get too many results (should be no more than 3-5). Check each result by searching for the address ( 4byte hex for x32 and 8byte hex for x64) and then searching for something within 3-4 x pointer size and that address ...

...

... The name index is at +4 or +8 for x32 and x64 respectively so just read out the name from your dictionary using the index.
*Note that for some games, the index is the full value read out and others you will need to add or subtract 100000 to it (if the names are blank when populated, just add or subtract 100000 to the index you read from the object).
[Link]

wannaknow
Novice Cheater
Novice Cheater
Posts: 16
Joined: Thu Mar 17, 2022 7:31 am
Reputation: 0

Re: GameMaker Variable Names and Indexes

Post by wannaknow »

Such a noobzor so I have several basic questions.
Would you please answer when you can afford your time?
(Anyone's answer would be appreciated) ^_^

1. I've read this post and also your previous post on objects and instance but still don't get how to get 'base address'
Your previous post provides the template CT files to get the base address but I think there's no explanation about 'how' to get the base.
I want to know the mechanism of getting the base address. Could you give me more detailed explanation?

2. And in this post, I think you are introducing two methods, one for gamemaker .exes with virtual functions and the other for pre-compiled .exes.
What is the difference btw these and how do I know which case the certain game belongs to?
The game 'Slormancer' which is the example in your post, is that the case of .exes with virtual functions?

3. In the first method, you searched for @@array@@ and I guess it's for getting the base address of 'objects'.
What should I search if I want to get the base for 'script'?

4. In the first method, you found the static pointer for @@array@@ which is Slormancer.exe+blahblah, and this would be 14051CD48 in the first Assembly scan picture. That's not the base address? Then what is it and what is it for?

5. You said 'reliably grab the base' with the instruction by the result of Assembly scan.
But I don't know what to do with the instruction to grab the base.
Could you explain the process after assembly scan? I got about ten? of instructions but don't know how after that.
Indeed,..this question occurred actually because I totally don't get why you are searching the pointer of @@array@@ and using assembly scan.

Post Reply

Who is online

Users browsing this forum: No registered users