@@ -111,8 +111,21 @@ def parse_bitmap(
111111 The list of indices at which a 1 was found.
112112 """
113113 ret = []
114+ # This value is broken in many samples and was causing essentially infinite loops
115+ # Testing showed that 8192 is the current size across all Windows versions
116+ # We give some leeway in case it increases in later versions, while still keeping it sane
117+ # The problematic samples had values that looked like addresses, so in the billions
118+ if bitmap_size_in_byte > 8192 * 10 :
119+ return ret
120+
114121 for idx in range (bitmap_size_in_byte ):
115- current_byte = context .layers [layer_name ].read (bitmap_offset + idx , 1 )[0 ]
122+ try :
123+ current_byte = context .layers [layer_name ].read (bitmap_offset + idx , 1 )[
124+ 0
125+ ]
126+ except exceptions .InvalidAddressException :
127+ continue
128+
116129 current_offs = idx * 8
117130 for bit in range (8 ):
118131 if current_byte & (1 << bit ) != 0 :
@@ -154,32 +167,37 @@ def enumerate_structures_by_port(
154167 )
155168 else :
156169 # invalid argument.
157- return None
170+ return
158171
159172 vollog .debug (f"Current Port: { port } " )
160173 # the given port serves as a shifted index into the port pool lists
161174 list_index = port >> 8
162175 truncated_port = port & 0xFF
163176
164- # constructing port_pool object here so callers don't have to
165- port_pool = context . object (
166- net_symbol_table + constants . BANG + "_INET_PORT_POOL" ,
167- layer_name = layer_name ,
168- offset = port_pool_addr ,
169- )
170-
171- # first, grab the given port's PortAssignment (`_PORT_ASSIGNMENT`)
172- inpa = port_pool .PortAssignments [list_index ]
177+ try :
178+ # constructing port_pool object here so callers don't have to
179+ port_pool = context . object (
180+ net_symbol_table + constants . BANG + "_INET_PORT_POOL" ,
181+ layer_name = layer_name ,
182+ offset = port_pool_addr ,
183+ )
184+ # first, grab the given port's PortAssignment (`_PORT_ASSIGNMENT`)
185+ inpa = port_pool .PortAssignments [list_index ]
173186
174- # then parse the port assignment list (`_PORT_ASSIGNMENT_LIST`) and grab the correct entry
175- assignment = inpa .InPaBigPoolBase .Assignments [truncated_port ]
187+ # then parse the port assignment list (`_PORT_ASSIGNMENT_LIST`) and grab the correct entry
188+ assignment = inpa .InPaBigPoolBase .Assignments [truncated_port ]
189+ except exceptions .InvalidAddressException :
190+ return
176191
177192 if not assignment :
178- return None
193+ return
179194
180195 # the value within assignment.Entry is a) masked and b) points inside of the network object
181196 # first decode the pointer
182- netw_inside = cls ._decode_pointer (assignment .Entry )
197+ try :
198+ netw_inside = cls ._decode_pointer (assignment .Entry )
199+ except exceptions .InvalidAddressException :
200+ return
183201
184202 if netw_inside :
185203 # if the value is valid, calculate the actual object address by subtracting the offset
@@ -188,16 +206,30 @@ def enumerate_structures_by_port(
188206 )
189207 yield curr_obj
190208
209+ try :
210+ next_obj_address = cls ._decode_pointer (curr_obj .Next )
211+ except exceptions .InvalidAddressException :
212+ return
213+
191214 # if the same port is used on different interfaces multiple objects are created
192215 # those can be found by following the pointer within the object's `Next` field until it is empty
193- while curr_obj .Next :
194- curr_obj = context .object (
195- obj_name ,
196- layer_name = layer_name ,
197- offset = cls ._decode_pointer (curr_obj .Next ) - ptr_offset ,
198- )
216+ while next_obj_address :
217+ try :
218+ curr_obj = context .object (
219+ obj_name ,
220+ layer_name = layer_name ,
221+ offset = next_obj_address - ptr_offset ,
222+ )
223+ except exceptions .InvalidAddressException :
224+ return
225+
199226 yield curr_obj
200227
228+ try :
229+ next_obj_address = cls ._decode_pointer (curr_obj .Next )
230+ except exceptions .InvalidAddressException :
231+ return
232+
201233 @classmethod
202234 def get_tcpip_module (
203235 cls ,
@@ -243,16 +275,25 @@ def parse_hashtable(
243275 The hash table entries which are _not_ empty
244276 """
245277 # we are looking for entries whose values are not their own address
278+ # smear sanity check from mass testing
279+ if ht_length > 4096 :
280+ return
281+
246282 for index in range (ht_length ):
247283 current_addr = ht_offset + index * alignment
248- current_pointer = context .object (
249- net_symbol_table + constants .BANG + "pointer" ,
250- layer_name = layer_name ,
251- offset = current_addr ,
252- )
284+ try :
285+ current_pointer = context .object (
286+ net_symbol_table + constants .BANG + "pointer" ,
287+ layer_name = layer_name ,
288+ offset = current_addr ,
289+ )
290+ except exceptions .InvalidAddressException :
291+ continue
292+
253293 # check if addr of pointer is equal to the value pointed to
254294 if current_pointer .vol .offset == current_pointer :
255295 continue
296+
256297 yield current_pointer
257298
258299 @classmethod
@@ -292,22 +333,34 @@ def parse_partitions(
292333 tcpip_symbol_table + constants .BANG + "PartitionCount"
293334 ).address
294335
295- part_table_addr = context .object (
296- net_symbol_table + constants .BANG + "pointer" ,
297- layer_name = layer_name ,
298- offset = tcpip_module_offset + part_table_symbol ,
299- )
336+ try :
337+ part_table_addr = context .object (
338+ net_symbol_table + constants .BANG + "pointer" ,
339+ layer_name = layer_name ,
340+ offset = tcpip_module_offset + part_table_symbol ,
341+ )
342+ except exceptions .InvalidAddressException :
343+ vollog .debug (f"`PartitionTable` not present in memory." )
344+ return
300345
301346 # part_table is the actual partition table offset and consists out of a dynamic amount of _PARTITION objects
302347 part_table = context .object (
303348 net_symbol_table + constants .BANG + "_PARTITION_TABLE" ,
304349 layer_name = layer_name ,
305350 offset = part_table_addr ,
306351 )
307- part_count = int .from_bytes (
308- context .layers [layer_name ].read (tcpip_module_offset + part_count_symbol , 1 ),
309- "little" ,
310- )
352+
353+ try :
354+ part_count = int .from_bytes (
355+ context .layers [layer_name ].read (
356+ tcpip_module_offset + part_count_symbol , 1
357+ ),
358+ "little" ,
359+ )
360+ except exceptions .InvalidAddressException :
361+ vollog .debug (f"`PartitionCount` not present in memory." )
362+ return
363+
311364 part_table .Partitions .count = part_count
312365
313366 vollog .debug (
@@ -316,9 +369,21 @@ def parse_partitions(
316369 entry_offset = context .symbol_space .get_type (obj_name ).relative_child_offset (
317370 "ListEntry"
318371 )
319- for ctr , partition in enumerate (part_table .Partitions ):
372+
373+ try :
374+ partitions = part_table .Partitions
375+ except exceptions .InvalidAddressException :
376+ vollog .debug ("Partitions member not present in memory" )
377+ return
378+
379+ for ctr , partition in enumerate (partitions ):
320380 vollog .debug (f"Parsing partition { ctr } " )
321- if partition .Endpoints .NumEntries > 0 :
381+ try :
382+ num_entries = partition .Endpoints .NumEntries
383+ except exceptions .InvalidAddressException :
384+ continue
385+
386+ if num_entries > 0 :
322387 for endpoint_entry in cls .parse_hashtable (
323388 context ,
324389 layer_name ,
@@ -402,6 +467,7 @@ def find_port_pools(
402467 upp_symbol = context .symbol_space .get_symbol (
403468 tcpip_symbol_table + constants .BANG + "UdpPortPool"
404469 ).address
470+
405471 upp_addr = context .object (
406472 net_symbol_table + constants .BANG + "pointer" ,
407473 layer_name = layer_name ,
@@ -498,13 +564,16 @@ def list_sockets(
498564
499565 # then, towards the UDP and TCP port pools
500566 # first, find their addresses
501- upp_addr , tpp_addr = cls .find_port_pools (
502- context ,
503- layer_name ,
504- net_symbol_table ,
505- tcpip_symbol_table ,
506- tcpip_module_offset ,
507- )
567+ try :
568+ upp_addr , tpp_addr = cls .find_port_pools (
569+ context ,
570+ layer_name ,
571+ net_symbol_table ,
572+ tcpip_symbol_table ,
573+ tcpip_module_offset ,
574+ )
575+ except (exceptions .SymbolError , exceptions .InvalidAddressException ):
576+ vollog .debug ("Unable to reconstruct port pools" )
508577
509578 # create port pool objects at the detected address and parse the port bitmap
510579 upp_obj = context .object (
0 commit comments