-
Notifications
You must be signed in to change notification settings - Fork 186
Scanning
The scan panel is where you find normal values in memory. Health, ammo, money, timers, coordinates, item counts, that sort of thing.
The usual idea is simple:
- Search for a value
- Change that value in the game
- Search again using the new value or how it changed
- Repeat until only a few results are left
- Add the good looking ones to the address table and test them
Most failed scans are not because the scanner is broken. It is usually the wrong value type, the game showing a rounded value, the value being stored somewhere weird or the scan scope being too small.
Start with something visible if you are new to this. Ammo is better than health because you can usually change it by exactly 1 whenever you want.
Example with ammo:
- Attach to the game
- Set
Value TypetoInt32 - Set
Scan TypetoExact - Enter the current ammo value, for example
30 - Click
First Scan - Spend one bullet in the game
- Enter the new value, for example
29 - Click
Next Scan - Repeat until the result count is small
- Double click likely addresses to add them to the address table
- Change or freeze them and see which one actually affects the game
After the first scan, First Scan becomes New Scan. Clicking New Scan throws away the current scan and starts over.
Pressing Enter in the value field runs the next sensible scan. Before the first scan it starts a first scan, after that it runs Next Scan. Ctrl+Enter starts a new scan.
First Scan creates the first result list. It searches the selected memory regions and stores every address that matches.
Next Scan filters that existing result list. It does not search the whole process from scratch, it checks the previous matches and keeps only the ones that still fit.
That is why the first scan can return millions of results but later scans get much faster.
Undo Scan goes back one scan step. Useful when you picked the wrong next scan type or changed the game value in a bad way.
Cancel Scan asks the scanner to stop the current scan. This is mainly useful for huge first scans, Full scans or bad ByteArray searches.
Value Type decides how PINCE reads the bytes it finds.
For most normal game values:
- Start with
Int32for whole numbers like ammo, money, levels, item counts and health shown as100 - Try
Float32for coordinates, speed, timers, bars, percentages and values that feel smooth - Try
Int16orInt8for small old games, emulators, flags and compact structs - Try
Int64for very large counters or games that store everything as 64-bit values - Use
Int(any)if you know it is an integer but not the size - Use
Float(any)if you know it is a float but not whether it is 32-bit or 64-bit - Use
Any(int, float)if you really have no idea, but expect more results - Use
Stringfor text - Use
ByteArrayfor raw byte patterns, usually code or known binary data
The default Int32 is a good first guess. Do not jump straight to Any(int, float) unless you need it. It can find more stuff but that also means more junk to filter.
After the first scan, Value Type is locked until New Scan. Changing the type would make the old result list meaningless, so PINCE resets the scan when you do it before starting.
Scan Type decides how PINCE compares memory against your input or against the previous scan.
For first scans:
-
Exactfinds values equal to what you typed -
Notfinds values that are not equal to what you typed -
Less Thanfinds values below your input -
More Thanfinds values above your input -
Betweenuses both value fields as a range -
Unknown Valuetakes a snapshot without needing a value
For next scans:
-
Exactkeeps values that now equal what you typed -
Notkeeps values that now do not equal what you typed -
Increasedkeeps values that went up since the previous scan -
Increased bykeeps values that went up by the amount you typed -
Decreasedkeeps values that went down since the previous scan -
Decreased bykeeps values that went down by the amount you typed -
Less Thankeeps values below your input -
More Thankeeps values above your input -
Betweenkeeps values inside the range -
Changedkeeps anything that changed -
Unchangedkeeps anything that stayed the same
For String and ByteArray, next scans only support Exact. First scans support Exact and Unknown Value.
Use Unknown Value when the game does not show the number. For example hidden stamina, suspicion meters, internal timers or a charge value behind a bar.
The first Unknown Value scan does not need an input. PINCE takes a snapshot of matching memory and waits for you to narrow it down.
A typical hidden value scan looks like this:
- Start with
Unknown Value - Make the value go up in the game
- Use
Increased - Make the value go down
- Use
Decreased - Wait without changing it
- Use
Unchanged - Repeat until the result list is manageable
Changed is useful when you know something happened but not the direction. Unchanged is useful to throw away noisy values while you keep the game state stable.
Games do not always store the number exactly as it appears on screen.
Some common cases:
- The UI says
100but memory stores99,100.0,0.75,7500or a pointer to an object that contains the real value - The UI rounds a float, so
12.5on screen might be12.483921in memory - Health bars often store a float ratio like
0.0to1.0 - Money might be split into multiple values, cached for display or checked by server code
- Some games encrypt or obfuscate important values
If Exact does not work, try Unknown Value with Increased and Decreased. If an integer scan fails for a bar or physics value, try Float32.
Scan Scope controls which memory regions are searched.
The options are:
-
Basic: heap, stack and executable memory. Fastest, but can miss values -
Normal: heap, stack, executable memory andBSS. This is the default and usually the best starting point -
Read+Write: all readable and writable memory regions. Slower, but catches more normal variables -
Full: all readable memory regions, including read-only mappings. Slowest and usually overkill for normal values
Start with Normal. If the value is not found, try Read+Write. Full is mostly useful when you know what you are doing, for example some ByteArray searches.
Changing Scan Scope resets the scan. After the first scan it is locked until New Scan.
Manage Scan Regions shows the regions that will be scanned. Checked regions are removed from the current scan.
This is useful when you want to:
- Skip huge mapped files
- Ignore regions that clearly cannot contain the value
- Focus on a specific module or memory area
- Make a slow scan less painful
The dialog shows things like region id, start address, size, type, load address, permissions and file path. Invert Selection flips what is selected.
If you remove regions, PINCE remembers that for the current scan. Starting a fresh scan with New Scan is usually the cleanest way to get back to normal.
Endianness controls byte order for multi-byte values.
The options are:
-
Host: use your system byte order. On normal x86/x64 Linux this is little endian -
Little: force little endian -
Big: force big endian
Use Host unless you have a reason not to. Big is mostly for emulators, file-like data, network-style data or targets that store values in big endian.
Changing Endianness resets the scan before you start. After the first scan it is locked until New Scan.
Alignment filters which addresses are checked.
The options are Auto, 1, 2, 4, 8 and 16.
Normal values are often aligned. A 4 bytes integer is often at an address divisible by 4, an 8 bytes value is often at an address divisible by 8. Alignment makes scans faster and cuts down junk results.
Auto is the normal choice. Use 1 if you suspect the value is packed into an odd address or if you are searching bytes.
Changing Alignment resets the scan before you start. After the first scan it is locked until New Scan.
Hex changes integer input from decimal to hexadecimal.
With Hex checked, FF and 0xFF both mean 255. Negative hex works too, for example -10 means -0x10 when hex mode is on.
Hex is only available for integer value types. It is mostly useful when you are working from disassembly, offsets, flags or raw memory values.
ByteArray searches bytes instead of typed numbers.
Input is written as two hex characters per byte:
48 8B 05 11 22 33 44
You can use ?? as a wildcard:
48 8B ?? ?? ?? 89
This is useful for AOB-style searches where part of the pattern changes between launches. For code patterns, the Memory Viewer and Libpince Engine are usually the next step after you find the bytes.
After a scan, results appear with:
-
Address: where the value was found -
Value: current value at that address -
Previous: value from the previous scan
PINCE may find more matches than it displays. The table shows up to 1000 rows, while the match count label still tells you the real count. Keep scanning until the count is small enough to test properly.
Double click a result to add it to the address table.
Right click results for common actions:
-
Copy Address: copy the selected address or addresses -
Browse this memory region: open the Memory Viewer hex view around that address -
Disassemble this address: open the Memory Viewer disassembly around that address -
Delete selection: remove selected results from the scan list
Green addresses are static according to PINCE. Static addresses are often nicer than heap addresses, but they can still be display copies or temporary values, so always test them.
Finding an address is not the end. You still need to check if it is the real one.
Good tests:
- Change the value in the address table and see if the game changes
- Freeze it and see if the game stops changing it
- Let the game change it again and see if the address table updates
- Restart the level or reload the save and see if it still makes sense
Bad signs:
- The value changes in PINCE but not in the game
- The game changes once then snaps back
- The address stops updating after a menu, loading screen or death
- Freezing it breaks unrelated things
If an address works only until restart, read the Pointers page next. If you need to find the code changing it, use Search Opcodes & Watchpoints from the address table.
Try these before assuming the value cannot be found:
- Switch between
Int32andFloat32 - Use
Unknown Valueinstead ofExact - Use
IncreasedandDecreasedinstead of typing the exact displayed number - Change
Scan ScopefromNormaltoRead+Write - Set
Alignmentto1if the value might be packed - Check if the game is online or server authoritative
- Pause the game or keep the value stable while scanning
- Scan for a nearby value, like current ammo instead of max ammo
Sometimes the value you want is not the value you should edit. For example, editing health might do nothing because the game recalculates it from stats. In those cases, finding what writes to the value is usually more useful than fighting the scan forever.