ntmemoryapi 2.1.5__tar.gz → 2.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ntmemoryapi
3
- Version: 2.1.5
3
+ Version: 2.2.1
4
4
  Summary: Simple library for Windows to manipulate process virtual memory with stelthy syscall wraps.
5
5
  Author: Xenely
6
6
  Requires-Dist: psutil>=7.1.3
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ntmemoryapi"
3
- version = "2.1.5"
3
+ version = "2.2.1"
4
4
  description = "Simple library for Windows to manipulate process virtual memory with stelthy syscall wraps."
5
5
  authors = [
6
6
  {name = "Xenely"}
@@ -505,8 +505,8 @@ class Process:
505
505
 
506
506
  raise ValueError("Invalid pattern: `%s`" % pattern)
507
507
 
508
- # Result list of found addresses
509
- found_addresses = []
508
+ # List of regions to scan
509
+ to_scan_regions = []
510
510
 
511
511
  # iterate memory regions and finding addresses at them
512
512
  for region in self.list_memory_regions(allowed_states, allowed_protects, allowed_types, memory_regions_filter):
@@ -528,18 +528,39 @@ class Process:
528
528
  continue
529
529
 
530
530
  # Scan params
531
- scan_start = max(region_start, start_address) if start_address is not None else region_start
532
- scan_size = min(region_end, end_address) - scan_start if end_address is not None else region_end - scan_start
531
+ scan_adderss = max(region_start, start_address) if start_address is not None else region_start
532
+ scan_size = min(region_end, end_address) - scan_adderss if end_address is not None else region_end - scan_adderss
533
+
534
+ # Save region information to scan later
535
+ to_scan_regions.append((scan_adderss, scan_size))
536
+
537
+ # If no regions to scan presented
538
+ if not to_scan_regions:
539
+ return []
540
+
541
+ # Result list of found addresses
542
+ found_addresses = []
543
+
544
+ # Pre-allocated buffer to hold read memory
545
+ read_memory_buffer = (ctypes.c_byte * (max(item[-1] for item in to_scan_regions) + 1))()
546
+
547
+ # Iterate regions to scan read them and find pattern
548
+ for scan_adderss, scan_size in to_scan_regions:
549
+
550
+ # If required amount of addresses found
551
+ if return_first is not None and return_first <= 0:
552
+ break
533
553
 
534
- # Read region as bytes
535
554
  try:
536
- read_region_bytes = self.read_bytes(scan_start, scan_size)
555
+
556
+ # Read bytes into pre-allocated buffer
557
+ self.read_into_buffer(scan_adderss, scan_size, ctypes.addressof(read_memory_buffer))
537
558
 
538
559
  except Exception:
539
- continue
560
+ pass
540
561
 
541
562
  # Pattern scan region using SIMD KMP algorithm
542
- self.__kmp.scanAOB(read_region_bytes, scan_size, pattern.strip().encode(), ctypes.c_uint64(scan_start), ctypes.c_uint64(return_first if return_first is not None else 0), ctypes.byref(scan_result := PatternScanBuffer()))
563
+ self.__kmp.scanAOB(ctypes.addressof(read_memory_buffer), scan_size, pattern.strip().encode(), ctypes.c_uint64(scan_adderss), ctypes.c_uint64(return_first if return_first is not None else 0), ctypes.byref(scan_result := PatternScanBuffer()))
543
564
 
544
565
  # Read result addresses
545
566
  addresses = scan_result.read()
@@ -665,6 +686,13 @@ class Process:
665
686
 
666
687
  return buffer
667
688
 
689
+ def read_into_buffer(self, address: int, size: int, buffer_pointer: int) -> None:
690
+ """Read bytes array of variadic size located at given address into pre-allocated internal buffer by pointer."""
691
+
692
+ # If result failed
693
+ if (result := _nt_read_virtual_memory(self.handle, address, buffer_pointer, size, None)):
694
+ raise MemoryReadError(result, address)
695
+
668
696
  def write_int8(self, address: int, value: int) -> None:
669
697
  """Write 1 byte signed integer value at given address."""
670
698
 
File without changes