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 


Custom Type and Actual Game Address
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
Zanzer
I post too much
Reputation: 126

Joined: 09 Jun 2013
Posts: 3278

PostPosted: Thu Apr 30, 2015 9:41 pm    Post subject: Custom Type and Actual Game Address Reply with quote

I was attempting to build a custom type and the 64-bit code suggested RCX holds the address containing the value.
However, this address is not the game's address containing the value.

Is the actual game address accessible from within the conversion routines?

For example, if I defined ConvertRoutine as below, I would expect address 7FEFDA21000 to display the value 7FEFDA21000 using this type.
Code:
mov rax,rcx

Instead, it displays some other address and is constantly changing as CE refreshes the display.
Back to top
View user's profile Send private message
mgr.inz.Player
I post too much
Reputation: 222

Joined: 07 Nov 2008
Posts: 4438
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Fri May 01, 2015 3:43 am    Post subject: Reply with quote

Nope. Because memoryscanner unit is designed to work on copies, and copies of copies (compare to first scan results/compare to last scan results).

Also MemoryRecord unit works on copies (buf variable):
Code:
function TMemoryRecord.GetValue: string;
var
  br: PtrUInt;
  bufsize: integer;
  buf: pointer;
  ...
  ...
begin

  bufsize:=getbytesize;
  ...
  ...
  getmem(buf,bufsize);
  GetRealAddress;

  if ReadProcessMemory(processhandle, pointer(realAddress), buf, bufsize,br) then
  begin
    case vartype of
      vtCustom:
      begin
        if customtype<>nil then
        begin
          if customtype.scriptUsesFloat then
            result:=FloatToStr(customtype.ConvertDataToFloat(buf))
          else
            if         showashex then result:=inttohex(customtype.ConvertDataToInteger(buf),8)
            else if showassigned then result:=inttostr(integer(customtype.ConvertDataToInteger(buf)))
            else                      result:=inttostr(customtype.ConvertDataToInteger(buf));
        end
        else
          result:='error';
      end;
      ...
      ...
      ...
    end;
  end
  ...
  ...
  ...
  ...
  freemem(buf);
end;






Yes, it is doable, but would require changing some code in CE source.

_________________
Back to top
View user's profile Send private message MSN Messenger
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25836
Location: The netherlands

PostPosted: Fri May 01, 2015 4:19 am    Post subject: Reply with quote

the TCheckroutine in memscan would then also need to be changed, and for every check, wheter it's a valid found result or not, the address needs to be calculated, which will slow down the scan.
so not sure if an address based custom type is worth it to slow down the normal scans, or fragment the scanner's design even more (there is already seperate handling of multiaob's and the all type)

Code:
 
if checkroutine(p,nil) then //found one
        StoreResultRoutine(base+ptruint(p)-ptruint(buffer),p);

_________________
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
View user's profile Send private message MSN Messenger
Zanzer
I post too much
Reputation: 126

Joined: 09 Jun 2013
Posts: 3278

PostPosted: Fri May 01, 2015 11:26 am    Post subject: Reply with quote

Sorry, I haven't glanced at the source code, but it wouldn't be as simple as sending the address by value as an additional argument?

All of the functions could simply ignore it and continue using their local copies of the value.

But then if the address is ever needed, we could get it from the stack.

pseudo code:
local value = readInteger(address)
compareResult(value, address)

The only reason this has come up is because of GTA5's encryption logic.
They XOR every address' value with the address itself.
So if I could add a custom type which does the same, I could more easily find the values.
Back to top
View user's profile Send private message
mgr.inz.Player
I post too much
Reputation: 222

Joined: 07 Nov 2008
Posts: 4438
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Fri May 01, 2015 6:39 pm    Post subject: Reply with quote

I changed CustomTypeHandler and MemoryRecordUnit units.
(and it is still backward compatible for older custom AA scripts)

Results:





I'm still editing memscan unit.... can take a while.



EDIT:

Patch:
https://github.com/mgrinzPlayer/cheat-engine/commit/ee33e74cfb93e96b615fcf51592d57663fab55a0
CustomTypeHandler, MemoryRecordUnit, byteinterpreter, memscan

Info:
Real address value passed to convert routines.

in ConvertRoutine routine, I appended realAddress just after "structure/chunk/RAWDataCopy"
depends on currently used ByteSize.

in ConvertBackRoutine routine, realAddress is inside [EBP+10] or R8


Code:
ByteSize:
dd 4

ConvertRoutine:
[64-bit]
// eax  = output (store result in EAX)
//[rcx] = address of input
//[rcx+ByteSize] = "realAddress" (the value is the real address from the game)


// bytesize is 4 (hexadecimal)
// struct starts at [RCX+0] and ends at [RCX+03]
// appended "realAddress" is at [RCX+04]

mov eax,[rcx]      // get value
xor eax,[rcx+4]    // xor with "realAddress"
ret
[/64-bit]



Example:
Code:
alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(UsesFloat,1)
alloc(UsesRealAddress,1)

TypeName:
db 'encrypted float (xor with address)',0

ByteSize:
dd 4

UsesFloat:
db 1

UsesRealAddress:
db 1

ConvertRoutine:
[64-bit]
// eax  = output (store result in EAX)
//[rcx] = address of input
//[rcx+ByteSize] = "realAddress" (the value is the real address from the game)
mov eax,[rcx]      // get value
xor eax,[rcx+4]    // xor with "realAddress"
ret
[/64-bit]

[32-bit]
// eax    = output (store result in EAX)
//[ebp+8] = address of input
//[[ebp+8]+ByteSize] = "realAddress" (the value is the real address from the game)
push ebp
mov ebp,esp
push ebx

mov ebx,[ebp+8] // get addres
mov eax,[ebx]   // get origbytes
xor eax,[ebx+4] // xor with "realAddress"

pop ebx
pop ebp
ret 4
[/32-bit]




ConvertBackRoutine:
[64-bit]
//ecx = input (value you want to write)
//rdx = address of output
//r8  = "realAddress"
xor ecx,r8        // xor rcx,r8
mov [rdx],ecx
ret
[/64-bit]

[32-bit]
//[ebp+8]  = input (value you want to write)
//[ebp+c]  = address of output
//[ebp+10] = "realAddress"
push ebp
mov ebp,esp
push eax
push ebx
mov eax,[ebp+8] //load the value into eax
mov ebx,[ebp+c] //load the address into ebx

xor eax,[ebp+10] //xor with "realAddress"

mov [ebx],eax    //write the value into the address
pop ebx
pop eax

pop ebp
ret 8
[/32-bit]




Download:
https://github.com/mgrinzPlayer/cheat-engine/releases/tag/CE6.4-15.05.01
https://github.com/mgrinzPlayer/cheat-engine/releases/download/CE6.4-15.05.01/customTypeMod.15.05.01.7z

How to:
1. make a copy of current CE6.4 folder, rename the copy to something meaningful, e.g. "CE64_mod"
2. download customTypeMod.15.05.01.7z, extract everything into "CE64_mod"
3. overwrite everything
4. CT files created with this new CE, better test them on original CE6.4 before posting them.


What I've tested so far:
- first scan
- next scan, value increased/decreased
- next scan, smaller/bigger than, between
- editing values via "memoryrecords"

_________________
Back to top
View user's profile Send private message MSN Messenger
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25836
Location: The netherlands

PostPosted: Fri May 01, 2015 7:14 pm    Post subject: This post has 1 review(s) Reply with quote

why not use r8=realaddress for convertroutine ?

(you forgot the all type loop)

And try not to put any extra IF statements inside "while (ptruint(p)<=lastmem) do" loops. See the first scan example for vtByteArrays and vtAll scan, instead of putting the if statement inside it, put it outside of it

_________________
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


Last edited by Dark Byte on Fri May 01, 2015 7:26 pm; edited 1 time in total
Back to top
View user's profile Send private message MSN Messenger
mgr.inz.Player
I post too much
Reputation: 222

Joined: 07 Nov 2008
Posts: 4438
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Fri May 01, 2015 7:26 pm    Post subject: Reply with quote

I wanted to save original "real address" for some checkroutines (compare to previous or saved).

I forgot to add a note:
Code:
Not available in "Value Type: All" scans.

_________________
Back to top
View user's profile Send private message MSN Messenger
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25836
Location: The netherlands

PostPosted: Fri May 01, 2015 7:30 pm    Post subject: Reply with quote

mgr.inz.Player wrote:
I wanted to save original "real address" for some checkroutines (compare to previous or saved).

I know, but people are going to complain about that (trust me)
Besides, if you're going to have a separate scanloop for custom types anyhow, you can just as well add a TCustomCheckRoutine where the address is passed as well (or use a private var in TScanner and use that to pass to the custom type)

_________________
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
View user's profile Send private message MSN Messenger
mgr.inz.Player
I post too much
Reputation: 222

Joined: 07 Nov 2008
Posts: 4438
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Fri May 01, 2015 8:01 pm    Post subject: Reply with quote

I agree.

For now, the changes I made are just for "proof of concept".

I know that scans for customtype with UsesRealAddress will take about 105% more of time (another copyMemory).
And scans for non-customtype will be slightly slower because of those extra IFs...

Quote:
you can just as well add a TCustomCheckRoutine

Quote:
instead of putting the if statement inside it, put it outside of it

If current customTypeMod.15.05.01 build works for somebody, I will add/commit those changes.


Another note:
setting a value with "foundlist - change value of selected addresses" doesn't work for now.








edit:
afk

_________________
Back to top
View user's profile Send private message MSN Messenger
Zanzer
I post too much
Reputation: 126

Joined: 09 Jun 2013
Posts: 3278

PostPosted: Fri May 01, 2015 9:06 pm    Post subject: Reply with quote

Throwing out some random ideas. No experience with Pascal or CE's source, so forgive me. Smile

1. Would it be a monumental change or cause a performance hit to pass the input by reference instead?
procedure TCustomType.ConvertToData(input: pointer; output: pointer); or
procedure TCustomType.ConvertToData(input: ptruint; output: pointer);
Or if useRealAddress is enabled, then to use this third, new conversion routine instead?
So as to not affect standard custom searches.
This way you are interacting directly with game memory.

2. In your current approach, to not affect other custom searches, you could:
Code:
if (variableType=vtCustom) and customType.scriptNeedsRealAddress then
begin
  while (ptruint(p)<=lastmem) do
  begin
    ...
  end
else
  while (ptruint(p)<=lastmem) do
  begin
    ...
  end
end


3. Again, not certain how each module fits together, but doesn't the 'p' variable already hold the address you are currently examining in the code [if checkroutine(p,nil)]? Not sure of the use of all that modifiedMEM code. (You don't need to explain it, I just wanted to make sure all of that logic was needed)
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25836
Location: The netherlands

PostPosted: Fri May 01, 2015 9:26 pm    Post subject: Reply with quote

1: cheat engine has no direct access to the game's memory. Only copies it inspects locally. So when ConvertToData(input, output) input and output are CE's addresses, not the game's
And sure, I could let the custom type do the ReadProcessMemory call,for every single address, but that would just be too slow

2: I did, but it just looks so cluttery

3: p holds the address of the current copy
CE allocates a block of up to 512KB (depending on the settings) copies a chunk of the game's memory into there
sets P to the start of the copy, and lastmem to the end of the copy
and then goes through the loop which will check every bytes or 4 bytes (fastscan) if the value matches what was being looked for
To calculate the actual address ce needs to get the base address of the copy, the original address and p, then add the difference of p and the copy to the actual address
Doing that for every address, including the ones that don't have a matching value, is a small amount of wasted cpu cycles, but for a 2GB game that would be :(2147483648-found results) * number of wasted cpu cycles

anyhow, I just implemented something of my own.
I added a new calling convention you can activate with
Code:

CallMethod:
db 1

this will give you the following functions to implement:
Code:

cdecl int ConvertRoutine(unsigned char *input, PTR_UINT address);
cdecl void ConvertBackRoutine(int i, PTR_UINT address, unsigned char *output);

_________________
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
View user's profile Send private message MSN Messenger
Zanzer
I post too much
Reputation: 126

Joined: 09 Jun 2013
Posts: 3278

PostPosted: Fri May 01, 2015 11:51 pm    Post subject: Reply with quote

1. checkroutine doesn't need to be sent currentAddress?
2. Should you be adding base again to AddressFound?
Code:
     vtCustom:
     begin
+      while (ptruint(p)<=lastmem) do
       begin
+        currentAddress:=base+ptruint(p)-ptruint(buffer);
+        if checkroutine(p,nil) then //found one   *** 1 ***
         begin
+          StoreResultRoutine(currentAddress,p);
+          if OnlyOne then
+          begin
+            AddressFound:=base+currentAddress; *** 2 ***
+            exit;
+          end;
         end;
+
+        inc(p,stepsize);
       end;
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25836
Location: The netherlands

PostPosted: Sat May 02, 2015 3:59 am    Post subject: Reply with quote

1: no, the TCheckRoitine methodcall does not need an address, else it would have to be applied to other types as well.
In this case the tscanner. currentaddress var is a type specific addition for vtCustom which the CheckRoutine implementation for custom scan uses to figure out the address

2: that is a bug yes (not a big one as it only takes effect in lua scripts that use the vtCustom type specifically in a custom memory scan, and use the only one result option, which is most of the time useless for integer types)

_________________
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
View user's profile Send private message MSN Messenger
mgr.inz.Player
I post too much
Reputation: 222

Joined: 07 Nov 2008
Posts: 4438
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Sat May 02, 2015 5:35 pm    Post subject: Reply with quote

OK. I deleted my realAddressForCustomType branch... There's no point in keeping it.







"ret" instead of "ret 4" in 32bit ConvertRoutine
ConvertBackRoutine also different: RDX==>R8, [ebp+c]==>[ebp+10], "ret 8"==>"ret"

Recent changes, CE is no longer backward compatible with my collection of CustomType scripts.



Also typo here:
Code:

      Add('//example:');
      Add('mov [r8],ecx //place the integer at the 4 bytes pointed to by rdx')

should be: "pointed to by r8"

_________________
Back to top
View user's profile Send private message MSN Messenger
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25836
Location: The netherlands

PostPosted: Sat May 02, 2015 6:17 pm    Post subject: Reply with quote

if you set CALLMETHOD to 0 (or don't define it at all) it should be fully compatible with the old custom types (and old custom types don't have that defined)
but yes, new scripts developed for 6.5 won't work for 6.4(unless made for 6.4 specifically), which isn't anything that new (same goes for lua, new lua functions won't work on 6.4)

_________________
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
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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