77-- * Provide a copy of or a link to the original license (GPL-3.0 or later); see LICENSE.md or <https://www.gnu.org/licenses/>.
88
99
10+ -- #region Pattern
1011---- ----------------------------------
1112-- Class: Pattern
1213---- ----------------------------------
2324--- @field private m_address uint64_t
2425--- @field protected m_ptr pointer
2526--- @field private m_sig string
26- --- @field private m_func fun (ptr : pointer ): any
27+ --- @field private m_callback fun (ptr : pointer ): any
2728--- @overload fun ( name : string , ida_sig : string , func : fun ( ptr : pointer ): any ): Pattern
2829local Pattern = { __type = " Pattern" }
2930Pattern .__index = Pattern
4041
4142--- @param name string
4243--- @param ida_sig string
43- --- @param func fun ( ptr : pointer )
44+ --- @param callback fun ( ptr : pointer )
4445--- @return Pattern
45- function Pattern .new (name , ida_sig , func )
46+ function Pattern .new (name , ida_sig , callback )
4647 return setmetatable ({
47- m_name = name ,
48- m_sig = ida_sig ,
49- m_ptr = nullptr ,
50- m_address = 0x0 ,
51- m_func = func
48+ m_name = name ,
49+ m_sig = ida_sig ,
50+ m_ptr = nullptr ,
51+ m_address = 0x0 ,
52+ m_callback = callback
5253 --- @diagnostic disable-next-line : param-type-mismatch
5354 }, Pattern )
5455end
5556
56- -- Scans memory for this pointer's pattern and resolves its address.
57+ -- Scans memory for this pattern and resolves its address.
5758--
58- -- Logs a debug message if successful.
59+ -- Logs a debug messages on successful or failure .
5960--- @return boolean
6061function Pattern :Scan ()
6162 self .m_ptr = memory .scan_pattern (self .m_sig )
@@ -68,10 +69,10 @@ function Pattern:Scan()
6869
6970 log .fdebug (" [PatternScanner]: Found %s at 0x%X" , self .m_name , self .m_address )
7071
71- if (type ( self .m_func ) == " function " ) then
72- local ok , result = pcall (self .m_func , self .m_ptr )
72+ if (self .m_callback ) then
73+ local ok , e = pcall (self .m_callback , self .m_ptr )
7374 if (not ok ) then
74- log .fwarning (" [PatternScanner]: Resolver failed for %s: %s" , self .m_name , result )
75+ log .fwarning (" [PatternScanner]: Resolver failed for %s: %s" , self .m_name , e )
7576 return false
7677 end
7778 end
@@ -84,6 +85,10 @@ function Pattern:GetAddress()
8485 return self .m_address
8586end
8687
88+ -- #endregion
89+
90+ -- #region PatternScanner
91+
8792--- @enum eScannerState
8893local eScannerState = {
8994 NONE = 0x0 ,
@@ -96,50 +101,48 @@ local eScannerState = {
96101---- ----------------------------------
97102-- A singleton manager for storing and lazy scanning multiple memory patterns.
98103--- @class PatternScanner : ClassMeta <PatternScanner >
99- --- @field private m_patterns dict<Pattern>
100- --- @field private m_failed_patterns array<Pattern>
101- --- @field private m_state eScannerState
104+ --- @field protected m_patterns dict<Pattern>
105+ --- @field protected m_failed_patterns array<Pattern>
106+ --- @field protected m_state eScannerState
102107--- @field protected m_initialized boolean
103108--- @overload fun (): PatternScanner
104109local PatternScanner = Class (" PatternScanner" )
105110
106111--- @return PatternScanner
107112function PatternScanner :init ()
108- if (self .m_initialized ) then
109- log .warning (" Attempt to create a second instance of a singleton (PatternScanner)" )
110- return self
111- end
113+ if (self .m_initialized ) then return self end
114+ if (_G .PatternScanner ) then return _G .PatternScanner end
112115
113- self .m_patterns = {}
114- self .m_failed_patterns = {}
115- self .m_state = eScannerState .NONE
116- self .m_initialized = true
117- return self
116+ return setmetatable ({
117+ m_patterns = {},
118+ m_failed_patterns = {},
119+ m_state = eScannerState .NONE ,
120+ m_initialized = true ,
121+ --- @diagnostic disable-next-line
122+ }, PatternScanner )
118123end
119124
120125-- Registers a new pattern to be scanned later.
121126--
122127-- If a pattern with the same name already exists, the new name will be concatenated with four random characters.
123128--- @param name string -- Unique name
124129--- @param sig string -- IDA signature
125- --- @param func fun ( ptr : pointer ) -- Resolver called with the found pointer.
126- function PatternScanner :Add (name , sig , func )
130+ --- @param callback fun ( ptr : pointer ) -- Resolver called with the found pointer.
131+ function PatternScanner :Add (name , sig , callback )
127132 if (self .m_patterns [name ]) then
128133 name = name .. string .random (4 )
129134 log .fwarning (" [PatternScanner]: A pattern with the same name already exists. Renamed current to '%s'" , name )
130135 end
131136
132- self .m_patterns [name ] = Pattern (name , sig , func )
137+ self .m_patterns [name ] = Pattern (name , sig , callback )
133138end
134139
135140--- @return Pattern ?
136141function PatternScanner :Get (name )
137142 return self .m_patterns [name ]
138143end
139144
140- -- Scans all registered patterns asynchronously in a fiber.
141- --
142- -- Should be called on script init.
145+ -- Scans all registered patterns. Should be called on script init.
143146function PatternScanner :Scan ()
144147 if (self :IsBusy ()) then
145148 log .debug (" PatternScanner is busy at the moment. Try again later." )
@@ -159,7 +162,6 @@ function PatternScanner:Scan()
159162 if (not ptr :Scan ()) then
160163 table.insert (self .m_failed_patterns , ptr )
161164 end
162-
163165 -- yield()
164166 end
165167
@@ -184,12 +186,11 @@ function PatternScanner:RetryScan()
184186
185187 ThreadManager :Run (function ()
186188 local success = 0
187- self .m_state = eScannerState .BUSY
189+ self .m_state = eScannerState .BUSY
188190
189191 for i = sizeof_failed , 1 , - 1 do
190- local ptr = self .m_failed_patterns [i ]
191-
192- if (ptr :Scan ()) then
192+ local pattern = self .m_failed_patterns [i ]
193+ if (pattern :Scan ()) then
193194 table.remove (self .m_failed_patterns , i )
194195 success = success + 1
195196 end
@@ -217,9 +218,13 @@ function PatternScanner:IsBusy()
217218 return self .m_state == eScannerState .BUSY
218219end
219220
220- --- @return dict<Pattern> , array<Pattern>
221- function PatternScanner :ListPointers ()
221+ --- @return dict<Pattern> patterns , array<Pattern> failed_patterns
222+ function PatternScanner :ListPatterns ()
222223 return self .m_patterns , self .m_failed_patterns
223224end
224225
225- return PatternScanner ()
226+ -- #endregion
227+
228+ local singleInstance = PatternScanner ()
229+ _G .PatternScanner = singleInstance
230+ return singleInstance
0 commit comments