Difference between revisions of "Lua:AOBScan"
| m | Mr millchick (talk | contribs)   (Added more in depth details for parameters, wildcards, example usage, performance, and returns. Also added related function refrences.) | ||
| Line 4: | Line 4: | ||
| '''function''' AOBScan(''AOBString'', ''ProtectionFlags'' OPTIONAL, ''AlignmentType'' OPTIONAL, ''AlignmentParam'' HALFOPTIONAL) | '''function''' AOBScan(''AOBString'', ''ProtectionFlags'' OPTIONAL, ''AlignmentType'' OPTIONAL, ''AlignmentParam'' HALFOPTIONAL) | ||
| − | Scans the currently opened process and returns a [[Lua:Class:Stringlist|StringList]] object containing all the  | + | Scans the currently opened process memory for a byte pattern (Array of Bytes) and returns a [[Lua:Class:Stringlist|StringList]] object containing all matching addresses as hexadecimal strings. | 
| − | + | ||
| − | + | '''Returns:''' A [[Lua:Class:Stringlist|StringList]] containing the addresses found, or '''nil''' if no matches are found. | |
| + | |||
| + | '''Important:''' Always call '''list.destroy()''' when done to free memory and prevent leaks. | ||
| + | |||
| + | === Two Calling Modes === | ||
| + | |||
| + | '''Mode 1: Pattern String''' - Provide an AOB pattern as a hex string with optional wildcards | ||
| + |  AOBScan(AOBString, ProtectionFlags, AlignmentType, AlignmentParam) | ||
| + | |||
| + | '''Mode 2: Varargs Bytes''' - Pass individual byte values as separate arguments | ||
| + |  AOBScan(byte1, byte2, byte3, ...) | ||
| + | |||
| + | In varargs mode: | ||
| + | * Values 0-255 are treated as literal bytes | ||
| + | * '''nil''', non-numeric values, or values > 255 become wildcards | ||
| + | * Zero (0) is written as "00" if it's a number, or as a wildcard if nil/non-numeric | ||
| === Function Parameters === | === Function Parameters === | ||
| − | + | ==== Mode 1: Pattern String ==== | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| {|width="85%" cellpadding="10%" cellpadding="5%" cellspacing="0" border="0" | {|width="85%" cellpadding="10%" cellpadding="5%" cellspacing="0" border="0" | ||
| Line 29: | Line 35: | ||
| |AOBString | |AOBString | ||
| |string | |string | ||
| − | |A  | + | |A hex byte pattern with space/comma/dash separators. Use '''??''' or '''*''' for full-byte wildcards. Supports nibble wildcards like '''7?''' or '''?A''' | 
| |- | |- | ||
| |ProtectionFlags | |ProtectionFlags | ||
| |string | |string | ||
| − | | | + | |'''Optional.''' Memory protection filter (see below). Default: "" (scan all memory) | 
| |- | |- | ||
| |AlignmentType | |AlignmentType | ||
| |integer | |integer | ||
| − | | | + | |'''Optional.''' Alignment mode: 0=None, 1=Divisible, 2=Last digits. Default: 0 | 
| |- | |- | ||
| |AlignmentParam | |AlignmentParam | ||
| |string | |string | ||
| − | | | + | |'''Optional.''' Hex value for alignment checking. Default: "1" | 
| |} | |} | ||
| + | |||
| + | ==== Mode 2: Varargs Bytes ==== | ||
| + | |||
| + | {|width="85%" cellpadding="10%" cellpadding="5%" cellspacing="0" border="0" | ||
| + | !align="left"|Parameter | ||
| + | !align="left"|Type | ||
| + | !style="width: 80%;" align="left"|Description | ||
| + | |- | ||
| + | |... | ||
| + | |'''varargs''' | ||
| + | |Individual byte values (0-255). Use '''nil''' or values > 255 for wildcards | ||
| + | |} | ||
| + | |||
| + | |||
| + | === Protection Flags === | ||
| + | |||
| + | The '''''ProtectionFlags''''' parameter is a string that filters which memory regions to scan based on their 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:''' | ||
| + |   "+W-C"     Writable memory excluding copy-on-write (don't care about executable) | ||
| + |   "+X-W-C"   Readonly executable memory (code sections) | ||
| + |   "+X"       All executable memory (typical for code scanning) | ||
| + |   "-W"       Non-writable memory only | ||
| + |   ""         Scan everything (equivalent to "*X*W*C") | ||
| + |   "*X*W*C"   Explicitly scan everything (don't care about any flags) | ||
| + | |||
| + | |||
| + | === Alignment Parameters === | ||
| + | |||
| + | Use '''''AlignmentType''''' and '''''AlignmentParam''''' to constrain addresses and improve scan performance: | ||
| + | |||
| + | '''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, "F0" = ending in ...F0) | ||
| + | |||
| + | '''Examples:''' | ||
| + |   AlignmentType=1, AlignmentParam="10"   Only 16-byte aligned addresses (0x...0, 0x...10, 0x...20, etc.) | ||
| + |   AlignmentType=1, AlignmentParam="4"    Only 4-byte aligned addresses | ||
| + |   AlignmentType=2, AlignmentParam="00"   Only addresses ending with 00 (0x...00) | ||
| + |   AlignmentType=2, AlignmentParam="F0"   Only addresses ending with F0 (0x...F0) | ||
| + | |||
| + | |||
| + | === Wildcard Syntax === | ||
| + | |||
| + | '''Full-byte wildcards:''' Match any byte value | ||
| + | * '''??''' - Most common notation | ||
| + | * '''*''' - Alternative notation | ||
| + | * Any non-hex characters in a byte position | ||
| + | |||
| + | '''Nibble wildcards:''' Match specific half-byte (4 bits) | ||
| + | * '''7?''' - High nibble is 7, low nibble can be anything (matches 70-7F) | ||
| + | * '''?A''' - High nibble can be anything, low nibble is A (matches 0A, 1A, 2A, ..., FA) | ||
| + | |||
| + | '''Examples:''' | ||
| + |   "48 8B ?? ?? ?? 89"        Full wildcards for bytes 3-5 | ||
| + |   "DE AD ?? EF"              Wildcard for byte 3 | ||
| + |   "7? A? ?3"                 Nibble wildcards: 7x, Ax, x3 | ||
| + | |||
| + | |||
| + | === Usage Examples === | ||
| + | |||
| + | '''Basic scan - find all matches:''' | ||
| + |  local results = AOBScan("48 8B 05 ?? ?? ?? 89") | ||
| + |  if results then | ||
| + |    print("Found " .. results.Count .. " matches") | ||
| + |    for i = 0, results.Count - 1 do | ||
| + |      print(string.format("%X", results[i])) | ||
| + |    end | ||
| + |    results.destroy() | ||
| + |  else | ||
| + |    print("Pattern not found") | ||
| + |  end | ||
| + | |||
| + | '''Scan executable memory only (faster for code patterns):''' | ||
| + |  local results = AOBScan("55 8B EC", "+X") | ||
| + |  if results then | ||
| + |    print("First match: " .. results[0]) | ||
| + |    results.destroy() | ||
| + |  end | ||
| + | |||
| + | '''Scan with alignment (16-byte aligned addresses):''' | ||
| + |  local results = AOBScan("FF 15 ?? ?? ?? ??", "+X", 1, "10") | ||
| + |  if results then | ||
| + |    results.destroy() | ||
| + |  end | ||
| + | |||
| + | '''Scan for addresses ending in 00:''' | ||
| + |  local results = AOBScan("DE AD BE EF", "", 2, "00") | ||
| + |  if results then | ||
| + |    results.destroy() | ||
| + |  end | ||
| + | |||
| + | '''Varargs mode with wildcards:''' | ||
| + |  local results = AOBScan(0x48, 0x8B, nil, nil, nil, 0x89)  -- nil = wildcard | ||
| + |  if results then | ||
| + |    results.destroy() | ||
| + |  end | ||
| + | |||
| + | '''Helper function to get first match:''' | ||
| + |  function findAOB(pattern, flags) | ||
| + |    local results = AOBScan(pattern, flags or "+X") | ||
| + |    if results and results.Count > 0 then | ||
| + |      local addr = results[0] | ||
| + |      results.destroy() | ||
| + |      return addr | ||
| + |    end | ||
| + |    return nil | ||
| + |  end | ||
| + | |||
| + |  local address = findAOB("48 8B ?? ?? ?? 89") | ||
| + |  if address then | ||
| + |    print("Found at: " .. address) | ||
| + |  end | ||
| + | |||
| + | |||
| + | === Performance Tips === | ||
| + | |||
| + | * Use '''+X''' protection flag when scanning for code to dramatically reduce scan time | ||
| + | * Use alignment when you know the address characteristics (e.g., function pointers are often aligned) | ||
| + | * Keep patterns as specific as possible - avoid excessive wildcards | ||
| + | * For single-result scans, consider using '''AOBScanUnique''' or module-specific variants | ||
| + | * Always destroy the StringList after use to prevent memory leaks | ||
| − | + | === Return Value === | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| + | * '''Success:''' Returns a [[Lua:Class:Stringlist|StringList]] object containing hex address strings | ||
| + | * '''Failure:''' Returns '''nil''' (no matches found or invalid pattern) | ||
| − | + | '''Note:''' The returned addresses are strings in hexadecimal format (e.g., "7FF12340"). Convert with tonumber(addr, 16) if you need numeric values. | |
| − | |||
| − | |||
| − | |||
| − | + | === See Also === | |
| − | + | * [[Lua:AOBScanUnique|AOBScanUnique]] - Returns a single address or nil (no cleanup needed) | |
| − | + | * [[Lua:AOBScanModule|AOBScanModule]] - Scan within a specific module | |
| − | + | * [[Lua:AOBScanModuleUnique|AOBScanModuleUnique]] - Find unique pattern in a module | |
| − | + | * [[Lua:Class:Stringlist|StringList]] - String list object documentation | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | * [[Lua: | ||
| − | * [[Lua: | ||
| − | * [[Lua: | ||
| − | * [[Lua: | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
Revision as of 21:40, 20 October 2025
function AOBScan(...)
function AOBScan(AOBString, ProtectionFlags OPTIONAL, AlignmentType OPTIONAL, AlignmentParam HALFOPTIONAL)
Scans the currently opened process memory for a byte pattern (Array of Bytes) and returns a StringList object containing all matching addresses as hexadecimal strings.
Returns: A StringList containing the addresses found, or nil if no matches are found.
Important: Always call list.destroy() when done to free memory and prevent leaks.
Contents
Two Calling Modes
Mode 1: Pattern String - Provide an AOB pattern as a hex string with optional wildcards
AOBScan(AOBString, ProtectionFlags, AlignmentType, AlignmentParam)
Mode 2: Varargs Bytes - Pass individual byte values as separate arguments
AOBScan(byte1, byte2, byte3, ...)
In varargs mode:
- Values 0-255 are treated as literal bytes
- nil, non-numeric values, or values > 255 become wildcards
- Zero (0) is written as "00" if it's a number, or as a wildcard if nil/non-numeric
Function Parameters
Mode 1: Pattern String
| 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 (see below). Default: "" (scan all memory) | 
| AlignmentType | integer | Optional. Alignment mode: 0=None, 1=Divisible, 2=Last digits. Default: 0 | 
| AlignmentParam | string | Optional. Hex value for alignment checking. Default: "1" | 
Mode 2: Varargs Bytes
| Parameter | Type | Description | 
|---|---|---|
| ... | varargs | Individual byte values (0-255). Use nil or values > 255 for wildcards | 
Protection Flags
The ProtectionFlags parameter is a string that filters which memory regions to scan based on their 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:
"+W-C" Writable memory excluding copy-on-write (don't care about executable) "+X-W-C" Readonly executable memory (code sections) "+X" All executable memory (typical for code scanning) "-W" Non-writable memory only "" Scan everything (equivalent to "*X*W*C") "*X*W*C" Explicitly scan everything (don't care about any flags)
Alignment Parameters
Use AlignmentType and AlignmentParam to constrain addresses and improve scan performance:
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, "F0" = ending in ...F0)
Examples:
AlignmentType=1, AlignmentParam="10" Only 16-byte aligned addresses (0x...0, 0x...10, 0x...20, etc.) AlignmentType=1, AlignmentParam="4" Only 4-byte aligned addresses AlignmentType=2, AlignmentParam="00" Only addresses ending with 00 (0x...00) AlignmentType=2, AlignmentParam="F0" Only addresses ending with F0 (0x...F0)
Wildcard Syntax
Full-byte wildcards: Match any byte value
- ?? - Most common notation
- * - Alternative notation
- Any non-hex characters in a byte position
Nibble wildcards: Match specific half-byte (4 bits)
- 7? - High nibble is 7, low nibble can be anything (matches 70-7F)
- ?A - High nibble can be anything, low nibble is A (matches 0A, 1A, 2A, ..., FA)
Examples:
"48 8B ?? ?? ?? 89" Full wildcards for bytes 3-5 "DE AD ?? EF" Wildcard for byte 3 "7? A? ?3" Nibble wildcards: 7x, Ax, x3
Usage Examples
Basic scan - find all matches:
local results = AOBScan("48 8B 05 ?? ?? ?? 89")
if results then
  print("Found " .. results.Count .. " matches")
  for i = 0, results.Count - 1 do
    print(string.format("%X", results[i]))
  end
  results.destroy()
else
  print("Pattern not found")
end
Scan executable memory only (faster for code patterns):
local results = AOBScan("55 8B EC", "+X")
if results then
  print("First match: " .. results[0])
  results.destroy()
end
Scan with alignment (16-byte aligned addresses):
local results = AOBScan("FF 15 ?? ?? ?? ??", "+X", 1, "10")
if results then
  results.destroy()
end
Scan for addresses ending in 00:
local results = AOBScan("DE AD BE EF", "", 2, "00")
if results then
  results.destroy()
end
Varargs mode with wildcards:
local results = AOBScan(0x48, 0x8B, nil, nil, nil, 0x89) -- nil = wildcard if results then results.destroy() end
Helper function to get first match:
function findAOB(pattern, flags)
  local results = AOBScan(pattern, flags or "+X")
  if results and results.Count > 0 then
    local addr = results[0]
    results.destroy()
    return addr
  end
  return nil
end
local address = findAOB("48 8B ?? ?? ?? 89")
if address then
  print("Found at: " .. address)
end
Performance Tips
- Use +X protection flag when scanning for code to dramatically reduce scan time
- Use alignment when you know the address characteristics (e.g., function pointers are often aligned)
- Keep patterns as specific as possible - avoid excessive wildcards
- For single-result scans, consider using AOBScanUnique or module-specific variants
- Always destroy the StringList after use to prevent memory leaks
Return Value
- Success: Returns a StringList object containing hex address strings
- Failure: Returns nil (no matches found or invalid pattern)
Note: The returned addresses are strings in hexadecimal format (e.g., "7FF12340"). Convert with tonumber(addr, 16) if you need numeric values.
See Also
- AOBScanUnique - Returns a single address or nil (no cleanup needed)
- AOBScanModule - Scan within a specific module
- AOBScanModuleUnique - Find unique pattern in a module
- StringList - String list object documentation

