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 


Why is memscan returning 0 results?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
Rectangle
Advanced Cheater
Reputation: 1

Joined: 23 Feb 2013
Posts: 73

PostPosted: Wed Mar 20, 2013 4:52 pm    Post subject: Why is memscan returning 0 results? Reply with quote

This is for Candy Crush Saga (facebook app). The idea of this script it to find any 8-byte timer values, and narrow the results down to a specified number.
The problem, however, is that the initial memscan always seems to return 0 results when using the script, but works just fine when I use the GUI.
Of course, the problem with using the GUI for this is that there are often WAY too many results, and for timed levels within the game, you don't have enough time to manually narrow down those results before you lose the game.

Note that in order to use the script, you will need to attach to the FlashPlayerPlugin with the highest peak working set.
I have created a console application which finds the PID of the highest peak working set of any given process search token.
It can be found here (Sorry, I can't directly post URLs yet):
Source: 4shared[dot]com/zip/aezm77Dl/pws_src[dot]html
Binary: 4shared[dot]com/file/gKTZuTNH/pws[dot]html

If you don't wish to use the tool, you will need to open Windows Task Manager and check which of the current FlashPlayerPlugin processes has the highest peak working set (memory), look at it's PID, then manually open this process in the CE client.
Also, be sure to comment out the lines in the script (under the 'global variables' section) which use the PWS tool, and uncomment the line which gets the opened process ID.

Candy Crush Saga can be found at:
apps[dot]facebook[dot]com/candycrush

Here's the script:
Code:
--Asserts an object variable
function IS(obj)
  if(obj == nil) then
    print("[WARNING] - Null object!")
    return false
  else
    return true
  end
end

function table.pack(...)
  return { n = select("#", ...), ... }
end

--Exactly as it says: Disables the update timer, if valid
function disableUpdateTimer()
  if not t == nil then timer_setEnabled(t, false) end
end

--Exactly as it says: Enables the update timer, if valid
function enableUpdateTimer()
  if not t == nil then timer_setEnabled(t, true) end
end

--Exactly as it says: Destroys a timer and memscan object
function destroyTimerAndMemScan(timer, scan)
  if not timer == nil then timer_setEnabled(timer, false) end
  object_destroy(timer)
  object_destroy(scan)
  print("[INFO] - Timer and current memscan have been destroyed")
end

--Reverse 'for' statement with callback and optional args
function rfor(limit, block, ...)
  local args = table.pack(...)
  local index = limit
  if not (limit and block) then
    error("Invalid arguments!")
    return
  end
  disableUpdateTimer()
  while (index > 0) do
    block(index, limit, args)
    index = index - 1
  end
  enableUpdateTimer()
end

--Alternative 'for' statement with callback and optional args
function forr(limit, block, ...)
  local args = table.pack(...)
  local index = 0
  if not (limit and block) then
    error("Invalid arguments!")
    return
  end
  disableUpdateTimer()
  while (index <= limit) do
    block(index, limit, args)
    index = index + 1
  end
  enableUpdateTimer()
end

--Callback function which clears a single record
function clearEntry(index, limit, args)
  print("- Getting entry "..index.."/"..limit)
  local mr = addresslist_getMemoryRecord(args[1], index - 1)
  print("- Deleting entry "..index.."/"..limit)
  memoryrecord_delete(mr)
end

--Clears all records from the current address list
function clearAddressList()
  local al = getAddressList()
  local n = 0
  if IS(al) then
    n = addresslist_getCount(al)
    if n > 0 then
      print("[INFO] - Clearing address list...")
      if n == 1 then
        print("- "..n.." entry found")
      else
        print("- "..n.." entries found")
      end
      rfor(n, clearEntry, al)
    end
    return al
  end
  return nil
end

--Callback function which updates a single record
function updateRecord(index, limit, args)
  local saddress = foundlist_getAddress(args[1], index)
  local mr = addresslist_createMemoryRecord(args[2])
  memoryrecord_setDescription(mr, "Automated Scan "..args[3].."/"..args[4]..", entry "..index.."/"..limit)
  memoryrecord_setAddress(mr, saddress)
  memoryrecord_setType(mr, vtQword)
end

function updateRecordList()
  --first, clear any previous records
  local al = clearAddressList()
  if IS(al) then
    --update current records
    print("[INFO] - Updating address list...")
    print("- "..count.." total entries found")
    forr(count, updateRecord, found, al, updateIndex, maxUpdates)
    return true
  else
    print("- Failed to retrieve address list!")
    return false
  end
end

--Waits for current scan to complete, returns number of results and list of results
function finishScanAndGetResults(scan)
  print("[INFO] - Waiting for results...")
  memscan_waitTillDone(scan)
  print("[INFO] - Fetching results...")
  results = createFoundList(scan)
  foundlist_initialize(results)
  return foundlist_getCount(results), memscan_getAttachedFoundlist(scan)
end

--Returns a new memscan object, clearing any current scans
function getNewMemScan(oldScan)
  if not oldScan == nil then
    print("- Creating new memscan...")
    object_destroy(oldScan)
  else
    print("- Creating initial memscan...")
  end
  return createMemScan()
end

--Stops all updates, frees all objects, and lists the final results
function completeScan()
  updateRecordList()
  destroyTimerAndMemScan(t, ms)
  print("[INFO] - Search complete!")
end

--[[///////////////
-- global variables
--///////////////]]
updateIndex = 0
count = 0
maxUpdates = 20
minEntries = 10
maxEntries = 50
--[[
-- NOTE: If you wish to manually open the process, comment out the next four
--       lines, and then uncomment the fifth line (pid = getOpenedProcessID())
--]]
handle = io.popen("C:\\pws.exe FlashPlayerPlugin")
pid = tonumber(handle:read("*a"))
handle:close()
openProcess(pid)
--pid = getOpenedProcessID()
print("[INFO] - ProcessID: "..pid)
found = nil
ms = nil
t = nil

--clear any current entries
clearAddressList()

--main application code... finds all 8-byte values
pause()
print("[INFO] - Initial scan...")
ms = getNewMemScan(ms)
memscan_firstScan(ms, soUnknownValue, vtQword, rtTruncated, "", "", "0", "ffffffff", "", fsmNotAligened, "", false, false, false, false)
count, found = finishScanAndGetResults(ms)
if IS(found) then
  print("- Found "..count.." initial entries")
  --create an update timer to check for gradually decreasing 8-byte values
  t = createTimer(nil, false)
  timer_setInterval(t, 3000) -- 1.5 seconds
  timer_onTimer(t, update)
  timer_setEnabled(t, true)
else
  error("Failed to retrieve initial entries!")
end
unpause()

--Searches for any decreased values and updates the address list
function update()
  pause()

  --only allow a maximum # of updates, for debugging purposes
  updateIndex = updateIndex + 1
  if updateIndex > maxUpdates then
    destroyTimerAndMemScan(t, ms)
    unpause()
    return
  end

  --scan for any changes
  print("[INFO] - Updating...");
  memscan_nextScan(ms, soDecreasedValue, rtTruncated, "", "", false, false, false, false, false, '')
  count = finishScanAndGetResults(ms, found)
  if IS(found) then
    print("- Found "..count.." new entries")
    --add any found entries to the address list
    if count > 0 then
      if count <= maxEntries then
        if count >= minEntries then
          --update address list
          if updateRecordList() == false then
            print("- Failed to update address list!")
          end
        else
          --update final list
          completeScan()
        end
      end
    else
      destroyTimerAndMemScan(t, ms)
    end
  else
    print("- Failed to retrieve new entries!")
  end

  unpause()
end
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Wed Mar 20, 2013 5:56 pm    Post subject: Reply with quote

your initial scan is an "soUnknownValue"
That scan never returns any addresses. It MUST have a next scan to scan through the list
CE's gui only shows an estimated number of results based on the value type and total memory

_________________
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
Rectangle
Advanced Cheater
Reputation: 1

Joined: 23 Feb 2013
Posts: 73

PostPosted: Thu Mar 21, 2013 12:19 am    Post subject: Reply with quote

Okay... but the update timer should still get called for the 2nd scan, which for some reason, it doesn't.
Also... I noticed that executing the script twice and waiting a few seconds does in fact make the script work as expected, with the exception that the returned addresses are all 00000000 (see image link below):


Bit .ly/11ixKIi

I've been poking around and can't figure out why this happens.
My only guess was some sort of string/integer conflict somewhere, but shouldn't I get an error in the output window if this was the case?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Thu Mar 21, 2013 5:04 am    Post subject: Reply with quote

I don't have a facebook account so can't really try it.

Anyhow, in your main application code ,at the time timer_onTimer(t, update) gets executed ,update has not been defined yet (it's defined after the main function, at this point it is still nil). That explains why the second run does work as update has previously been defined

Not sure why address is 00000000, this usually happens if the foundlist is accessed after the scan is almost done but not all results have been written to disk. But then it still only shows 00000000 after the first few thousands of addresses. So no idea

_________________
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
DaSpamer
Grandmaster Cheater Supreme
Reputation: 52

Joined: 13 Sep 2011
Posts: 1578

PostPosted: Thu Mar 21, 2013 11:20 am    Post subject: Reply with quote

Few things,
You don't need to use that script to attach to the right processor Smile.
Its always the 2nd processor of both.

About the timer,
Can you tell me what timer you're talking about?

_________________
HEY Hitler
Do you get lazy when making trainers?
Well no more!
My CETrainer will generate it for you in seconds, so you won't get lazy! Very Happy

http://forum.cheatengine.org/viewtopic.php?t=564919
Back to top
View user's profile Send private message
Rectangle
Advanced Cheater
Reputation: 1

Joined: 23 Feb 2013
Posts: 73

PostPosted: Thu Mar 21, 2013 9:00 pm    Post subject: Reply with quote

Dark Byte wrote:
in your main application code ,at the time timer_onTimer(t, update) gets executed ,update has not been defined yet (it's defined after the main function, at this point it is still nil). That explains why the second run does work as update has previously been defined

Ah yes, thanks for pointing that out! It's times like these I wish lua supported forward declarations =P
Now if only I could figure out why the addresses are all zero'd out...

Flashacking wrote:
Few things,
You don't need to use that script to attach to the right processor Smile.
Its always the 2nd processor of both.

I think you mean process, in which case no. It is not always the 2nd one. I'd have a better shot at comparing both pids to see which one has a lower hex value, but even that is no guarantee...
The only truly certain way of knowing the correct FlashPlayerPlugin to attach to is to find the one with the highest peak working set.
And the only time where this is a gamble is in the rare scenario where you have 4 or more processes instead of just 2.
Trust me, I've spent weeks testing this alone, using a mixture of various flash versions/apps/browsers.

Flashacking wrote:
About the timer,
Can you tell me what timer you're talking about?

It's in the script, and is bound to the update() function (the last function in the script)
Back to top
View user's profile Send private message
DaSpamer
Grandmaster Cheater Supreme
Reputation: 52

Joined: 13 Sep 2011
Posts: 1578

PostPosted: Thu Mar 21, 2013 11:37 pm    Post subject: Reply with quote

Quote:
This is for Candy Crush Saga (facebook app). The idea of this script it to find any 8-byte timer values, and narrow the results down to a specified number.
The problem, however, is that the initial memscan always seems to return 0 results when using the script, but works just fine when I use the GUI.
Of course, the problem with using the GUI for this is that there are often WAY too many results, and for timed levels within the game, you don't have enough time to manually narrow down those results before you lose the game.

I have never seen not a single timer yet Surprised.
1 Question,
Why make it so hard when you can use auto assembler?
Find the timers addresses > check what accesses them (much easier*).
Inject the functions that are being called (doesn't matter which).
Or tell me which stage I'll make it for you.

_________________
HEY Hitler
Do you get lazy when making trainers?
Well no more!
My CETrainer will generate it for you in seconds, so you won't get lazy! Very Happy

http://forum.cheatengine.org/viewtopic.php?t=564919
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Fri Mar 22, 2013 9:57 am    Post subject: Reply with quote

The function finishScanAndGetResults creates a new foundlist (global named results and as a secondary result)

Your update() function does not get the foundlist object. The second parameter you pass to finishScanAndGetResults is ignored. If you want the second result you'd have to
Code:

count, found = finishScanAndGetResults(ms)

_________________
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
Rectangle
Advanced Cheater
Reputation: 1

Joined: 23 Feb 2013
Posts: 73

PostPosted: Tue Mar 26, 2013 3:44 am    Post subject: Reply with quote

Mother of hack wrote:
Why make it so hard when you can use auto assembler?

Because most of the byte patterns in the flash process don't seem very stable. There are a ton of wildcards, which results in numerous matches. I'm really not sure why this occurs, but it might have something to do with the way ActionScript is handled.
I wrote a few AA scripts to handle other things (such as # of moves left, and the ability to freeze the timer on bombs which start after level 100)...
But the byte patterns change too drastically after only a few levels, rendering the code useless and often crashing the flash plugin (which often results in losing a life in-game).

So there's that, plus the issue that I first need to FIND the correct address(es) in order to open the disassembler to the proper writing location to figure out what those byte patterns are in the first place.
You see the problem here? You've basically asked me why don't I just skip this nonsense and move on to... well, this nonsense. Just a tad bit illogical.
Or perhaps you missed the part where I mentioned the purpose of the script?
Back to top
View user's profile Send private message
AylinCE
Grandmaster Cheater Supreme
Reputation: 32

Joined: 16 Feb 2017
Posts: 1253

PostPosted: Wed Jul 17, 2019 4:44 pm    Post subject: Reply with quote

Rectangle wrote:
Mother of hack wrote:
Why make it so hard when you can use auto assembler?

Because most of the byte patterns in the flash process ...


Laughing Laughing Laughing Laughing Laughing

I'm sorry, but how is this title a quote?
He wrote this on purpose?
I caught my attention while doing research
Who did he quote from? Very Happy Very Happy Very Happy

_________________
Hi Hitler Different Trainer forms for you!
https://forum.cheatengine.org/viewtopic.php?t=619279
Enthusiastic people: Always one step ahead
Do not underestimate me Master: You were a beginner in the past
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting 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