Revamp history tests

This commit is contained in:
elicn
2023-08-25 02:39:10 +03:00
parent dbe2437fa1
commit 93dcb1723a
+80 -54
View File
@@ -1,100 +1,126 @@
import re
import unittest
from typing import List, Optional, Tuple
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.coverage.formats.history import History
from typing import List
class HistoryTest(unittest.TestCase):
P_LIBC = r".*libc(-\d\.\d+)?.so.*" # covers both generic (i.e. "libc.so.6") and specific (e.g. "libc-2.27.so")
P_LD = r"ld-linux.*"
@staticmethod
def sanitize_mmap_path(mmap: List[tuple]) -> List[tuple]:
'''Removes the path from the mmap tuple so that it can be compared to other mmaps
currently because the loader is handling loading ld and the main binary, we get the annotation of the path in element 5 of the tuple (index 4)
this path is going to be dependent on the users filesystem, so it doesnt quite make sense to test for it
'''
def sanitize_mmap_path(mmap: List[Tuple]) -> List[Tuple[int, int, str, str]]:
"""Removes the path from the mmap tuple so that it can be compared to other mmaps.
currently because the loader is handling loading ld and the main binary, we get the annotation of the path in
element 5 of the tuple (index 4) this path is going to be dependent on the users filesystem, so it doesnt quite
make sense to test for it
"""
if isinstance(mmap, tuple):
mmap = [mmap]
return list(map(lambda x: (x[0], x[1], x[2], x[3], ''), mmap))
return [tup[:4] for tup in mmap]
def setUp(self):
rootfs = '../examples/rootfs/x8664_linux'
argv = [fr'{rootfs}/bin/x8664_hello']
ql = Qiling(argv, rootfs, verbose=QL_VERBOSE.OFF)
self.history = History(ql)
self.ql = ql
def get_label(self, basename: str) -> Optional[str]:
"""Return the matching label from mapinfo, ignoring boxes and possible different suffixes.
For example, on some systems libc label may appear as "libc.so.6" and "libc-2.27.so" on others.
This method also ignores the boxed prefixes, if exists (e.g. "[mmap]")
"""
p = re.compile(rf'\A(\[.+\]\s+)?{basename}[.-]')
return next((label for _, _, _, label, _ in self.ql.mem.map_info if re.match(p, label)), None)
def test_get_regex_matching_exec_maps(self):
ql = Qiling(["../examples/rootfs/x8664_linux/bin/x8664_hello"], "../examples/rootfs/x8664_linux", verbose=QL_VERBOSE.OFF)
history = History(ql)
ql.run()
self.ql.run()
self.assertEqual([(0x7fffb7dd6000, 0x7fffb7fbd000, 'r-x', '[mmap] libc.so.6', '')], history.get_regex_matching_exec_maps(".*libc.so.*"))
self.assertEqual(
self.assertListEqual(
[
(0x7fffb7dd6000, 0x7fffb7fbd000, 'r-x', '[mmap] libc.so.6', ''),
(0x7ffff7dd5000, 0x7ffff7dfc000, 'r-x', 'ld-linux-x86-64.so.2', '')
(0x7fffb7dd6000, 0x7fffb7fbd000, 'r-x', self.get_label('libc'), '')
],
self.sanitize_mmap_path(history.get_regex_matching_exec_maps([".*libc.so.*", "ld.*"]))
self.history.get_regex_matching_exec_maps(self.P_LIBC)
)
del ql
self.assertListEqual(
[
(0x7fffb7dd6000, 0x7fffb7fbd000, 'r-x', self.get_label('libc')),
(0x7ffff7dd5000, 0x7ffff7dfc000, 'r-x', self.get_label('ld'))
],
self.sanitize_mmap_path(self.history.get_regex_matching_exec_maps([self.P_LIBC, self.P_LD]))
)
def test_get_mem_map_from_addr(self):
ql = Qiling(["../examples/rootfs/x8664_linux/bin/x8664_hello"], "../examples/rootfs/x8664_linux", verbose=QL_VERBOSE.OFF)
history = History(ql)
ql.run()
self.ql.run()
self.assertEqual(
self.sanitize_mmap_path(history.get_mem_map_from_addr(0x7ffff7df4830))[0],
(
0x7ffff7dd5000,
0x7ffff7dfc000,
'r-x',
'ld-linux-x86-64.so.2',
''))
mmap = self.history.get_mem_map_from_addr(0x7ffff7df4830)
self.assertIsNotNone(mmap)
self.assertTupleEqual(
(0x7ffff7dd5000, 0x7ffff7dfc000, 'r-x', self.get_label('ld')),
self.sanitize_mmap_path(mmap)[0]
)
def test_get_ins_exclude_lib(self):
ql = Qiling(["../examples/rootfs/x8664_linux/bin/x8664_hello"], "../examples/rootfs/x8664_linux", verbose=QL_VERBOSE.OFF)
history = History(ql)
ql.run(end=0x55555555465a)
self.ql.run(end=0x55555555465a)
non_libc_blocks = history.get_ins_exclude_lib(".*libc.so.*")
non_libc_blocks = self.history.get_ins_exclude_lib(self.P_LIBC)
self.assertGreater(len(non_libc_blocks), 0)
# this test is going to take a while but oh well
# also assumes that the get_mem_map_from_addr function works
for block in non_libc_blocks:
map_for_ins = history.get_mem_map_from_addr(block)
self.assertNotRegex(map_for_ins[3], ".*libc.so.*")
map_for_ins = self.history.get_mem_map_from_addr(block)
assert len(non_libc_blocks) > 0
self.assertIsNotNone(map_for_ins)
self.assertNotRegex(map_for_ins[3], self.P_LIBC)
non_libc_blocks_and_ld = history.get_ins_exclude_lib([".*libc.so.*", "ld-linux.*"])
non_libc_blocks_and_ld = self.history.get_ins_exclude_lib([self.P_LIBC, self.P_LD])
self.assertGreater(len(non_libc_blocks_and_ld), 0)
for block in non_libc_blocks_and_ld:
map_for_ins = history.get_mem_map_from_addr(block)
self.assertNotRegex(map_for_ins[3], ".*libc.so.*|ld-linux.*")
assert len(non_libc_blocks_and_ld) > 0
map_for_ins = self.history.get_mem_map_from_addr(block)
self.assertIsNotNone(map_for_ins)
self.assertNotRegex(map_for_ins[3], '|'.join((self.P_LIBC, self.P_LD)))
def test_get_ins_only_lib(self):
ql = Qiling(["../examples/rootfs/x8664_linux/bin/x8664_hello"], "../examples/rootfs/x8664_linux", verbose=QL_VERBOSE.OFF)
history = History(ql)
ql.run(end=0x55555555465a)
self.ql.run(end=0x55555555465a)
non_libc_blocks = history.get_ins_only_lib(".*libc.so.*")
non_libc_blocks = self.history.get_ins_only_lib(self.P_LIBC)
self.assertGreater(len(non_libc_blocks), 0)
# this test is going to take a while but oh well
# also assumes that the get_mem_map_from_addr function works
for block in non_libc_blocks:
map_for_ins = history.get_mem_map_from_addr(block)
self.assertRegex(map_for_ins[3], ".*libc.so.*")
map_for_ins = self.history.get_mem_map_from_addr(block)
assert len(non_libc_blocks) > 0
self.assertIsNotNone(map_for_ins)
self.assertRegex(map_for_ins[3], self.P_LIBC)
non_libc_blocks_and_ld = history.get_ins_only_lib([".*libc.so.*", "ld-linux.*"])
non_libc_blocks_and_ld = self.history.get_ins_only_lib([self.P_LIBC, self.P_LD])
self.assertGreater(len(non_libc_blocks_and_ld), 0)
for block in non_libc_blocks_and_ld :
map_for_ins = history.get_mem_map_from_addr(block)
self.assertRegex(map_for_ins[3], ".*libc.so.*|.*ld-linux.*")
for block in non_libc_blocks_and_ld:
map_for_ins = self.history.get_mem_map_from_addr(block)
self.assertIsNotNone(map_for_ins)
self.assertRegex(map_for_ins[3], '|'.join((self.P_LIBC, self.P_LD)))
assert len(non_libc_blocks_and_ld) > 0
if __name__ == "__main__":
unittest.main()
unittest.main()