Skip to content

Commit 0d37928

Browse files
committed
Support plain and regex memory searches
1 parent 835d889 commit 0d37928

File tree

2 files changed

+16
-12
lines changed

2 files changed

+16
-12
lines changed

qiling/os/memory.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55

66
import os, re
7-
from typing import Any, Callable, List, Mapping, MutableSequence, Optional, Sequence, Tuple
7+
from typing import Any, Callable, Iterator, List, Mapping, MutableSequence, Optional, Pattern, Sequence, Tuple, Union
88

99
from unicorn import UC_PROT_NONE, UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC, UC_PROT_ALL
1010

@@ -371,18 +371,18 @@ def write_ptr(self, addr: int, value: int, size: int=None) -> None:
371371

372372
self.write(addr, __pack(value))
373373

374-
def search(self, needle: bytes, begin: int = None, end: int = None) -> Sequence[int]:
374+
def search(self, needle: Union[bytes, Pattern[bytes]], begin: int = None, end: int = None) -> Sequence[int]:
375375
"""Search for a sequence of bytes in memory.
376376
377377
Args:
378-
needle: bytes sequence to look for
378+
needle: bytes sequence or regex pattern to look for
379379
begin: search starting address (or None to start at lowest avaiable address)
380380
end: search ending address (or None to end at highest avaiable address)
381381
382382
Returns: addresses of all matches
383383
"""
384384

385-
# if starting point not set, search from the first mapped region
385+
# if starting point not set, search from the first mapped region
386386
if begin is None:
387387
begin = self.map_info[0][0]
388388

@@ -396,6 +396,10 @@ def search(self, needle: bytes, begin: int = None, end: int = None) -> Sequence[
396396
ranges = [(max(begin, lbound), min(ubound, end)) for lbound, ubound, _, _, is_mmio in self.map_info if not (end < lbound or ubound < begin or is_mmio)]
397397
results = []
398398

399+
# if needle is a bytes sequence use it verbatim, not as a pattern
400+
if type(needle) is bytes:
401+
needle = re.escape(needle)
402+
399403
for lbound, ubound in ranges:
400404
haystack = self.read(lbound, ubound - lbound)
401405
local_results = (match.start(0) + lbound for match in re.finditer(needle, haystack))

tests/test_elf.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,28 +1119,28 @@ def test_memory_search(self):
11191119
ql.mem.write(0x1FFB, b"\x1f\x00\x07\x53\x03\x06\x07\x1f\x1b")
11201120

11211121
# Needle not in haystack
1122-
self.assertEqual([], ql.mem.search(re.escape(b"\x3a\x01\x0b\x03\x53\x29\x1b\x1c\x04\x0d\x11")))
1122+
self.assertEqual([], ql.mem.search(b"\x3a\x01\x0b\x03\x53\x29\x1b\x1c\x04\x0d\x11"))
11231123

11241124
# Needle appears several times in haystack
1125-
self.assertEqual([0x1000 + 24, 0x2000 + 38, 0x3000 + 24], ql.mem.search(re.escape(b"\x4f\x53\x06\x0d\x1e\x0d\x1a")))
1125+
self.assertEqual([0x1000 + 24, 0x2000 + 38, 0x3000 + 24], ql.mem.search(b"\x4f\x53\x06\x0d\x1e\x0d\x1a"))
11261126

11271127
# Needle inside haystack
1128-
self.assertEqual([0x1000 + 13], ql.mem.search(re.escape(b"\x0f\x01\x1e\x0d\x53\x11\x07\x1d\x53\x1d\x18"), begin=0x1000 + 10, end=0x1000 + 30))
1128+
self.assertEqual([0x1000 + 13], ql.mem.search(b"\x0f\x01\x1e\x0d\x53\x11\x07\x1d\x53\x1d\x18", begin=0x1000 + 10, end=0x1000 + 30))
11291129

11301130
# Needle before haystack
1131-
self.assertEqual([], ql.mem.search(re.escape(b"\x04\x0d\x1c\x53\x11\x07\x1d\x53\x0c\x07\x1f\x06"), begin=0x1337))
1131+
self.assertEqual([], ql.mem.search(b"\x04\x0d\x1c\x53\x11\x07\x1d\x53\x0c\x07\x1f\x06", begin=0x1337))
11321132

11331133
# Needle after haystack
1134-
self.assertEqual([], ql.mem.search(re.escape(b"\x1b\x09\x11\x53\x0f\x07\x07\x0c\x0a\x11\x0d"), end=0x3000 + 13))
1134+
self.assertEqual([], ql.mem.search(b"\x1b\x09\x11\x53\x0f\x07\x07\x0c\x0a\x11\x0d", end=0x3000 + 13))
11351135

11361136
# Needle exactly inside haystack
1137-
self.assertEqual([0x2000 + 13], ql.mem.search(re.escape(b"\x1a\x1d\x06\x53\x09\x1a\x07\x1d\x06\x0c"), begin=0x2000 + 13, end=0x2000 + 23))
1137+
self.assertEqual([0x2000 + 13], ql.mem.search(b"\x1a\x1d\x06\x53\x09\x1a\x07\x1d\x06\x0c", begin=0x2000 + 13, end=0x2000 + 23))
11381138

11391139
# Needle 'tears' two mapped regions
1140-
self.assertEqual([], ql.mem.search(re.escape(b"\x1f\x00\x07\x53\x03\x06\x07\x1f\x1b"), begin=0x1F00, end=0x200F))
1140+
self.assertEqual([], ql.mem.search(b"\x1f\x00\x07\x53\x03\x06\x07\x1f\x1b", begin=0x1F00, end=0x200F))
11411141

11421142
# Needle is a regex
1143-
self.assertEqual([0x1000 + 11, 0x2000 + 11, 0x3000 + 43], ql.mem.search(b"\x09\x53(\x0f|\x1a|\x04)[^\x0d]"))
1143+
self.assertEqual([0x1000 + 11, 0x2000 + 11, 0x3000 + 43], ql.mem.search(re.compile(b"\x09\x53(\x0f|\x1a|\x04)[^\x0d]")))
11441144

11451145
del ql
11461146

0 commit comments

Comments
 (0)