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 . 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!
Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?
- Dread_Pony_Roberts
- Table Makers
- Posts: 522
- Joined: Sun Dec 09, 2018 8:46 am
- Reputation: 386
Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?
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.
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.
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
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.
Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?
^ 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
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
Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?
Maybe try:anonmalia wrote: ↑Mon Mar 30, 2020 9:44 amSorry 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.
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
....
Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?
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
Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?
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 skillsDread_Pony_Roberts wrote: ↑Mon Mar 30, 2020 3:02 amHowever, 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.
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!
Re: Any secrets, Tips, etc. for finding GOOD/Unique values in stack to use for compares?
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.
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
BR,
Sun
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
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
Sun
- kantoboy69
- 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?
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
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
Who is online
Users browsing this forum: No registered users