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 


Lua AOBScan() returns weird address

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
gibberishh
Cheater
Reputation: 1

Joined: 30 Aug 2021
Posts: 45

PostPosted: Sat Feb 26, 2022 2:36 am    Post subject: Lua AOBScan() returns weird address Reply with quote

I'm using lua's AOBScan() because I need the +X+W parameter to speed up my scans. I'm writing code for Joe Dever's Lonewolf, which generates code on the fly, so there is no chance of using AA's AOBScanModule().

Code:
local find = assert(AOBScan(pattern,"+W+X-C"), "")
local address = ""
if find ~= nil then address = find[0] end -- Also checked for find.Count > 0, which is always true in my case (see below)
find.destroy()
print(address) -- I go on to string.format("define()") etc.

Everything works correctly as long as the AOB is valid.

I want to try and gracefully handle situations when the AOB is not found (which happens often with on-the-fly code). However, find is never nil. If the AOB doesn't exist (CE search interface can't find it with options set to: Scan All, grey check -- i.e. * -- on Write, Exec, Copy), find[0] still returns some bizarre address. I also know for a fact that the AOB doesn't exist because I haven't performed the action that generates the code.

In Memory View, I can see that the address spat out by find[0] is completely random and has nothing to do with my search.

So:
1) Why is find returning an invalid address? -- This is not a rant, I truly wish to understand what is happening here. Is the +W+X-C forcing AOBScan() to just return the first writable executable piece of memory?
2) How can I gracefully capture errors and prompt the user to perform appropriate action before executing the rest of the code?

Thanks

_________________
It's not cheating. It's playing by my rules.
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 51

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Sat Feb 26, 2022 3:04 am    Post subject: Reply with quote

Lua assert just checks if something evaluates to true. So the way your using it, it really won't do anything. And the second parameter is for the error message and is optional so no need to pass an empty string to it.

The found list that AOBscan returns does have a 0 based index but count is 1 based. So you need to check if count is >= 1.

Here is an example of one I made to be used for making an AA command, basically in the end it works like the AA AOBscan in that it returns just one address or nil.

Code:

----
---- Scans for the given array of bytes and returns a address if found.
----
---- i2aobScan(signature)
---- i2aobScan(signature, index)
---- i2aobScan(signature, index, aobSignaturePrivileges)
----
---- Parameters:
----    signature : string :
----       The string of bytes to scan for.
----    index : number :
----       The index of the found list for the address.
----    aobSignaturePrivileges (optional): string : default : "*X*C*W"
----       The memory privileges to scan for.
----          "+W-C"   : Writable memory excluding copy on write and doesn't care about the
----                   Executable flag
----          "+X-C-W" : Find readonly executable memory
----          "+W"     : Finds all writable memory and don't care about copy on write or execute
---- Return:
----    number :
----       The address of the found array of bytes.
function i2aobScan(signature, index, aobSignaturePrivileges)
   if not signature then return end
   index = index or 1
   result = AOBScan(signature, aobSignaturePrivileges)
   if result == nil then
      return
   elseif result.Count >= 1 then
      local aobAddr = result[index - 1]
      result.destroy()
      return getAddressSafe(aobAddr)
   end
end
registerLuaFunctionHighlight('i2aobScan')

_________________
Back to top
View user's profile Send private message Visit poster's website
gibberishh
Cheater
Reputation: 1

Joined: 30 Aug 2021
Posts: 45

PostPosted: Sat Feb 26, 2022 4:41 am    Post subject: Reply with quote

TheyCallMeTim13 wrote:
The found list that AOBscan returns does have a 0 based index but count is 1 based. So you need to check if count is >= 1.

Here is an example of one I made (sic)


Thanks, this will be very useful. I can also use the nil return to return something that lets me handle the error, right? E.g.,
Code:
if result == nil then
      return false
...


Also, I'm not sure if you answered the first part of my question, or if I'm just slow in processing. Just trying to understand the code's behavior. Am I getting what looks to be a zombie address because I'm using assert()? Or is the AOBScan() responsible for the zombie address? -- And if it's the latter, why is that?

_________________
It's not cheating. It's playing by my rules.
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 51

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Sat Feb 26, 2022 5:14 am    Post subject: Reply with quote

That would have it returning false, but you'd also need to add a return false after the check so if you have 0 results it will still return false. But you can just check the return like normal and and it will work fine with a return of nil, since nil will evaluate to false. Here's an example of how I actually use it inside my AA command function.
Code:
--...
   local aobAddr = i2aobScan(signature, index, privileges)
   if aobAddr then
      return string.format('define(%s, %016X)', symbol, aobAddr)
   end
   return nil, 'AOB/signature not found.'
--...


Honestly not sure on the wrong address, might be that you're getting the handle for the results list. I'm actually surprised it didn't throw an index out of bounds error, I think that was how I figured out count was a one based index while the list is a zero based index. But that may have been for something else and it was after I knew it worked like that with stuff in CE that have a count property.

_________________
Back to top
View user's profile Send private message Visit poster's website
gibberishh
Cheater
Reputation: 1

Joined: 30 Aug 2021
Posts: 45

PostPosted: Sat Feb 26, 2022 7:24 am    Post subject: Reply with quote

TheyCallMeTim13 wrote:
So you need to check if count is >= 1.

Just two more questions:

1) Isn't
Code:
if result.Count > 0 then
the same as
Code:
if result.Count >=1 then

I assumed there would be a difference only if Count returned a floating point number. However, as we are dealing with integers, both code blocks should behave exactly alike, right? I'll use >=1, but I'd like to understand if this behavior is different in Lua from other (traditional) programming languages or if my understanding has been limited all along.

2. Ideally, shouldn't the code be checking for
Code:
if result.Count >= index

If the call is trying to retrieve the second found address, but the results list finds only one, then >=1 would result in an unhandled error, right?

Thanks

_________________
It's not cheating. It's playing by my rules.
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 51

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Sat Feb 26, 2022 8:07 am    Post subject: Reply with quote

Yes for both, I'm thinking I just hadn't changed the code after adding the index for when I needed it. And just hadn't had an error so it never got changed. But ideally yes you should probably make that change, then handle the error so you can have it show the error where it's called and not in the function. But thanks for pointing it out I'll make sure to update my code as well.

EDIT:
This was what I came up with so I could handle the error elsewhere.
Code:

----
---- Scans for the given array of bytes and returns a address if found.
----
---- i2aobScan(signature)
---- i2aobScan(signature, index)
---- i2aobScan(signature, index, aobSignaturePrivileges)
----
---- Parameters:
----    signature : string :
----       The string of bytes to scan for.
----    index : number :
----       The index of the found list for the address.
----    aobSignaturePrivileges (optional): string : default : "*X*C*W"
----       The memory privileges to scan for.
----          "+W-C"   : Writable memory excluding copy on write and doesn't care about the
----                   Executable flag
----          "+X-C-W" : Find readonly executable memory
----          "+W"     : Finds all writable memory and don't care about copy on write or execute
---- Return:
----    number :
----       The address of the found array of bytes.
function i2aobScan(signature, index, aobSignaturePrivileges)
   if not signature then return end
   index = index or 1
   result = AOBScan(signature, aobSignaturePrivileges)
   if result == nil then
      return nil, 'error with aobScan, return was nil'
   elseif result.Count >= index then
      local aobAddr = result[index - 1]
      result.destroy()
      return getAddressSafe(aobAddr)
   else
      local msg = string.format('Results found was less then the index given, count: %d, index: %d',
         result.Count, index)
      return nil, msg
   end
   return nil, 'unknown error'
end
registerLuaFunctionHighlight('i2aobScan')

_________________
Back to top
View user's profile Send private message Visit poster's website
gibberishh
Cheater
Reputation: 1

Joined: 30 Aug 2021
Posts: 45

PostPosted: Sat Feb 26, 2022 9:28 am    Post subject: Reply with quote

Okay, sorry for obsessing, but one more: why are you padding your address to 16 characters (8 bytes)? Of course, it's good practice, but why not maybe 4 bytes? (CE memory viewer shows 4-byte addresses.) And would the padding differ between 32-bit and 64-bit apps?

The last one doesn't apply to my current needs, but will be good to know.

_________________
It's not cheating. It's playing by my rules.
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 51

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Sat Feb 26, 2022 10:21 am    Post subject: Reply with quote

You could if you wanted to, just ues "targetIs64Bit()" to check if the process is 64 bit. But you'll never actually see that code anyway since its part of the AA command function, and that is what the AA command that's used in returns. So it's just defining a symbol as that number. But it really doesn't need to be padded at all. It was just what I chose to do at the time, and made the unittests easier to deal with else I'd also have to do the same kind of thing in them too.
_________________
Back to top
View user's profile Send private message Visit poster's website
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4717

PostPosted: Sat Feb 26, 2022 12:14 pm    Post subject: Reply with quote

Your first code has some problems, but none that would be the cause of your issue.
This is fine:
Code:
{$lua}
if syntaxcheck then return 'define(foo,0)' end

local result = assert(AOBScan(pattern,'+W+X-C'), 'AOBScan failed: no results found')
assert(result.Count == 1, 'AOBScan failed: multiple results found')

local address = getAddress(result[0])
result.destroy()

return ('define(foo,%08X)'):format(address)
{$asm}


gibberishh wrote:
1) Why is find returning an invalid address?

You're going to need to give more information. What is the pattern you're searching for? What are the addresses and values (real bytes) of the results that come up? Also provide information about the memory region(s) the results are in (memory viewer -> View -> Memory Regions)
gibberishh wrote:
2) How can I gracefully capture errors and prompt the user to perform appropriate action before executing the rest of the code?

Instead of directly using assert, maybe do something else like showing a message:
Code:
...
if result.Count ~= 1 then
  showMessage'More than one AOBScan result was found.'
  error('AOBScan failed: multiple results found')
end
...
You should still call error to abort enabling the script.
_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
gibberishh
Cheater
Reputation: 1

Joined: 30 Aug 2021
Posts: 45

PostPosted: Sat Feb 26, 2022 4:23 pm    Post subject: Reply with quote

ParkourPenguin wrote:
You're going to need to give more information.

Hey thanks! I got it all working correctly thanks to TheyCallMeTim, so it's no longer an issue. Got rid of my old code, so don't have the details now.
ParkourPenguin wrote:
Instead of directly using assert, maybe do something else like showing a message:

Yes, that was exactly what I did. showMessage() and error() within my new calling script and it works beautifully now.

_________________
It's not cheating. It's playing by my rules.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking 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