It is easy for them to do it (and for Cheat Engine, if he wanted) because they only use the two standard storage methods.
The first method if just a list of DWORD-sized addresses, each followed by the actual data at the time of the search.
So a series of results for a byte search might be:
- Code: Select all
XXXXYXXXXYXXXXY
Where the X’s are the bytes for the address (4 bytes) and the Y is the actual byte value.
A search for a DWORD would look like this:
- Code: Select all
XXXXYYYYXXXXYYYYXXXXYYYY
You can see how this quickly consumes space, as for every result found you store 4 extra bytes for the address of that result.
That is method #1.
Method #2 is used for Unknown searches, and it simply has a small header followed by the actual chunk of data.
For each large chunk of contiguous data, you would have:
- Code: Select all
XXXXSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY…
X’s are the bytes for the address of the start of the list.
S’s are the bytes for the size of the list.
Y’s are the bytes in the entire buffer of data.
Because every other memory searcher uses only these two methods, it is easy for them to remove entries from their lists.
To remove from method #1, you simply use memmove() to move the data above the address you removed down, overwriting the address you removed. It works because it is linear. Just move the data from the top down X bytes and then the address you wanted to remove is gone from the list.
To remove from method #2 you split the large chunk into two smaller chunks (each with its own XXXXSSSS header), and adjust the headers to exclude the address you removed (also adjust the YYYYY data).
However Memory Hacking Software uses a new method, which uses compression to save the same number of returns in a much smaller space (sometimes 50% less RAM/disk usage).
The entire list is compressed in such a way that the addresses are not stored, but derived, which means adjusting anything will change how the addresses are derived for the rest of the entire list, which in turn means the entire list of addresses must be completely refactored.
This is made all that much more difficult since parts of the list may or may not be stored to disk.
L. Spiro