def test_pointer_type_cache(self): """test the comportment of _pointer_type_cache""" # between reset(), we keep the reference to the ctypes modules # and we don't the pointer cache, that we only share with the default # ctypes proxy instance ctypes = types.load_ctypes_default() class X(ctypes.Structure): pass self.assertNotIn(X, ctypes._pointer_type_cache.keys()) ctypes.POINTER(X) self.assertIn(X, ctypes._pointer_type_cache.keys()) # we keep the cache self.assertIn(X, ctypes._pointer_type_cache.keys()) c4 = types.build_ctypes_proxy(4, 4, 8) c8 = types.build_ctypes_proxy(8, 8, 16) cd = types.load_ctypes_default() if c4 != cd: newarch = c4 elif c8 != cd: newarch = c4 else: raise RuntimeError("unmanaged case") # cd and ctypes share a cache self.assertIn(X, cd._pointer_type_cache.keys()) # and cd.POINTER is actually ctypes.POINTER self.assertEquals(cd.POINTER, ctypes.POINTER) self.assertEquals(cd._pointer_type_cache, ctypes._pointer_type_cache) # but not other proxies self.assertNotIn(X, newarch._pointer_type_cache.keys()) class Y(newarch.Structure): pass self.assertNotIn(Y, cd._pointer_type_cache.keys()) self.assertNotIn(Y, ctypes._pointer_type_cache.keys()) self.assertNotIn(Y, newarch._pointer_type_cache.keys()) newarch.POINTER(Y) self.assertNotIn(Y, cd._pointer_type_cache.keys()) self.assertNotIn(Y, ctypes._pointer_type_cache.keys()) self.assertIn(Y, newarch._pointer_type_cache.keys()) pass
def setUp(self): ctypes = types.load_ctypes_default() for name, value in make_types(ctypes).items(): globals()[name] = value self.tests = [St, St2, SubSt2, btype, longt, voidp, stp, stpvoid, arra1, arra2, arra3, charp, string, fptr, arra4, double, arra5, arra6, Union, ptrUnion]
def test_get_pointee_address(self): """tests get_pointee_address on host ctypes POINTER and haystack POINTER""" my_ctypes = types.build_ctypes_proxy(8, 8, 16) my_utils = utils.Utils(my_ctypes) class X(my_ctypes.Structure): _pack_ = True _fields_ = [('a', my_ctypes.c_long), ('p', my_ctypes.POINTER(my_ctypes.c_int)), ('b', my_ctypes.c_ubyte)] self.assertEquals(my_ctypes.sizeof(X), 17) i = X.from_buffer_copy( b'\xAA\xAA\xBB\xBB' + 4 * '\xBB' + 8 * '\x11' + '\xCC') a = my_utils.get_pointee_address(i.p) self.assertEquals(my_ctypes.sizeof(i.p), 8) self.assertNotEquals(a, 0) self.assertEquals(a, 0x1111111111111111) # 8*'\x11' # null pointer i = X.from_buffer_copy( b'\xAA\xAA\xBB\xBB' + 4 * '\xBB' + 8 * '\x00' + '\xCC') pnull = my_utils.get_pointee_address(i.p) self.assertEquals (my_utils.get_pointee_address(pnull), 0) # change arch, and retry my_ctypes = types.build_ctypes_proxy(4, 4, 8) class Y(ctypes.Structure): _pack_ = True _fields_ = [('a', my_ctypes.c_long), ('p', my_ctypes.POINTER(my_ctypes.c_int)), ('b', my_ctypes.c_ubyte)] self.assertEquals(my_ctypes.sizeof(Y), 9) i = Y.from_buffer_copy(b'\xAA\xAA\xBB\xBB' + 4 * '\x11' + '\xCC') a = my_utils.get_pointee_address(i.p) self.assertEquals(my_ctypes.sizeof(i.p), 4) self.assertNotEquals(a, 0) self.assertEquals(a, 0x11111111) # 4*'\x11' # null pointer i = Y.from_buffer_copy(b'\xAA\xAA\xBB\xBB' + 4 * '\x00' + '\xCC') pnull = my_utils.get_pointee_address(i.p) self.assertEquals (my_utils.get_pointee_address(pnull), 0) # non-pointer, and void null pointer my_ctypes = types.load_ctypes_default() i = my_ctypes.c_int(69) self.assertEquals (my_utils.get_pointee_address(i), 0) pnull = my_ctypes.c_void_p(0) self.assertEquals (my_utils.get_pointee_address(pnull), 0) pass
def test_load_ctypes_default(self): """Test if the default proxy works""" ctypes = types.build_ctypes_proxy(4, 4, 8) self.assertTrue(ctypes.proxy) # test ctypes = types.load_ctypes_default() self.assertTrue(ctypes.proxy) for name, value in make_types(ctypes).items(): globals()[name] = value # default ctypes should be similar to host ctypes. self.assertEqual( ctypes.sizeof(arra1), 4 * ctypes.sizeof( ctypes.get_real_ctypes_member('c_long'))) self.assertEqual( ctypes.sizeof(stp), ctypes.sizeof( ctypes.get_real_ctypes_member('c_void_p'))) self.assertEqual( ctypes.sizeof(arra1), 4 * ctypes.sizeof( ctypes.c_long)) self.assertEqual(ctypes.sizeof(stp), ctypes.sizeof(ctypes.c_void_p)) return
def _load_memory_mappings(self): """ make the python objects""" _mappings = [] default_ctypes = types.load_ctypes_default() for mmap_fname, start, end, permissions, offset, major_device, minor_device, inode, pathname in self.metalines: log.debug('Loading %s - %s' % (mmap_fname, pathname)) # open the file in the archive fname = os.path.sep.join([self.dumpname, mmap_fname]) mmap = FilenameBackedMemoryMapping(fname, start, end, permissions, offset, major_device, minor_device, inode, pathname=pathname) mmap.set_ctypes(default_ctypes) _mappings.append(mmap) _target_platform = target.TargetPlatform(_mappings, cpu_bits=self._cpu_bits, os_name=self._os_name) self._memory_handler = MemoryHandler(_mappings, _target_platform, self.dumpname) self._memory_handler.reset_mappings() return
def test_pointer_type_cache(self): """test the comportment of _pointer_type_cache""" # between reset(), we keep the reference to the ctypes modules # and we don't the pointer cache, that we only share with the default # ctypes proxy instance ctypes = types.load_ctypes_default() class X(ctypes.Structure): pass self.assertNotIn(X, ctypes._pointer_type_cache.keys()) ctypes.POINTER(X) self.assertIn(X, ctypes._pointer_type_cache.keys()) # we keep the cache self.assertIn(X, ctypes._pointer_type_cache.keys()) c4 = types.build_ctypes_proxy(4, 4, 8) c8 = types.build_ctypes_proxy(8, 8, 16) cd = types.load_ctypes_default() if c4 != cd: newarch = c4 elif c8 != cd: newarch = c4 else: raise RuntimeError("unmanaged case") # cd and ctypes share a cache self.assertIn(X, cd._pointer_type_cache.keys()) # and cd.POINTER is actually ctypes.POINTER self.assertEqual(cd.POINTER, ctypes.POINTER) self.assertEqual(cd._pointer_type_cache, ctypes._pointer_type_cache) # but not other proxies self.assertNotIn(X, newarch._pointer_type_cache.keys()) class Y(newarch.Structure): pass self.assertNotIn(Y, cd._pointer_type_cache.keys()) self.assertNotIn(Y, ctypes._pointer_type_cache.keys()) self.assertNotIn(Y, newarch._pointer_type_cache.keys()) newarch.POINTER(Y) self.assertNotIn(Y, cd._pointer_type_cache.keys()) self.assertNotIn(Y, ctypes._pointer_type_cache.keys()) self.assertIn(Y, newarch._pointer_type_cache.keys()) pass
def reset(): """Clean the book""" log.info("RESET MODEL") __book.modules = set() from haystack import types ctypes = types.load_ctypes_default() for mod in sys.modules.keys(): if "haystack.reverse" in mod: del sys.modules[mod] log.debug("de-imported %s", mod) log.info("MODEL: %s %s", str(ctypes.c_void_p), id(ctypes.c_void_p))
def test_get_pointee_address(self): """tests get_pointee_address on host ctypes POINTER and haystack POINTER""" my_ctypes = types.build_ctypes_proxy(8, 8, 16) my_utils = utils.Utils(my_ctypes) class X(my_ctypes.Structure): _pack_ = True _fields_ = [('a', my_ctypes.c_long), ('p', my_ctypes.POINTER(my_ctypes.c_int)), ('b', my_ctypes.c_ubyte)] self.assertEquals(my_ctypes.sizeof(X), 17) i = X.from_buffer_copy(b'\xAA\xAA\xBB\xBB' + 4 * '\xBB' + 8 * '\x11' + '\xCC') a = my_utils.get_pointee_address(i.p) self.assertEquals(my_ctypes.sizeof(i.p), 8) self.assertNotEquals(a, 0) self.assertEquals(a, 0x1111111111111111) # 8*'\x11' # null pointer i = X.from_buffer_copy(b'\xAA\xAA\xBB\xBB' + 4 * '\xBB' + 8 * '\x00' + '\xCC') pnull = my_utils.get_pointee_address(i.p) self.assertEquals(my_utils.get_pointee_address(pnull), 0) # change arch, and retry my_ctypes = types.build_ctypes_proxy(4, 4, 8) class Y(ctypes.Structure): _pack_ = True _fields_ = [('a', my_ctypes.c_long), ('p', my_ctypes.POINTER(my_ctypes.c_int)), ('b', my_ctypes.c_ubyte)] self.assertEquals(my_ctypes.sizeof(Y), 9) i = Y.from_buffer_copy(b'\xAA\xAA\xBB\xBB' + 4 * '\x11' + '\xCC') a = my_utils.get_pointee_address(i.p) self.assertEquals(my_ctypes.sizeof(i.p), 4) self.assertNotEquals(a, 0) self.assertEquals(a, 0x11111111) # 4*'\x11' # null pointer i = Y.from_buffer_copy(b'\xAA\xAA\xBB\xBB' + 4 * '\x00' + '\xCC') pnull = my_utils.get_pointee_address(i.p) self.assertEquals(my_utils.get_pointee_address(pnull), 0) # non-pointer, and void null pointer my_ctypes = types.load_ctypes_default() i = my_ctypes.c_int(69) self.assertEquals(my_utils.get_pointee_address(i), 0) pnull = my_ctypes.c_void_p(0) self.assertEquals(my_utils.get_pointee_address(pnull), 0) pass
def test_import(self): #''' Do not replace c_char_p ''' ctypes = types.load_ctypes_default() from haystack import basicmodel self.assertEquals(ctypes.c_char_p.__name__, 'c_char_p', 'c_char_p should not be changed') self.assertFalse( issubclass(ctypes.Structure, basicmodel.CTypesRecordConstraintValidator)) self.assertFalse( issubclass(ctypes.Union, basicmodel.CTypesRecordConstraintValidator)) self.assertIn(ctypes.CString, ctypes.__dict__.values())
def test_import(self): #''' Do not replace c_char_p ''' ctypes = types.load_ctypes_default() from haystack import basicmodel self.assertEqual( ctypes.c_char_p.__name__, 'c_char_p', 'c_char_p should not be changed') self.assertFalse( issubclass( ctypes.Structure, basicmodel.CTypesRecordConstraintValidator)) self.assertFalse(issubclass(ctypes.Union, basicmodel.CTypesRecordConstraintValidator)) self.assertIn(ctypes.CString, ctypes.__dict__.values())
def test_get_subtype(self): my_ctypes = types.load_ctypes_default() my_utils = utils.Utils(my_ctypes) class X(my_ctypes.Structure): _fields_ = [('p', my_ctypes.POINTER(my_ctypes.c_long))] PX = my_ctypes.POINTER(X) self.assertEquals(my_utils.get_subtype(PX), X) my_ctypes = types.build_ctypes_proxy(4, 4, 8) # different arch class Y(my_ctypes.Structure): _fields_ = [('p', my_ctypes.POINTER(my_ctypes.c_long))] PY = my_ctypes.POINTER(Y) self.assertEquals(my_utils.get_subtype(PY), Y)
def test_pointer2bytes(self): # utils.pointer2bytes(attr,nbElement) # FIXME: requires is_address_local ctypes = types.load_ctypes_default() class X(ctypes.Structure): _fields_ = [('a', ctypes.c_long)] nb = 3 x = (nb * X)() x[2].a = 42 ptr = ctypes.POINTER(X)(x[0]) bytes_x = utils.pointer2bytes(ptr, nb) self.assertEquals(len(bytes_x), ctypes.sizeof(x)) self.assertEquals( bytes_x, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\x00\x00\x00\x00\x00\x00\x00') pass
def test_set_ctypes(self): """Test reloading of previous defined arch-ctypes.""" x32 = types.build_ctypes_proxy(4, 4, 8) x64 = types.build_ctypes_proxy(8, 8, 16) win = types.build_ctypes_proxy(8, 8, 8) ctypes = types.load_ctypes_default() ctypes = x32 for name, value in make_types(ctypes).items(): globals()[name] = value self.assertTrue(ctypes.proxy) self.assertEqual(ctypes, x32) self.assertEqual(ctypes.sizeof(arra1), 4 * 4) self.assertEqual(ctypes.sizeof(stp), 4) self.assertEqual(ctypes.sizeof(double), 8) ctypes = x64 for name, value in make_types(ctypes).items(): globals()[name] = value self.assertTrue(ctypes.proxy) self.assertEqual(ctypes, x64) self.assertEqual(ctypes.sizeof(arra1), 4 * 8) self.assertEqual(ctypes.sizeof(stp), 8) self.assertEqual(ctypes.sizeof(double), 16) ctypes = win for name, value in make_types(ctypes).items(): globals()[name] = value self.assertTrue(ctypes.proxy) self.assertEqual(ctypes, win) self.assertEqual(ctypes.sizeof(arra1), 4 * 8) self.assertEqual(ctypes.sizeof(stp), 8) self.assertEqual(ctypes.sizeof(double), 8) ctypes = x32 for name, value in make_types(ctypes).items(): globals()[name] = value self.assertTrue(ctypes.proxy) self.assertEqual(ctypes, x32) self.assertEqual(ctypes.sizeof(arra1), 4 * 4) self.assertEqual(ctypes.sizeof(stp), 4) self.assertEqual(ctypes.sizeof(double), 8) return
def test_cast(self): ctypes = types.load_ctypes_default() i = ctypes.c_int(42) a = ctypes.c_void_p(ctypes.addressof(i)) p = ctypes.cast(a, ctypes.POINTER(ctypes.c_int)) # ctypes is 32bits, local is 64, pointer is 64 bytes # pointer value is truncated. # why is ctypes 32 bites in the first place ? because its called # in the 32 bits unit test class that inherits this one if ctypes.sizeof(ctypes.c_void_p) != ctypes.sizeof( ctypes.get_real_ctypes_member("c_void_p")): self.skipTest('cant cast memory pointer cross platform') self.assertEqual(ctypes.addressof(i), a.value) self.assertEqual(ctypes.addressof(i), ctypes.addressof(p.contents)) i = St() a = ctypes.c_void_p(ctypes.addressof(i)) p = ctypes.cast(a, stp) self.assertEqual(ctypes.addressof(i), a.value) self.assertEqual(ctypes.addressof(i), ctypes.addressof(p.contents))
def test_is_address_local(self): ctypes = types.load_ctypes_default() from test.src import ctypes5_gen64 # kinda chicken and egg here... from haystack.mappings.process import readProcessMappings import os class P: pid = os.getpid() def readBytes(self, addr, size): import ctypes return ctypes.string_at(addr, size) mappings = readProcessMappings(P()) m = mappings.mappings[0] # struct a - basic types s = ctypes.sizeof(ctypes5_gen64.struct_a) a = ctypes5_gen64.struct_a.from_address(m.start) pa = ctypes.c_void_p(m.start) ptr_a = ctypes.POINTER(ctypes5_gen64.struct_a)(a) b = ctypes5_gen64.struct_a.from_address(m.end - s) pb = ctypes.c_void_p(m.end - s) ptr_b = ctypes.POINTER(ctypes5_gen64.struct_a)(b) c = ctypes5_gen64.struct_a.from_address(m.end - 1) pc = ctypes.c_void_p(m.end - 1) ptr_c = ctypes.POINTER(ctypes5_gen64.struct_a)(c) self.assertTrue(utils.is_address_local(pa, structType=None)) self.assertTrue( utils.is_address_local( pa, structType=ctypes5_gen64.struct_a)) self.assertTrue(utils.is_address_local(ptr_a, structType=None)) self.assertTrue( utils.is_address_local( ptr_a, structType=ctypes5_gen64.struct_a)) self.assertTrue(utils.is_address_local(pb, structType=None)) self.assertTrue( utils.is_address_local( pb, structType=ctypes5_gen64.struct_a)) self.assertTrue(utils.is_address_local(ptr_b, structType=None)) self.assertTrue( utils.is_address_local( ptr_b, structType=ctypes5_gen64.struct_a)) self.assertTrue(utils.is_address_local(pc, structType=None)) self.assertFalse( utils.is_address_local( pc, structType=ctypes5_gen64.struct_a)) self.assertTrue(utils.is_address_local(ptr_c, structType=None)) self.assertFalse( utils.is_address_local( ptr_c, structType=ctypes5_gen64.struct_a))
def tearDown(self): model.reset() types.load_ctypes_default()
total += size if mbi.is_readable(): readable += size if mbi.is_writeable(): writeable += size if mbi.is_executable(): executable += size if mbi.is_private(): private += size if mbi.is_mapped(): mapped += size if mbi.is_image(): image += size width = len(str(total)) log.debug(" %%%ds bytes of readable memory" % width) % int(readable) log.debug(" %%%ds bytes of writeable memory" % width) % int(writeable) log.debug(" %%%ds bytes of executable memory" % width) % int(executable) log.debug(" %%%ds bytes of private memory" % width) % int(private) log.debug(" %%%ds bytes of mapped memory" % width) % int(mapped) log.debug(" %%%ds bytes of image memory" % width) % int(image) log.debug(" %%%ds bytes of total memory" % width) % int(total) log.debug("") return class ProcessError(Exception): pass ProcError = ProcessError types.load_ctypes_default()