Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Compare to group of values (list of values) ?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Sat Sep 15, 2018 9:05 pm    Post subject: Compare to group of values (list of values) ? Reply with quote

Hi!

My current task in two words:
I want to figure out how to during injection (preferably in ASM) comparing register to the few groups of total ~370 different values.
In the game i found the instruction that "listening" values of all currently "active" (loaded) foliage and by changing it's value i can also change type of foliage (from some tree to some logs, bushes, grass and so on). But problem is that i want to find the way how to change trees, bushes and all other separately from each other, as some groups.

Here is my current solution. It's good for one map of the game, but bad for others, because on other maps range of values pretty mixed up and i need to use much more compares, which with i can brake my brains with a using of tons of "jg", "jl" and others conditional jumps:
Code:

[ENABLE]

aobscanmodule(foliage_replace,theHunterCotW_F.exe,8B 45 2C 25 FF FF FF 1F 66 44 89 7C FB 04) // should be unique
alloc(newmem,$1000,"theHunterCotW_F.exe"+93C7C4)

label(code)
label(return)
label(trees)
registersymbol(trees)
label(rocks)
registersymbol(rocks)
label(grass)
registersymbol(grass)

newmem:

tree:
  cmp [rbp+2C],#81
  jg rock
  mov eax,[trees]
  and eax,1FFFFFFF
  jmp return

rock:
   cmp [rbp+2C],#133
   jg grasss
   mov eax,[rocks]
   and eax,1FFFFFFF
   jmp return

grasss:
  mov eax,[grass]
  and eax,1FFFFFFF
  jmp return

code:
  mov eax,[rbp+2C]
  and eax,1FFFFFFF
  jmp return


trees:
dd #2
rocks:
dd #1
grass:
dd #4

foliage_replace:
  jmp newmem
  nop
  nop
  nop
return:
registersymbol(foliage_replace)

[DISABLE]

foliage_replace:
  db 8B 45 2C 25 FF FF FF 1F
unregistersymbol(trees)
unregistersymbol(rocks)
unregistersymbol(grass)
unregistersymbol(foliage_replace)
dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: "theHunterCotW_F.exe"+93C7C4

"theHunterCotW_F.exe"+93C79E: E8 ED 0D 00 00     -  call theHunterCotW_F.exe+93D590
"theHunterCotW_F.exe"+93C7A3: 8B 45 20           -  mov eax,[rbp+20]
"theHunterCotW_F.exe"+93C7A6: 4C 8B 4C 24 50     -  mov r9,[rsp+50]
"theHunterCotW_F.exe"+93C7AB: 48 8B 54 24 68     -  mov rdx,[rsp+68]
"theHunterCotW_F.exe"+93C7B0: 89 46 30           -  mov [rsi+30],eax
"theHunterCotW_F.exe"+93C7B3: 8B 45 24           -  mov eax,[rbp+24]
"theHunterCotW_F.exe"+93C7B6: 89 46 34           -  mov [rsi+34],eax
"theHunterCotW_F.exe"+93C7B9: 8B 45 28           -  mov eax,[rbp+28]
"theHunterCotW_F.exe"+93C7BC: 89 46 38           -  mov [rsi+38],eax
"theHunterCotW_F.exe"+93C7BF: F3 0F 11 76 3C     -  movss [rsi+3C],xmm6
// ---------- INJECTING HERE ----------
"theHunterCotW_F.exe"+93C7C4: 8B 45 2C           -  mov eax,[rbp+2C]
"theHunterCotW_F.exe"+93C7C7: 25 FF FF FF 1F     -  and eax,1FFFFFFF
// ---------- DONE INJECTING  ----------
"theHunterCotW_F.exe"+93C7CC: 66 44 89 7C FB 04  -  mov [rbx+rdi*8+04],r15w
"theHunterCotW_F.exe"+93C7D2: 89 04 FB           -  mov [rbx+rdi*8],eax
"theHunterCotW_F.exe"+93C7D5: 66 44 89 6C FB 06  -  mov [rbx+rdi*8+06],r13w
"theHunterCotW_F.exe"+93C7DB: 41 FF 01           -  inc [r9]
"theHunterCotW_F.exe"+93C7DE: 45 3B FC           -  cmp r15d,r12d
"theHunterCotW_F.exe"+93C7E1: 0F 84 A8 00 00 00  -  je theHunterCotW_F.exe+93C88F
"theHunterCotW_F.exe"+93C7E7: 41 0F 28 F0        -  movaps xmm6,xmm8
"theHunterCotW_F.exe"+93C7EB: F3 41 0F 5C F1     -  subss xmm6,xmm9
"theHunterCotW_F.exe"+93C7F0: F3 41 0F 59 F6     -  mulss xmm6,xmm14
"theHunterCotW_F.exe"+93C7F5: F3 41 0F 5F F2     -  maxss xmm6,xmm10
}


From google i found that topic, which seems like exactly what i need, but for some reason solution provided by DB in that topic is not working in my case. Basically, CE give me error "This instruction can't be compiled" when i try to use "mov edi,[comparelist1+ecx*2]" and this happen because of "*2" in the end of that line. Here is my my version of that code, which is working only if i use "mov edi,[comparelist1]", but in such case it comparing "comparelist1" only to the "#30".

Code:

[ENABLE]

aobscanmodule(foliage_replace,theHunterCotW_F.exe,8B 45 2C 25 FF FF FF 1F 66 44 89 7C FB 04) // should be unique
alloc(newmem,$1000,"theHunterCotW_F.exe"+93C7C4)

alloc(comparelist1,128)
comparelist1:
dw #30, #31, #32, #33, #34, #35, #36

label(code)
label(return)
label(trees)
registersymbol(trees)

newmem:
push ecx
push edi
mov ecx,(int)6

myloop:
mov edi,[comparelist1]
cmp word ptr[rbp+2C],di
je inthelist
loop myloop  //loope/ loopne might be used here as well
jmp notinthelist

inthelist:
  mov eax,[trees]
  and eax,1FFFFFFF
  jmp finally

notinthelist:
  mov eax,[rbp+2C]
  and eax,1FFFFFFF
  jmp finally

finally:
  pop edi
  pop ecx
  jmp return

code:
  mov eax,[rbp+2C]
  and eax,1FFFFFFF
  jmp return

trees:
dd #2

foliage_replace:
  jmp newmem
  nop
  nop
  nop
return:
registersymbol(foliage_replace)

[DISABLE]

foliage_replace:
  db 8B 45 2C 25 FF FF FF 1F
unregistersymbol(trees)
unregistersymbol(foliage_replace)
dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: "theHunterCotW_F.exe"+93C7C4

"theHunterCotW_F.exe"+93C79E: E8 ED 0D 00 00     -  call theHunterCotW_F.exe+93D590
"theHunterCotW_F.exe"+93C7A3: 8B 45 20           -  mov eax,[rbp+20]
"theHunterCotW_F.exe"+93C7A6: 4C 8B 4C 24 50     -  mov r9,[rsp+50]
"theHunterCotW_F.exe"+93C7AB: 48 8B 54 24 68     -  mov rdx,[rsp+68]
"theHunterCotW_F.exe"+93C7B0: 89 46 30           -  mov [rsi+30],eax
"theHunterCotW_F.exe"+93C7B3: 8B 45 24           -  mov eax,[rbp+24]
"theHunterCotW_F.exe"+93C7B6: 89 46 34           -  mov [rsi+34],eax
"theHunterCotW_F.exe"+93C7B9: 8B 45 28           -  mov eax,[rbp+28]
"theHunterCotW_F.exe"+93C7BC: 89 46 38           -  mov [rsi+38],eax
"theHunterCotW_F.exe"+93C7BF: F3 0F 11 76 3C     -  movss [rsi+3C],xmm6
// ---------- INJECTING HERE ----------
"theHunterCotW_F.exe"+93C7C4: 8B 45 2C           -  mov eax,[rbp+2C]
"theHunterCotW_F.exe"+93C7C7: 25 FF FF FF 1F     -  and eax,1FFFFFFF
// ---------- DONE INJECTING  ----------
"theHunterCotW_F.exe"+93C7CC: 66 44 89 7C FB 04  -  mov [rbx+rdi*8+04],r15w
"theHunterCotW_F.exe"+93C7D2: 89 04 FB           -  mov [rbx+rdi*8],eax
"theHunterCotW_F.exe"+93C7D5: 66 44 89 6C FB 06  -  mov [rbx+rdi*8+06],r13w
"theHunterCotW_F.exe"+93C7DB: 41 FF 01           -  inc [r9]
"theHunterCotW_F.exe"+93C7DE: 45 3B FC           -  cmp r15d,r12d
"theHunterCotW_F.exe"+93C7E1: 0F 84 A8 00 00 00  -  je theHunterCotW_F.exe+93C88F
"theHunterCotW_F.exe"+93C7E7: 41 0F 28 F0        -  movaps xmm6,xmm8
"theHunterCotW_F.exe"+93C7EB: F3 41 0F 5C F1     -  subss xmm6,xmm9
"theHunterCotW_F.exe"+93C7F0: F3 41 0F 59 F6     -  mulss xmm6,xmm14
"theHunterCotW_F.exe"+93C7F5: F3 41 0F 5F F2     -  maxss xmm6,xmm10
}


If i get it right, we need "mov edi,[comparelist1+ecx*2]" for comparing "comparelist1" with the all the values allocated in it. If i tried to use just "mov edi,[comparelist1+ecx]", it cause crash. I tried also to "play" with ecx-cx edi-di dw-dd-db, learn what LOOP does and how it works (i get that it based on (E)CX) but still can't get what is my mistake here.

At some point i thought that maybe i can use some another solution for increment "comparelist1" and i tried this:
Code:

myloop:
cmp [comparelist1],#290
jg zeroing
mov edi,[comparelist1]
add [comparelist1],ecx
cmp word ptr[rbp+2C],di
je inthelist
loop myloop  //loope/ loopne might be used here as well
jmp notinthelist

But, yeah, this is affected foliage, but in such case it's just jumping from one asset to another with very fast speed :)

If it also could be useful, here is short video where i'm showing how it all works.
Back to top
View user's profile Send private message
sbryzl
Master Cheater
Reputation: 6

Joined: 25 Jul 2016
Posts: 252

PostPosted: Sat Sep 15, 2018 10:58 pm    Post subject: This post has 1 review(s) Reply with quote

Code:
newmem:
push ecx
push edi
xor rcx,rcx
mov cl,(int)6
mov rdi,comparelist1

myloop:
mov ax,word ptr [rdi+rcx*2]
cmp ax, word ptr [rbp+2C]
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 94

Joined: 14 Jul 2007
Posts: 3110

PostPosted: Sun Sep 16, 2018 4:37 am    Post subject: Re: Compare to group of values (list of values) ? Reply with quote

geesve wrote:
Hi!

My current task in two words:
I want to figure out how to during injection (preferably in ASM) comparing register to the few groups of total ~370 different values.
In the game i found the instruction that "listening" values of all currently "active" (loaded) foliage and by changing it's value i can also change type of foliage (from some tree to some logs, bushes, grass and so on). But problem is that i want to find the way how to change trees, bushes and all other separately from each other, as some groups.

Here is my current solution. It's good for one map of the game, but bad for others, because on other maps range of values pretty mixed up and i need to use much more compares, which with i can brake my brains with a using of tons of "jg", "jl" and others conditional jumps:

If it also could be useful, here is short video where i'm showing how it all works.


Seems to me you got most of it figured out, but your problem is the ID change when the map changes, is that correct?

If so, this is comparable to sorting out players in a game - enemies, allies, neutrals and players.
This requires some further digging in the data structures to find the template (the base object) of an instance.
Meaning: you have 500 Actors, but you are interested only in those actors that are actually Pawns or PlayerPawns (this is a common structure in UE games).
The way to do that is either by:
a) backtracking through the stack in various calls to find the address of the base object. (or a piece of code that reads only the objects you want)
b) dissecting the object thoroughly (quite often, there is a way to link them back to their parents and through their parents, to the base object.

The second is usually easier (does not require strong debugging skills), but might be more time consuming than the other.

In your case, it seems you have a code that reads a list of statics and you want to filter for trees only.
Take a tree instance (that struct with XYZ coordinates and other values are an instance of the tree) and dissect it thoroughly.
Then, add another 2-3 trees in the dissect window so you have a few of them side by side.
Then, look for pointers that are pointing to similar structures and pointers that are identical in all structures (they are all green) and dig through those.
Sometimes you find a string, hash or a plain ID that's common in all those trees.
At that point, open up another dissect windows and add a trees and a bunch of other objects.
If the string, hash or a plain ID differs for those, then you found a way to sort them out. If not keep looking.
Assuming that you found the right place, you will need to include that check in your loop - when you do, make sure you check for valid pointers or else you might cause a crash.
The new CE comes with a try{} blocks, comes in handy for things like this.

I hope that helps, good luck!
Back to top
View user's profile Send private message
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Sun Sep 16, 2018 6:12 pm    Post subject: Reply with quote

sbryzl wrote:
Code:
newmem:
push ecx
push edi
xor rcx,rcx
mov cl,(int)6
mov rdi,comparelist1

myloop:
mov ax,word ptr [rdi+rcx*2]
cmp ax, word ptr [rbp+2C]


Oh, that's the trick :) Thanks, now it works as it's expected!

Csimbi wrote:
Seems to me you got most of it figured out, but your problem is the ID change when the map changes, is that correct?

If so, this is comparable to sorting out players in a game - enemies, allies, neutrals and players.
This requires some further digging in the data structures to find the template (the base object) of an instance.
Meaning: you have 500 Actors, but you are interested only in those actors that are actually Pawns or PlayerPawns (this is a common structure in UE games).
The way to do that is either by:
a) backtracking through the stack in various calls to find the address of the base object. (or a piece of code that reads only the objects you want)
b) dissecting the object thoroughly (quite often, there is a way to link them back to their parents and through their parents, to the base object.

The second is usually easier (does not require strong debugging skills), but might be more time consuming than the other.

In your case, it seems you have a code that reads a list of statics and you want to filter for trees only.
Take a tree instance (that struct with XYZ coordinates and other values are an instance of the tree) and dissect it thoroughly.
Then, add another 2-3 trees in the dissect window so you have a few of them side by side.
Then, look for pointers that are pointing to similar structures and pointers that are identical in all structures (they are all green) and dig through those.
Sometimes you find a string, hash or a plain ID that's common in all those trees.
At that point, open up another dissect windows and add a trees and a bunch of other objects.
If the string, hash or a plain ID differs for those, then you found a way to sort them out. If not keep looking.
Assuming that you found the right place, you will need to include that check in your loop - when you do, make sure you check for valid pointers or else you might cause a crash.
The new CE comes with a try{} blocks, comes in handy for things like this.

I hope that helps, good luck!


Yep, ID's is unique for every map (in this case, total 4 maps) but they are stable for particular map. So, for example, if i switch to another map and go back to previous, ID's will be the same (don't know yet if they are changing after game updating though).

By "parents" you mean that kind of cheat when there is injection at some point and further we can see some pointers as "p_player", "m_playerHealth" and so on? It's something that i want to learn further, but at current moment i'm just still feel myself as newbie and i even scare to think about various stack's, base objects and things like that :)

Related to dissect, if i get you right, you talk about "dissect data and structures"? I tried that and this is how i find and get to see that "type of foliage" address. But issue here is that right after that address (i mean, +04) there going group of another object started with the position values, so i can't see any pointers near by. When i tried to find another solution (i thought that maybe here is somewhere else already existing "grouping" for different type of foliage) i was able to catch instruction that write that "structure" of position, rotation, type and i tried to backtrace that instruction and i was able to find another instruction that i can operate, but, as i said, it's still complicated things for me, so i give up and going to that forum.
But thanks for advice! When i saw such cheats, i even doesn't have any idea about which words i should search to find some examples or explanations. Now i know that when i start to feel myself comfortable to start new challenge, i can google something like "parent", "entity list" and so on :)

UPD:
Oh, if someone find that topic from google, here is full example of code. I just added some kind of "switchers", so, for example, if i don't want that some group were affected by script (lets say, in that case i want to leave grass by original), than i can insert in "GrassOnOff" value "0" and grass will be stay as original.

Code:

[ENABLE]

aobscanmodule(foliage_replace,theHunterCotW_F.exe,8B 45 2C 25 FF FF FF 1F 66 44 89 7C FB 04) // should be unique
alloc(newmem,$1000,"theHunterCotW_F.exe"+93C7C4)

alloc(CompareDecidTree,128)
CompareDecidTree:
dw #999, #12, #13, #14, #15, #16, #17, #18, #19, #20, #21, #22, #23, #24, #25, #26, #27, #28, #29
dw #73, #77, #78, #79, #80 //24

alloc(CompareSpruceTreeG,128)
CompareSpruceTreeG:
dw #999, #30, #31, #32, #33, #34, #35, #36, #37, #38, #39, #40, #41, #42, #43, #44, #45
dw #58, #59, #60, #61, #62, #63, #64, #65, #66, #67, #68, #69, #70, #247, #248, #249, #250 //34

alloc(CompareSpruceTreeY,128)
CompareSpruceTreeY:
dw #999, #51, #52, #53, #54, #55, #56, #57, #275, #276 //10

alloc(CompareRocks,128)
CompareRocks:
dw #999, #81, #82, #83, #84, #85, #86, #87, #88, #89, #90, #91, #92, #93, #94, #95, #96, #97, #98
dw #99, #100, #101, #102, #103, #104, #105, #106, #107, #108, #109, #110, #111, #112, #113
dw #114, #115, #116, #117, #118, #119, #120, #121, #122, #123, #124, #125, #126, #127, #128
dw #129, #130, #131, #132, #208, #209, #210, #211, #273, #274, #284, #285, #286, #287, #288 //64

alloc(CompareGrass,256)
CompareGrass:
dw #999, #131, #132, #133, #134, #135, #136, #137, #138, #139, #140, #141, #142, #143, #144, #145
dw #146, #147, #148, #149, #150, #151, #152, #153, #154, #155, #157, #158, #159, #160, #161
dw #170, #171, #172, #173, #174, #175, #176, #177, #178, #179, #180, #181, #182, #183, #184
dw #185, #186, #187, #188, #189, #190, #191, #192, #193, #194, #195, #196, #197, #206, #207
dw #212, #213, #214, #215, #216, #217, #218, #219, #220, #221, #222, #223, #224, #225, #226
dw #227, #228, #229, #230, #231, #232, #233, #234, #235, #236, #237, #238, #239, #240, #241
dw #242, #243, #244, #245, #246, #251, #252, #253, #254, #255, #256, #257, #258, #260, #261
dw #268, #269, #270, #271, #272, #277, #278, #280, #281, #283, #289, #290 //118

alloc(CompareBushes,128)
CompareBushes:
dw #999, #71, #72, #74, #75, #76, #156, #259, #282 //9

alloc(CompareLogs,128)
CompareLogs:
dw #999, #46, #47, #48, #49, #50, #162, #163, #164, #165, #166, #167, #168, #169, #262, #263, #264
dw #265, #266, #267, #279 //21

label(code)
label(return)

label(DecidTrees)
registersymbol(DecidTrees)
label(SpruceTreesG)
registersymbol(SpruceTreesG)
label(SpruceTreesY)
registersymbol(SpruceTreesY)
label(Rocks)
registersymbol(Rocks)
label(Grass)
registersymbol(Grass)
label(Bushes)
registersymbol(Bushes)
label(Logs)
registersymbol(Logs)

label(DecidTreesOnOff)
registersymbol(DecidTreesOnOff)
label(SpruceTreesGOnOff)
registersymbol(SpruceTreesGOnOff)
label(SpruceTreesYOnOff)
registersymbol(SpruceTreesYOnOff)
label(RocksOnOff)
registersymbol(RocksOnOff)
label(GrassOnOff)
registersymbol(GrassOnOff)
label(BushesOnOff)
registersymbol(BushesOnOff)
label(LogsOnOff)
registersymbol(LogsOnOff)

newmem:
  push ecx
  push edi
  xor rcx,rcx
  mov cl,(int)23
  mov rdi,CompareDecidTree
  myloop1:
  mov ax,word ptr [rdi+rcx*2]
  cmp ax, word ptr [rbp+2C]
  je decidtree
  loop myloop1
  jmp notinthelist1

decidtree:
  cmp [DecidTreesOnOff],0
  je short @f
  pop edi
  pop ecx
  mov eax,[DecidTrees]
  and eax,1FFFFFFF
  jmp return
    @@:
    pop edi
    pop ecx
    mov eax,[rbp+2C]
    and eax,1FFFFFFF
    jmp return

notinthelist1:
  pop edi
  pop ecx
  push ecx
  push edi
  xor rcx,rcx
  mov cl,(int)33
  mov rdi,CompareSpruceTreeG
  myloop2:
  mov ax,word ptr [rdi+rcx*2]
  cmp ax, word ptr [rbp+2C]
  je SpruceTreeG
  loop myloop2
  jmp notinthelist2

SpruceTreeG:
  cmp [SpruceTreesGOnOff],0
  je short @f
  pop edi
  pop ecx
  mov eax,[SpruceTreesG]
  and eax,1FFFFFFF
  jmp return
    @@:
    pop edi
    pop ecx
    mov eax,[rbp+2C]
    and eax,1FFFFFFF
    jmp return

notinthelist2:
  pop edi
  pop ecx
  push ecx
  push edi
  xor rcx,rcx
  mov cl,(int)9
  mov rdi,CompareSpruceTreeY
  myloop3:
  mov ax,word ptr [rdi+rcx*2]
  cmp ax, word ptr [rbp+2C]
  je SpruceTreeY
  loop myloop3
  jmp notinthelist3

SpruceTreeY:
  cmp [SpruceTreesYOnOff],0
  je short @f
  pop edi
  pop ecx
  mov eax,[SpruceTreesY]
  and eax,1FFFFFFF
  jmp return
    @@:
    pop edi
    pop ecx
    mov eax,[rbp+2C]
    and eax,1FFFFFFF
    jmp return

notinthelist3:
  pop edi
  pop ecx
  push ecx
  push edi
  xor rcx,rcx
  mov cl,(int)63
  mov rdi,CompareRocks
  myloop4:
  mov ax,word ptr [rdi+rcx*2]
  cmp ax, word ptr [rbp+2C]
  je Rocks1
  loop myloop4
  jmp notinthelist4

Rocks1:
  cmp [RocksOnOff],0
  je short @f
  pop edi
  pop ecx
  mov eax,[Rocks]
  and eax,1FFFFFFF
  jmp return
    @@:
    pop edi
    pop ecx
    mov eax,[rbp+2C]
    and eax,1FFFFFFF
    jmp return

notinthelist4:
  pop edi
  pop ecx
  push ecx
  push edi
  xor rcx,rcx
  mov cl,(int)117
  mov rdi,CompareGrass
  myloop5:
  mov ax,word ptr [rdi+rcx*2]
  cmp ax, word ptr [rbp+2C]
  je Grass1
  loop myloop5
  jmp notinthelist5

Grass1:
  cmp [GrassOnOff],0
  je short @f
  pop edi
  pop ecx
  mov eax,[Grass]
  and eax,1FFFFFFF
  jmp return
    @@:
    pop edi
    pop ecx
    mov eax,[rbp+2C]
    and eax,1FFFFFFF
    jmp return

notinthelist5:
  pop edi
  pop ecx
  push ecx
  push edi
  xor rcx,rcx
  mov cl,(int)8
  mov rdi,CompareBushes
  myloop6:
  mov ax,word ptr [rdi+rcx*2]
  cmp ax, word ptr [rbp+2C]
  je Bushes1
  loop myloop6
  jmp notinthelist6

Bushes1:
  cmp [BushesOnOff],0
  je short @f
  pop edi
  pop ecx
  mov eax,[Bushes]
  and eax,1FFFFFFF
  jmp return
    @@:
    pop edi
    pop ecx
    mov eax,[rbp+2C]
    and eax,1FFFFFFF
    jmp return

notinthelist6:
  pop edi
  pop ecx
  push ecx
  push edi
  xor rcx,rcx
  mov cl,(int)20
  mov rdi,CompareLogs
  myloop7:
  mov ax,word ptr [rdi+rcx*2]
  cmp ax, word ptr [rbp+2C]
  je Logs1
  loop myloop7
  jmp code

Logs1:
  cmp [LogsOnOff],0
  je short @f
  pop edi
  pop ecx
  mov eax,[Logs]
  and eax,1FFFFFFF
  jmp return
    @@:
    pop edi
    pop ecx
    mov eax,[rbp+2C]
    and eax,1FFFFFFF
    jmp return

code:
  pop edi
  pop ecx
  mov eax,[rbp+2C]
  and eax,1FFFFFFF
  jmp return

DecidTrees:
dd #2
SpruceTreesG:
dd #3
SpruceTreesY:
dd #3
Rocks:
dd #1
Grass:
dd #4
Bushes:
dd #4
Logs:
dd #5

DecidTreesOnOff:
dd #1
SpruceTreesGOnOff:
dd #1
SpruceTreesYOnOff:
dd #1
RocksOnOff:
dd #1
GrassOnOff:
dd #1
BushesOnOff:
dd #1
LogsOnOff:
dd #1

foliage_replace:
  jmp newmem
  nop
  nop
  nop
return:
registersymbol(foliage_replace)

[DISABLE]

foliage_replace:
  db 8B 45 2C 25 FF FF FF 1F
unregistersymbol(DecidTrees)
unregistersymbol(SpruceTreesG)
unregistersymbol(SpruceTreesY)
unregistersymbol(Rocks)
unregistersymbol(Grass)
unregistersymbol(Bushes)
unregistersymbol(Logs)
unregistersymbol(foliage_replace)
dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: "theHunterCotW_F.exe"+93C7C4

"theHunterCotW_F.exe"+93C79E: E8 ED 0D 00 00     -  call theHunterCotW_F.exe+93D590
"theHunterCotW_F.exe"+93C7A3: 8B 45 20           -  mov eax,[rbp+20]
"theHunterCotW_F.exe"+93C7A6: 4C 8B 4C 24 50     -  mov r9,[rsp+50]
"theHunterCotW_F.exe"+93C7AB: 48 8B 54 24 68     -  mov rdx,[rsp+68]
"theHunterCotW_F.exe"+93C7B0: 89 46 30           -  mov [rsi+30],eax
"theHunterCotW_F.exe"+93C7B3: 8B 45 24           -  mov eax,[rbp+24]
"theHunterCotW_F.exe"+93C7B6: 89 46 34           -  mov [rsi+34],eax
"theHunterCotW_F.exe"+93C7B9: 8B 45 28           -  mov eax,[rbp+28]
"theHunterCotW_F.exe"+93C7BC: 89 46 38           -  mov [rsi+38],eax
"theHunterCotW_F.exe"+93C7BF: F3 0F 11 76 3C     -  movss [rsi+3C],xmm6
// ---------- INJECTING HERE ----------
"theHunterCotW_F.exe"+93C7C4: 8B 45 2C           -  mov eax,[rbp+2C]
"theHunterCotW_F.exe"+93C7C7: 25 FF FF FF 1F     -  and eax,1FFFFFFF
// ---------- DONE INJECTING  ----------
"theHunterCotW_F.exe"+93C7CC: 66 44 89 7C FB 04  -  mov [rbx+rdi*8+04],r15w
"theHunterCotW_F.exe"+93C7D2: 89 04 FB           -  mov [rbx+rdi*8],eax
"theHunterCotW_F.exe"+93C7D5: 66 44 89 6C FB 06  -  mov [rbx+rdi*8+06],r13w
"theHunterCotW_F.exe"+93C7DB: 41 FF 01           -  inc [r9]
"theHunterCotW_F.exe"+93C7DE: 45 3B FC           -  cmp r15d,r12d
"theHunterCotW_F.exe"+93C7E1: 0F 84 A8 00 00 00  -  je theHunterCotW_F.exe+93C88F
"theHunterCotW_F.exe"+93C7E7: 41 0F 28 F0        -  movaps xmm6,xmm8
"theHunterCotW_F.exe"+93C7EB: F3 41 0F 5C F1     -  subss xmm6,xmm9
"theHunterCotW_F.exe"+93C7F0: F3 41 0F 59 F6     -  mulss xmm6,xmm14
"theHunterCotW_F.exe"+93C7F5: F3 41 0F 5F F2     -  maxss xmm6,xmm10
}
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 94

Joined: 14 Jul 2007
Posts: 3110

PostPosted: Mon Sep 17, 2018 4:12 am    Post subject: This post has 1 review(s) Reply with quote

Quote:
It's something that i want to learn further, but at current moment i'm just still feel myself as newbie and i even scare to think about various stack's, base objects and things like that Smile

Once you're done with this, you'll be ready Wink

Quote:

Related to dissect, if i get you right, you talk about "dissect data and structures"? I tried that and this is how i find and get to see that "type of foliage" address. But issue here is that right after that address (i mean, +04) there going group of another object started with the position values, so i can't see any pointers near by.

Yes, that's what I meant.
Usually an object starts with a pointer at offset 0x0 to a code table (a list of which pointers that point to the object's methods. E.g. health.get()).
Then, there may be pointers to the base class, or the object's template.
Then, there may be sections for stuff the object inherited.
Finally, there may be a list of things that belong to this object only (its own properties) - they may be in different arrays though.

It seems you me you're going down the right path.
Once you were at it for a few days, you will start seeing patterns and relations between objects.
Just keep digging. IMHO, this is the fun part and it always take time - but having done it will give you that great feeling of accomplishment.
I promise you this: once you have figured out the data structures, building the code will be a breeze.

PS.
Have you considered implementing a switch() statement?
That way, you don't need to check any values, you just jump immediately to the right code.
It can get complex Wink
Back to top
View user's profile Send private message
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Wed Sep 19, 2018 10:58 am    Post subject: Reply with quote

Csimbi wrote:
Yes, that's what I meant.
Usually an object starts with a pointer at offset 0x0 to a code table (a list of which pointers that point to the object's methods. E.g. health.get()).
Then, there may be pointers to the base class, or the object's template.
Then, there may be sections for stuff the object inherited.
Finally, there may be a list of things that belong to this object only (its own properties) - they may be in different arrays though.

It seems you me you're going down the right path.
Once you were at it for a few days, you will start seeing patterns and relations between objects.
Just keep digging. IMHO, this is the fun part and it always take time - but having done it will give you that great feeling of accomplishment.
I promise you this: once you have figured out the data structures, building the code will be a breeze.

PS.
Have you considered implementing a switch() statement?
That way, you don't need to check any values, you just jump immediately to the right code.
It can get complex ;-)


I remember when i does previously some dissect's, i saw how groups that i was looking for has same pointers. I did not pay much attention to it and i was looking for that pointers as another array of bytes, but seems like when i get something similar next time, than this will be good example to play with it. Or this is even what i need right now... I'm tried to find how to change type value of all grass that does not affected by current script. Trick is that i can't find XYZ values of particular bush (in the video that i posted above at 0:50 here is some grass and bushes are still there) or anything else related to it. It seems like it generated from bitmap, because i was able to find ground bitmaps tile offset values, but those affect just diffuse ground maps. And nowhere close to that instructions i can't find anything related to grass. I'm absolutely agree about fun part! When there is something such hard to "catch up", it going to looks as some strong logic puzzle/riddle :)

Thanks for noticing not better switch! Yeah, would be better to avoid compares with the groups when we doesn't need it and keeping script simple. Like this:
Code:

newmem:
  push ecx
  push edi
  cmp [DecidTreesOnOff],0
  je notinthelist1
  xor rcx,rcx
  mov cl,(int)23
  mov rdi,CompareDecidTree
  myloop1:
  mov ax,word ptr [rdi+rcx*2]
  cmp ax, word ptr [rbp+2C]
  je decidtree
  loop myloop1
  jmp notinthelist1

decidtree:
  pop edi
  pop ecx
  mov eax,[DecidTrees]
  and eax,1FFFFFFF
  jmp return

notinthelist1:
  pop edi
  pop ecx
  push ecx
  push edi
  cmp [SpruceTreesGOnOff],0
  je notinthelist2
  xor rcx,rcx
Back to top
View user's profile Send private message
geesve
Cheater
Reputation: 0

Joined: 15 Feb 2017
Posts: 25

PostPosted: Sat Sep 22, 2018 9:29 pm    Post subject: Reply with quote

Csimbi
Man, thank you so much! When i was able to find what i was looking for (grass RGB multipliers), i got the problem that there is required some manual work with dissect data to find stable compare. And there was pretty suspicious 4 bytes... That actually was pointers and by replacing them from one to another i'm actually found that i changed textures. Well, i decide to go through that pointers to see where is it can lead me (never do so before) and i'm end with 4 byte value, which actually was texture ID's. They are slightly random every game launch, but, if i have enough of brains or luck to figure out how to deal with it, than there is would be possible to switch every texture on every object. Not only diffuse, but normals, displacement, specular... So, thank you! If you do not talk here about pointers in dissect data, i will probably did not pay attention to that :)

As proof of concept: https://imgur.com/Q6kNHQE
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 94

Joined: 14 Jul 2007
Posts: 3110

PostPosted: Sun Sep 23, 2018 4:33 am    Post subject: Reply with quote

Good stuff, congrats!
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites