|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Rectangle Advanced Cheater Reputation: 1
Joined: 23 Feb 2013 Posts: 73
|
Posted: Wed Mar 20, 2013 4:52 pm Post subject: Why is memscan returning 0 results? |
|
|
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 |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25288 Location: The netherlands
|
Posted: Wed Mar 20, 2013 5:56 pm Post subject: |
|
|
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 |
|
|
Rectangle Advanced Cheater Reputation: 1
Joined: 23 Feb 2013 Posts: 73
|
Posted: Thu Mar 21, 2013 12:19 am Post subject: |
|
|
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 |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25288 Location: The netherlands
|
Posted: Thu Mar 21, 2013 5:04 am Post subject: |
|
|
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 |
|
|
DaSpamer Grandmaster Cheater Supreme Reputation: 52
Joined: 13 Sep 2011 Posts: 1578
|
Posted: Thu Mar 21, 2013 11:20 am Post subject: |
|
|
Few things,
You don't need to use that script to attach to the right processor .
Its always the 2nd processor of both.
About the timer,
Can you tell me what timer you're talking about?
_________________
|
|
Back to top |
|
|
Rectangle Advanced Cheater Reputation: 1
Joined: 23 Feb 2013 Posts: 73
|
Posted: Thu Mar 21, 2013 9:00 pm Post subject: |
|
|
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 .
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 |
|
|
DaSpamer Grandmaster Cheater Supreme Reputation: 52
Joined: 13 Sep 2011 Posts: 1578
|
Posted: Thu Mar 21, 2013 11:37 pm Post subject: |
|
|
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 .
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.
_________________
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25288 Location: The netherlands
|
Posted: Fri Mar 22, 2013 9:57 am Post subject: |
|
|
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 |
|
|
Rectangle Advanced Cheater Reputation: 1
Joined: 23 Feb 2013 Posts: 73
|
Posted: Tue Mar 26, 2013 3:44 am Post subject: |
|
|
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 |
|
|
AylinCE Grandmaster Cheater Supreme Reputation: 32
Joined: 16 Feb 2017 Posts: 1253
|
Posted: Wed Jul 17, 2019 4:44 pm Post subject: |
|
|
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 ... |
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?
_________________
|
|
Back to top |
|
|
|
|
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
|
|