Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?

Memory scanning, code injection, debugger internals and other gamemodding related discussion
Post Reply
gideon25
Table Makers
Table Makers
Posts: 1389
Joined: Mon Mar 20, 2017 1:42 am
Reputation: 2289

Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?

Post by gideon25 »

So I am making a table for a game maker game so I am going to use the stack for some compares. I found a great tutorial on youtube by Stephen Chapman about it.

Anyway initially I had lots of problem with crashes but once I decided to just start testing the stack filter/compare BEFORE changing anything, that helped :P. It was on an instruction that accessed around a thousand or so values. So I needed a compare for resources for the game (4 values) so I found one that really looked unique and was shared by my 4 values..I even checked several other addresses (but not all obviously there were 1000 of them) and so I thought I have it! Well no, after activating the script and checking what addresses it accessed after the compare there were still 30 of them. So I tried again, finding another one I thought was unique and checked MOST of the other values. Nope, it effected 5 values, 1 extra value than I needed. So finally I find another one shared among the 4 and I finally have it. The code looks like this:

newmem:
movsd xmm0,[esp+10]
push ecx
mov ecx,[ebp+80]
pushf
cmp ecx,1
jne code
mov ecx,[ebp+C]
cmp ecx,2
jne code
mov ecx,[ebp+18]
cmp ecx,1
jne code
popf
movsd xmm0,[resource]
movsd [esi],xmm0
pop ecx
jmp return

code:
popf
pop ecx
movsd xmm0,[esp+10]
movsd [esi],xmm0
jmp return

resource:
dq (double)5000


Anyway I was wondering if there was a better way? I mean how can you guys tell its not shared by the other addresses? Any secrets, tips, etc or is it all trial and error or by whittling down using multiple compares like I had to. Or is it just because it was a game maker game? Thanks!

User avatar
Dread_Pony_Roberts
Table Makers
Table Makers
Posts: 521
Joined: Sun Dec 09, 2018 8:46 am
Reputation: 385

Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?

Post by Dread_Pony_Roberts »

If had to use this harder method, I would use the commonalities function as demonstrated in this video.


However, there does exist an easier method which I have used in my more recent tables.

Open the Dissect data/structures with the address you want to compare out. Add the top address to your table. Find what access that address. With any luck you would have some (or lots) of code constantly addressing that address. After you stopped scanning, go through each code in search of one which only accesses your address. If you find one then you are in luck, as they are generally very stable. If you don't find any constantly addressing that address, then you can try other addresses on the dissect data/structures list in case you have better luck with them.

To use it in your compares, you will want to write something like this.

Code: Select all

  //assume esi holds your base address

alloc(base,4)
registersymbol(base)

label(code)
label(return)

newmem:
  mov [base],eax
code:
  mov ecx,[eax+72]
  jmp return
  
  //remember to dealloc and unregistersymbol as well
You would want this code as an activator, as your actual code won't work unless this is active.

Now the original code would look something like this.

Code: Select all

//play around with the code as needed

newmem:
movsd xmm0,[esp+10]
push ecx
pushf
cmp [base],esi
jne code
popf
movsd xmm0,[resource]
movsd [esi],xmm0
pop ecx
jmp return

code:
popf
pop ecx
//movsd xmm0,[esp+10]      I'm leaving this deleted because (from what little I see) it seems like this could cause issues if left in
movsd [esi],xmm0
jmp return
Last edited by Dread_Pony_Roberts on Mon Mar 30, 2020 5:44 am, edited 2 times in total.

User avatar
SunBeam
Administration
Administration
Posts: 4704
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 4287

Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?

Post by SunBeam »

^ I really recommend tracing your code or doing back-tracing. Why? Because more than often I found myself in the scenario where, later on in the game or through some action I've not tested at the time of coding, there were OTHER functions calling the function I hooked. As such, what you see in your stack at [esp+10] might never be there when that action occurs. Furthermore, depending on what you do with [esp+10], your game might inexplicably crash. Then you will wonder why, cuz your code is "perfect". Then spend hours not realizing that your function with the hook MIGHT BE CALLED from other places.

So.. while in theory whatever's been said in this topic works.. please do your due diligence and thoroughly CHECK that your hook and stack are not hit from other unknown places to you. That you test not only what meets the immediate eye.

BR,
Sun

User avatar
Rysefox
Table Makers
Table Makers
Posts: 863
Joined: Sat Jun 23, 2018 3:32 pm
Reputation: 914

Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?

Post by Rysefox »

anonmalia wrote:
Mon Mar 30, 2020 9:44 am
Sorry if it's the same question, but..

I have an instruction that accesses too many values and I need to use cmp to change only what I want to. So I'd use that 'dissect data/structures'.. doing this I'LL have the list of it.. the question is: how can I find 'unique' number to cmp? And is that possible?
CODE: SELECT ALL

ucomisd xmm6,[rbx+28] //inside the instruction said
CODE: SELECT ALL

0174 - 4 Bytes 275B4114 : 4294967295 275B3D04 : 0 275B3BC4 : 1082081280 275B3F84 : 0 //in this case the 1st one, 2nd one, 3rd one and 4th are about money, knowledge points, level and level experience
So I have 4294967295 as number to cmp to change only money, but when I cmp that money doesn't change.. just like code below.
CODE: SELECT ALL

cmp [rbx+174],#4294967295 //it's 4bytes so should I use #, none or dword ptr?
jne code
addsd xmm6,xmm0
movsd [rbx+28],xmm6
(When define new structure.. should I use 4096, less or more?)

Well I think finding some number to cmp is hard cos when I find some offset that I see the 1st one is 1 and 2nd one is 0.. some times the 2nd one turns into 1 both values (ingame) will change.
Maybe try:

Code: Select all


[ENABLE]
your stuff 

alloc(ammo,8)

ammo:
dq (double)999

newmem:
cmp [rbx+174],#4294967295
jne code
fld qword ptr [ammo]
fstp qword ptr [rbx+174]
jmp return

code:
your code

....

gideon25
Table Makers
Table Makers
Posts: 1389
Joined: Mon Mar 20, 2017 1:42 am
Reputation: 2289

Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?

Post by gideon25 »

anonmalia wrote:
Tue Mar 31, 2020 9:16 am
@Dread_Pony_Roberts thank you so much for you time sharing that video.
There are LOTS of ways to approach compares for shared instructions:
Have you looked at stephen chapmans videos on structure compares and registers for shared instructions?
Here he demonstrates data structure compares:

Here he demonstrates using the registers to compare:

this is the one on how to hack game master games using the stack for compares (which was what I was talking about in my first post):

Anyway those might help.

UNFORTUNATELY there is a serious lack of tutorial videos on complex back tracing on difficult games. Its all back trace once or twice on a simple game or backtrace once and get lucky, etc. I would love to see some back tracing videos where someone back traces multiple steps all the way to several unique instructions off of say a UE4 game that runs everything thru VcRuntime for instance like was described here:
viewtopic.php?f=15&t=11748

gideon25
Table Makers
Table Makers
Posts: 1389
Joined: Mon Mar 20, 2017 1:42 am
Reputation: 2289

Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?

Post by gideon25 »

Dread_Pony_Roberts wrote:
Mon Mar 30, 2020 3:02 am
However, there does exist an easier method which I have used in my more recent tables.

Open the Dissect data/structures with the address you want to compare out. Add the top address to your table. Find what access that address. With any luck you would have some (or lots) of code constantly addressing that address. After you stopped scanning, go through each code in search of one which only accesses your address. If you find one then you are in luck, as they are generally very stable. If you don't find any constantly addressing that address, then you can try other addresses on the dissect data/structures list in case you have better luck with them.
Yea, unfortunately lately been running into lots of games that run all of its values thru only one opcode. I do a little backtracing then use a combination of compares on the registers at the time of break to whittle down the results, look at whats still shared and THEN use the data structures on whats left .. But I really need better back tracing skills :(

Heres one I did recently on Superlife (rpg) that was UE4 and ran everything thru one opcode in VCRuntime Memcopy. I did a conditional break and trace on the instruction (which was moving RDX) in VCRuntime with my address for XP to get to the actual call in the game memory. So I know that R8 is what gets moved into rdx vcruntime. So I traced back to the call in the actual game memory and then did a conditional break and trace a few instructions up on R8 with my address I found for experience. I then looked at the registers and started the comparing. So I do the registers that don't have any addresses, only values in them first. STILL to many adresses shared. So I know by looking at the structure for experience (R8 is experience). I found all kinds of other things, like energy, time of day, money, etc. NEAR the experience. I also knew that energy is ALWAYS between 0 and 10 and time of day is ALWAYS between 1 and 24. So after those additional compares I only had like 5 addresses left and I just used a structure compare for those 5. See here:

newmem:
pushf
cmp rbx,0
jne code
cmp rdx,4
jne code
cmp r12,0
jne code
cmp [r8+14],#0 //energy range
jl code
cmp [r8+14],#11 //energy range
jge code
cmp [r8+10],#1 //hours left in day range
jl code
cmp [r8+10],#24 //hours left in day range
jg code
cmp [r8+E4],#128 //Compare whats left
jne code
popf
mov [xp],r8
mov rax,[rcx]
mov rdx,r9
jmp return

code:
popf
mov rax,[rcx]
mov rdx,r9
jmp return


Being a better back tracer is what I am eventually hoping to become though!

User avatar
SunBeam
Administration
Administration
Posts: 4704
Joined: Sun Feb 04, 2018 7:16 pm
Reputation: 4287

Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?

Post by SunBeam »

Like I said, you want some solid logic. If you want, you can get IDA, open you .exe in IDA, then let it finish the analysis. Then go to your function and see how many xrefs are to it (assuming it's not a dynamic function, called in the fashion "call qword ptr [rax+D0]"). Based on that you can tell which other places are going to call the function you're about to hook. Thus obtain a better certainty that, if the function is called from a different location than expected, your stack will look good and the [esp+offset] will always contain what you're looking for.

On the other hand, it's not always registers comparing. Have you ever checked out what the ADDRESS in the register contains? Most, if not all, functions are called with parameters.

In C++ world an example would be DealDamage( Character, amount ).

In x86 ASM that would be:

push amount //+8 to esp
push Character //+8 to esp
call DoDamage //+8 to esp when looked at from inside the function

In x64 ASM that would be:

mov rdx,amount //2nd param
mov rcx,Character // 1st param
call DoDamage

So in x86 your "Character" structure (thus an address) will be in [esp+8]. Amount is in [esp+10].

In the x64 version, your "Character" structure (the address) will be in RCX. The amount in RDX.

So rather than discussing shit from 2000+ when people still flaunted these "compare registers" crap, please pull yourselves together and learn how a function is structured and called. The calling conventions. You can then later on devise "comparison" approaches.

Right now you're just mumbling and creating convoluted code that, while it's working and you're feeling self-sufficient, it's nowhere close to the programming logic of how these games were conceived. If you're happy it works and can't be bothered to learn more, then so be it.

Code: Select all

newmem:
pushf
cmp rbx,0
jne code
cmp rdx,4
jne code
cmp r12,0
jne code
cmp [r8+14],#0 //energy range
jl code
cmp [r8+14],#11 //energy range
jge code
cmp [r8+10],#1 //hours left in day range
jl code
cmp [r8+10],#24 //hours left in day range
jg code
cmp [r8+E4],#128 //Compare whats left
jne code
popf
mov [xp],r8
mov rax,[rcx]
mov rdx,r9
jmp return

code:
popf
mov rax,[rcx]
mov rdx,r9
jmp return
What if r8 is 0? Are you checking that anywhere? Cuz "cmp [r8+14]" will result in a big ass crash. Please don't say "yeah, but I know r8 is valid there, cuz I debugged the code". If so, then please read again what I said 2 posts back and the beginning of this post. I really doubt you've thoroughly tested all possibilities of your code being used by OTHER callers. So.. while r8 now is valid, there may be a loading screen in which your hook is ran and r8 is 0. Then you'll waste several more hours not understanding why it crashes, when you could've done this:

test r8,r8
je exit // if 0

Code: Select all

newmem:
pushf
cmp rbx,0
jne code
  cmp rdx,4
  jne code
    cmp r12,0
    jne code
      test r8,r8
      je code
      cmp [r8+14],#0 //energy range
      jl code
        cmp [r8+14],#11 //energy range
        jge code
          cmp [r8+10],#1 //hours left in day range
          jl code
            cmp [r8+10],#24 //hours left in day range
            jg code
              cmp [r8+E4],#128 //Compare whats left
              jne code
@@:
popf
mov [xp],r8
mov rax,[rcx]
mov rdx,r9
jmp return

code:
popf
mov rax,[rcx]
mov rdx,r9
jmp return
BR,
Sun

User avatar
kantoboy69
Expert Cheater
Expert Cheater
Posts: 90
Joined: Fri Aug 30, 2019 5:33 am
Reputation: 50

Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?

Post by kantoboy69 »

Try to find the code that is executed when you trigger something once that uses that code.

e.g.
function code for playerAttack will call function code decreaseHP

you're modifying from decreaseHP and you can backtrace the function code of playerAttack (in theory)
so I'll set an aa script on that first function code playerAttack and will registerasymbol isAttack and set it with value of 1 whenever it is called
then another aa script for decreaseHP code that will check registerasymbol isAttack if 1 or 0
if 1 then it was called by func backtrace code then set isAttack to 0 and do your thing
so if another function call decreaseHP like enemyAttack then isAttack is always 0

This way you don't have to rely on registers and stack too much

This what I did with xenonauts 2, finding the address for the quantity in the store list.
I trigger it when selling item. Back trace to that part and created registered symbol isFetchSellItem
To know that the value I need from get_value is when I click sell item
viewtopic.php?f=15&t=12308#p134819

Post Reply

Who is online

Users browsing this forum: No registered users