Difference between revisions of "Lua:AOBScanUnique"
Mr millchick (talk | contribs) (Created page with "Category:Lua '''function''' AOBScanUnique(''AOBString'', ''ProtectionFlags'' OPTIONAL, ''AlignmentType'' OPTIONAL, ''AlignmentParam'' HALFOPTIONAL) Scans the entire proce...") |
Mr millchick (talk | contribs) m (fixed formatting, added related links) |
||
Line 4: | Line 4: | ||
Scans the entire process memory for a byte pattern and returns the address if exactly one unique match is found. | Scans the entire process memory for a byte pattern and returns the address if exactly one unique match is found. | ||
− | '''Returns:''' The address as an integer if a unique match is found, or '''nil''' if no match or multiple matches are found. | + | * '''Returns:''' The address as an integer if a unique match is found, or '''nil''' if no match or multiple matches are found. |
− | + | * '''Note:''' Unlike [[Lua:AOBScan|AOBScan]], this function returns a single integer address (or nil) instead of a StringList, so there's no need to call destroy(). | |
− | '''Note:''' Unlike [[Lua:AOBScan|AOBScan]], this function returns a single integer address (or nil) instead of a StringList, so there's no need to call destroy(). | + | * '''Implementation:''' This function is equivalent to calling AOBScanModuleUnique("", AOBString, ...) with an empty module name. |
− | |||
− | '''Implementation:''' This function is equivalent to calling AOBScanModuleUnique("", AOBString, ...) with an empty module name. | ||
=== Function Parameters === | === Function Parameters === | ||
Line 171: | Line 169: | ||
|StringList or nil | |StringList or nil | ||
|All memory | |All memory | ||
− | |||
− | |||
− | |||
− | |||
− | |||
|No (returns all matches) | |No (returns all matches) | ||
|} | |} | ||
Line 203: | Line 196: | ||
− | + | {{LuaSeeAlso}} | |
+ | === Related Functions === | ||
+ | |||
+ | * [[Lua:AOBScan|AOBScan]] - Scan all memory and return all matches | ||
* [[Lua:AOBScanModuleUnique|AOBScanModuleUnique]] - Scan within a specific module (faster) | * [[Lua:AOBScanModuleUnique|AOBScanModuleUnique]] - Scan within a specific module (faster) | ||
− | + | ||
* [[Lua:registerSymbol|registerSymbol]] - Register found addresses as symbols | * [[Lua:registerSymbol|registerSymbol]] - Register found addresses as symbols | ||
* [[Lua:writeBytes|writeBytes]] - Write bytes to found addresses | * [[Lua:writeBytes|writeBytes]] - Write bytes to found addresses | ||
+ | |||
+ | * [[Lua:autoAssemble|autoAssemble]] | ||
+ | * [[Lua:disassemble|disassemble]] | ||
+ | * [[Lua:getInstructionSize|getInstructionSize]] | ||
+ | * [[Lua:getPreviousOpcode|getPreviousOpcode]] | ||
+ | * [[Lua:allocateSharedMemory|allocateSharedMemory]] | ||
+ | * [[Lua:mapMemory|mapMemory]] | ||
+ | * [[Lua:unmapMemory|unmapMemory]] | ||
+ | * [[Lua:readBytes|readBytes]] | ||
+ | * [[Lua:readPointer|readPointer]] | ||
+ | * [[Lua:writeBytes|writeBytes]] | ||
+ | * [[Lua:readBytesLocal|readBytesLocal]] | ||
+ | * [[Lua:readPointerLocal|readPointerLocal]] | ||
+ | * [[Lua:writeBytesLocal|writeBytesLocal]] | ||
+ | * [[Lua:wordToByteTable|wordToByteTable]] | ||
+ | * [[Lua:dwordToByteTable|dwordToByteTable]] | ||
+ | * [[Lua:qwordToByteTable|qwordToByteTable]] | ||
+ | * [[Lua:floatToByteTable|floatToByteTable]] | ||
+ | * [[Lua:doubleToByteTable|doubleToByteTable]] | ||
+ | * [[Lua:stringToByteTable|stringToByteTable]] | ||
+ | * [[Lua:wideStringToByteTable|wideStringToByteTable]] | ||
+ | * [[Lua:byteTableToWord|byteTableToWord]] | ||
+ | * [[Lua:byteTableToDword|byteTableToDword]] | ||
+ | * [[Lua:byteTableToQword|byteTableToQword]] | ||
+ | * [[Lua:byteTableToFloat|byteTableToFloat]] | ||
+ | * [[Lua:byteTableToDouble|byteTableToDouble]] | ||
+ | * [[Lua:byteTableToString|byteTableToString]] | ||
+ | * [[Lua:byteTableToWideString|byteTableToWideString]] |
Latest revision as of 04:21, 21 October 2025
function AOBScanUnique(AOBString, ProtectionFlags OPTIONAL, AlignmentType OPTIONAL, AlignmentParam HALFOPTIONAL)
Scans the entire process memory for a byte pattern and returns the address if exactly one unique match is found.
- Returns: The address as an integer if a unique match is found, or nil if no match or multiple matches are found.
- Note: Unlike AOBScan, this function returns a single integer address (or nil) instead of a StringList, so there's no need to call destroy().
- Implementation: This function is equivalent to calling AOBScanModuleUnique("", AOBString, ...) with an empty module name.
Contents
Function Parameters[edit]
Parameter | Type | Description |
---|---|---|
AOBString | string | A hex byte pattern with space/comma/dash separators. Use ?? or * for full-byte wildcards. Supports nibble wildcards like 7? or ?A |
ProtectionFlags | string | Optional. Memory protection filter. Default: "*X*W*C" (scan all memory regions) |
AlignmentType | integer | Optional. Alignment mode: 0=None, 1=Divisible, 2=Last digits. Default: 0 |
AlignmentParam | string | Optional. Hex value for alignment checking. Default: "1" |
Protection Flags[edit]
The ProtectionFlags parameter filters memory regions based on protection attributes:
Syntax: Prefix each flag with:
- + = Region MUST have this flag set
- - = Region MUST NOT have this flag set
- * = Don't care (default)
Flags:
- X = Executable
- W = Writable
- C = Copy On Write
- D = Dirty (macOS only)
Examples:
"+X" All executable memory (recommended for code patterns) "+W-C" Writable memory excluding copy-on-write "+X-W-C" Readonly executable memory (code sections) "" Uses default "*X*W*C" (scan all memory)
Alignment Parameters[edit]
AlignmentType values:
- 0 = fsmNotAligned - No alignment check (default)
- 1 = fsmAligned - Address must be divisible by AlignmentParam
- 2 = fsmLastDigits - Address must end with specific hex digits
AlignmentParam:
- Interpreted as a hexadecimal value
- For AlignmentType=1: Alignment boundary (e.g., "10" = 16-byte aligned, "4" = 4-byte aligned)
- For AlignmentType=2: Required ending hex digits (e.g., "00" = addresses ending in ...00)
Usage Examples[edit]
Basic unique scan:
local address = AOBScanUnique("48 8B 05 ?? ?? ?? 89") if address then print(string.format("Found at: %X", address)) -- Use address directly for reading/writing writeBytes(address, 0x90, 0x90, 0x90) else print("Pattern not found or not unique") end
Scan executable memory only (faster):
local address = AOBScanUnique("55 8B EC 83 EC", "+X") if address then print("Function found at: " .. address) end
With alignment checking:
local address = AOBScanUnique("FF 15 ?? ?? ?? ??", "+X", 1, "10") -- Only matches on 16-byte aligned addresses
Register the result as a symbol:
local addr = AOBScanUnique("48 89 5C 24 ?? 57", "+X") if addr then registerSymbol("MyFunction", addr) print("Registered MyFunction at " .. addr) end
Conditional execution based on pattern:
local patchAddr = AOBScanUnique("74 ?? 8B 45", "+X") if patchAddr then -- Apply patch only if pattern is unique writeBytes(patchAddr, 0xEB) -- Change JE to JMP print("Patched at: " .. patchAddr) else print("ERROR: Pattern not unique or not found!") return false end
Find and calculate relative offset:
local callAddr = AOBScanUnique("E8 ?? ?? ?? ??", "+X") if callAddr then local offset = readInteger(callAddr + 1) local target = callAddr + 5 + offset print(string.format("Call target: %X", target)) end
Return Value[edit]
- Success (unique match): Returns the address as an integer
- Failure: Returns nil in these cases:
- Pattern not found anywhere in memory
- Multiple matches found (not unique)
- Empty AOBString parameter
Performance Tips[edit]
- Use +X protection flag when scanning for code to dramatically reduce scan time
- For module-specific scans, use AOBScanModuleUnique instead (much faster)
- The scan stops after finding more than one match to ensure uniqueness
- More specific patterns (fewer wildcards) are faster and more likely to be unique
When to Use AOBScanUnique[edit]
Use AOBScanUnique when:
- You expect exactly one match in the entire process
- You want automatic validation that the pattern is unique
- You need a simple integer address for immediate use
- You're looking for a specific global function or unique code sequence
Use AOBScan when:
- You expect or want multiple matches
- You need to analyze all occurrences of a pattern
- The pattern might appear in multiple locations
Comparison with Related Functions[edit]
Function | Return Type | Scope | Uniqueness |
---|---|---|---|
AOBScanUnique | Integer or nil | All memory | Yes (returns nil if multiple matches) |
AOBScanModuleUnique | Integer or nil | Single module | Yes (returns nil if multiple matches) |
AOBScan | StringList or nil | All memory | No (returns all matches) |
Common Pitfalls[edit]
Pattern too generic:
-- This will likely fail because "90 90" appears many times local addr = AOBScanUnique("90 90") -- Returns nil (multiple matches)
Solution - Make pattern more specific:
local addr = AOBScanUnique("90 90 90 C3 48 89 5C") -- More unique context
Not checking for nil:
-- WRONG - will crash if pattern not found local addr = AOBScanUnique("48 8B") writeBytes(addr, 0x90) -- ERROR if addr is nil!
Solution - Always check return value:
local addr = AOBScanUnique("48 8B") if addr then writeBytes(addr, 0x90) else print("Pattern not found or not unique") end
See also[edit]
Related Functions[edit]
- AOBScan - Scan all memory and return all matches
- AOBScanModuleUnique - Scan within a specific module (faster)
- registerSymbol - Register found addresses as symbols
- writeBytes - Write bytes to found addresses
- autoAssemble
- disassemble
- getInstructionSize
- getPreviousOpcode
- allocateSharedMemory
- mapMemory
- unmapMemory
- readBytes
- readPointer
- writeBytes
- readBytesLocal
- readPointerLocal
- writeBytesLocal
- wordToByteTable
- dwordToByteTable
- qwordToByteTable
- floatToByteTable
- doubleToByteTable
- stringToByteTable
- wideStringToByteTable
- byteTableToWord
- byteTableToDword
- byteTableToQword
- byteTableToFloat
- byteTableToDouble
- byteTableToString
- byteTableToWideString