about summary refs log tree commit diff stats
path: root/test/analysis/mem.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--test/analysis/mem.py440
1 files changed, 440 insertions, 0 deletions
diff --git a/test/analysis/mem.py b/test/analysis/mem.py
new file mode 100644
index 00000000..4b306e67
--- /dev/null
+++ b/test/analysis/mem.py
@@ -0,0 +1,440 @@
+#!/usr/bin/env python
+
+# miasm2.analysis.mem tests
+
+
+from miasm2.analysis.machine import Machine
+from miasm2.analysis.mem import *
+from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE
+
+# Two structures with some fields
+class OtherStruct(MemStruct):
+    fields = [
+        ("foo", Num("H")),
+    ]
+
+class MyStruct(MemStruct):
+    fields = [
+        # Integer field: just struct.pack fields with one value
+        ("num", Num("I")),
+        ("flags", Num("B")),
+        # Ptr fields are Int, but they can also be dereferenced
+        # (self.deref_<field>). Deref can be read and set.
+        ("other", Ptr("I", OtherStruct)),
+        # Ptr to a variable length String
+        ("s", Ptr("I", MemStr)),
+        ("i", Ptr("I", Num("I"))),
+    ]
+
+jitter = Machine("x86_32").jitter("python")
+jitter.init_stack()
+addr = 0x1000
+addr2 = 0x1100
+addr3 = 0x1200
+addr_str = 0x1300
+addr_str2 = 0x1400
+addr_str3 = 0x1500
+addr4 = 0x1600
+addr5 = 0x1700
+addr6 = 0x1800
+addr7 = 0x1900
+addr8 = 0x2000
+addr9 = 0x2100
+addr10 = 0x2200
+addr11 = 0x2300
+size = 0x2000
+# Initialize all mem with 0xaa
+jitter.vm.add_memory_page(addr, PAGE_READ | PAGE_WRITE, "\xaa"*size)
+
+
+# MemStruct tests
+## Creation
+mstruct = MyStruct(jitter.vm, addr)
+## Fields are read from the virtual memory
+assert mstruct.num == 0xaaaaaaaa
+assert mstruct.flags == 0xaa
+
+## Field assignment modifies virtual memory
+mstruct.num = 3
+assert mstruct.num == 3
+memval = struct.unpack("I", jitter.vm.get_mem(mstruct.get_addr(), 4))[0]
+assert memval == 3
+
+## Memset sets the whole structure
+mstruct.memset()
+assert mstruct.num == 0
+assert mstruct.flags == 0
+assert mstruct.other == 0
+assert mstruct.s == 0
+assert mstruct.i == 0
+mstruct.memset('\x11')
+assert mstruct.num == 0x11111111
+assert mstruct.flags == 0x11
+assert mstruct.other == 0x11111111
+assert mstruct.s == 0x11111111
+assert mstruct.i == 0x11111111
+
+
+# Ptr tests
+## Setup for Ptr tests
+other = OtherStruct(jitter.vm, addr2)
+other.foo = 0x1234
+assert other.foo == 0x1234
+
+## Basic usage
+mstruct.other = other.get_addr()
+assert mstruct.other == addr2
+assert mstruct.deref_other == other
+assert mstruct.deref_other.foo == 0x1234
+
+## Deref assignment
+other2 = OtherStruct(jitter.vm, addr3)
+other2.foo = 0xbeef
+assert mstruct.deref_other != other2
+mstruct.deref_other = other2
+assert mstruct.deref_other == other2
+assert mstruct.deref_other.foo == 0xbeef
+assert mstruct.other == addr2 # Addr did not change
+assert other.foo == 0xbeef # Deref assignment copies by value
+assert other2.foo == 0xbeef
+assert other.get_addr() != other2.get_addr() # Not the same address
+assert other == other2 # But same value
+
+## Same stuff for Ptr to MemField
+mstruct.i = addr7
+mstruct.deref_i.value = 8
+assert mstruct.deref_i.value == 8
+assert mstruct.i == addr7
+memval = struct.unpack("I", jitter.vm.get_mem(addr7, 4))[0]
+assert memval == 8
+
+
+# Str tests
+## Basic tests
+memstr = MemStr(jitter.vm, addr_str)
+memstr.value = ""
+assert memstr.value == ""
+assert jitter.vm.get_mem(memstr.get_addr(), 1) == '\x00'
+memstr.value = "lala"
+assert jitter.vm.get_mem(memstr.get_addr(), memstr.get_size()) == 'lala\x00'
+jitter.vm.set_mem(memstr.get_addr(), 'MIAMs\x00')
+assert memstr.value == 'MIAMs'
+
+## Ptr(MemStr) manipulations
+mstruct.s = memstr.get_addr()
+assert mstruct.s == addr_str
+assert mstruct.deref_s == memstr
+assert mstruct.deref_s.value == 'MIAMs'
+mstruct.deref_s.value = "That's all folks!"
+assert mstruct.deref_s.value == "That's all folks!"
+assert memstr.value == "That's all folks!"
+
+## Other address, same value, same encoding
+memstr2 = MemStr(jitter.vm, addr_str2)
+memstr2.value = "That's all folks!"
+assert memstr2.get_addr() != memstr.get_addr()
+assert memstr2 == memstr
+
+## Same value, other encoding
+memstr3 = MemStr(jitter.vm, addr_str3, "utf16")
+memstr3.value = "That's all folks!"
+assert memstr3.get_addr() != memstr.get_addr()
+assert memstr3.get_size() != memstr.get_size() # Size is different
+assert str(memstr3) != str(memstr) # Mem representation is different
+assert memstr3 != memstr # Encoding is different, so they are not eq
+assert memstr3.value == memstr.value # But the python value is the same
+
+
+# MemArray tests
+memarray = MemArray(jitter.vm, addr6, Num("I"))
+# This also works:
+_memarray = mem_array_type(Num("I"))(jitter.vm, addr6)
+memarray[0] = 0x02
+assert memarray[0] == 0x02
+assert jitter.vm.get_mem(memarray.get_addr(),
+                         Num("I").size()) == '\x02\x00\x00\x00'
+memarray[2] = 0xbbbbbbbb
+assert memarray[2] == 0xbbbbbbbb
+assert jitter.vm.get_mem(memarray.get_addr() + 2 * Num("I").size(),
+                         Num("I").size()) == '\xbb\xbb\xbb\xbb'
+try:
+    s = str(memarray)
+    assert False, "Should raise"
+except (NotImplementedError, ValueError):
+    pass
+try:
+    s = len(memarray)
+    assert False, "Should raise"
+except (NotImplementedError, ValueError):
+    pass
+
+## Slice assignment
+memarray[2:4] = [3, 3]
+assert memarray[2] == 3
+assert memarray[3] == 3
+assert memarray[2:4] == [3, 3]
+try:
+    memarray[2:4] = [3, 3, 3]
+    assert False, "Should raise, mismatched sizes"
+except (ValueError):
+    pass
+
+try:
+    memarray[1, 2]
+    assert False, "Should raise, mismatched sizes"
+except (ValueError):
+    pass
+
+
+# MemSizedArray tests
+memsarray = MemSizedArray(jitter.vm, addr6, Num("I"), 10)
+# This also works:
+_memsarray = mem_sized_array_type(Num("I"), 10)(jitter.vm, addr6)
+# And mem_sized_array_type generates statically sized types
+assert _memsarray.sizeof() == len(memsarray)
+memsarray.memset('\xcc')
+assert memsarray[0] == 0xcccccccc
+assert len(memsarray) == 10 * 4
+assert str(memsarray) == '\xcc' * (4 * 10)
+for val in memsarray:
+    assert val == 0xcccccccc
+assert list(memsarray) == [0xcccccccc] * 10
+memsarray[0] = 2
+assert memsarray[0] == 2
+assert str(memsarray) == '\x02\x00\x00\x00' + '\xcc' * (4 * 9)
+
+
+# Atypical fields (Struct and Array)
+class MyStruct2(MemStruct):
+    fields = [
+        ("s1", Struct("=BI")),
+        ("s2", Array(Num("B"), 10)),
+    ]
+
+ms2 = MyStruct2(jitter.vm, addr5)
+ms2.memset('\xaa')
+assert len(ms2) == 15
+
+## Struct
+assert len(ms2.s1) == 2
+assert ms2.s1[0] == 0xaa
+assert ms2.s1[1] == 0xaaaaaaaa
+
+## Array
+### Basic checks
+assert len(ms2.s2) == 10
+for val in ms2.s2:
+    assert val == 0xaa
+assert ms2.s2[0] == 0xaa
+assert ms2.s2[9] == 0xaa
+
+### Subscript assignment
+ms2.s2[3] = 2
+assert ms2.s2[3] == 2
+
+### Field assignment (list)
+ms2.s2 = [1] * 10
+for val in ms2.s2:
+    assert val == 1
+
+### Field assignment (MemSizedArray)
+jitter.vm.set_mem(addr4, '\x02'*10)
+array2 = MemSizedArray(jitter.vm, addr4, Num("B"), 10)
+for val in array2:
+    assert val == 2
+ms2.s2 = array2
+for val in ms2.s2:
+    assert val == 2
+
+
+# Inline tests
+class InStruct(MemStruct):
+    fields = [
+        ("foo", Num("B")),
+        ("bar", Num("B")),
+    ]
+
+class ContStruct(MemStruct):
+    fields = [
+        ("one", Num("B")),
+        ("instruct", Inline(InStruct)),
+        ("last", Num("B")),
+    ]
+
+cont = ContStruct(jitter.vm, addr4)
+cont.memset()
+assert len(cont) == 4
+assert len(cont.instruct) == 2
+assert cont.one == 0
+assert cont.last == 0
+assert cont.instruct.foo == 0
+assert cont.instruct.bar == 0
+cont.memset('\x11')
+assert cont.one == 0x11
+assert cont.last == 0x11
+assert cont.instruct.foo == 0x11
+assert cont.instruct.bar == 0x11
+
+cont.one = 0x01
+cont.instruct.foo = 0x02
+cont.instruct.bar = 0x03
+cont.last = 0x04
+assert cont.one == 0x01
+assert cont.instruct.foo == 0x02
+assert cont.instruct.bar == 0x03
+assert cont.last == 0x04
+assert jitter.vm.get_mem(cont.get_addr(), len(cont)) == '\x01\x02\x03\x04'
+
+# Quick mem(MemField) test:
+assert mem(Num("f"))(jitter.vm, addr) == mem(Num("f"))(jitter.vm, addr)
+
+
+# Union test
+class UniStruct(MemStruct):
+    fields = [
+        ("one", Num("B")),
+        ("union", Union([
+            ("instruct", Inline(InStruct)),
+            ("i", Num(">I")),
+        ])),
+        ("last", Num("B")),
+    ]
+
+uni = UniStruct(jitter.vm, addr8)
+jitter.vm.set_mem(addr8, ''.join(chr(x) for x in xrange(len(uni))))
+assert len(uni) == 6 # 1 + max(InStruct.sizeof(), 4) + 1
+assert uni.one == 0x00
+assert uni.instruct.foo == 0x01
+assert uni.instruct.bar == 0x02
+assert uni.i == 0x01020304
+assert uni.last == 0x05
+uni.instruct.foo = 0x02
+assert uni.i == 0x02020304
+uni.i = 0x11223344
+assert uni.instruct.foo == 0x11
+assert uni.instruct.bar == 0x22
+
+
+# BitField test
+class BitStruct(MemStruct):
+    fields = [
+        ("flags", BitField(Num("H"), [
+            ("f1_1", 1),
+            ("f2_5", 5),
+            ("f3_8", 8),
+            ("f4_1", 1),
+        ])),
+    ]
+
+bit = BitStruct(jitter.vm, addr9)
+bit.memset()
+assert bit.flags == 0
+assert bit.f1_1 == 0
+assert bit.f2_5 == 0
+assert bit.f3_8 == 0
+assert bit.f4_1 == 0
+bit.f1_1 = 1
+bit.f2_5 = 0b10101
+bit.f3_8 = 0b10000001
+assert bit.flags == 0b0010000001101011
+assert bit.f1_1 == 1
+assert bit.f2_5 == 0b10101
+assert bit.f3_8 == 0b10000001
+assert bit.f4_1 == 0
+bit.flags = 0b1101010101011100
+assert bit.f1_1 == 0
+assert bit.f2_5 == 0b01110
+assert bit.f3_8 == 0b01010101
+assert bit.f4_1 == 1
+
+
+# Unhealthy ideas
+class UnhealthyIdeas(MemStruct):
+    fields = [
+        ("f1", Ptr("I", MemArray, Struct("=Bf"))),
+        ("f2", Array(Ptr("I", MemStr), 10)),
+        ("f3", Ptr("I", MemSelf)),
+        ("f4", Array(Ptr("I", MemSelf), 2)),
+        ("f5", Ptr("I", Ptr("I", MemSelf))),
+    ]
+
+# Other way to handle self dependency and circular dependencies
+# NOTE: in this case, MemSelf would have been fine
+UnhealthyIdeas.fields.append(
+    ("f6", Ptr("I", Ptr("I", Ptr("I", UnhealthyIdeas)))))
+# Regen all fields
+UnhealthyIdeas.gen_fields()
+
+ideas = UnhealthyIdeas(jitter.vm, addr7)
+ideas.memset()
+ideas.f3 = ideas.get_addr()
+assert ideas == ideas.deref_f3
+
+ideas.f4[0] = ideas.get_addr()
+assert ideas.f4.deref_get(0) == ideas
+ideas.f4[1] = addr6
+ideas.f4.deref_set(1, ideas)
+assert ideas.f4[1] != ideas.get_addr()
+assert ideas.f4.deref_get(1) == ideas
+
+ideas.f5 = addr2
+ideas.deref_f5.value = ideas.get_addr()
+assert ideas.deref_f5.value == ideas.get_addr()
+assert ideas.deref_f5.deref_value == ideas
+
+ideas.deref_f5.value = addr3
+ideas.deref_f5.deref_value = ideas
+assert ideas.deref_f5.value != ideas.get_addr()
+assert ideas.deref_f5.deref_value == ideas
+
+ideas.f6 = addr4
+ideas.deref_f6.value = addr5
+ideas.deref_f6.deref_value.value = ideas.get_addr()
+assert ideas.deref_f6.deref_value.deref_value == ideas
+
+# Cast tests
+# MemStruct cast
+MemInt = mem(Num("I"))
+MemShort = mem(Num("H"))
+dword = MemInt(jitter.vm, addr10)
+dword.value = 0x12345678
+assert isinstance(dword.cast(MemShort), MemShort)
+assert dword.cast(MemShort).value == 0x5678
+
+# Field cast
+ms2.s2[0] = 0x34
+ms2.s2[1] = 0x12
+assert ms2.cast_field("s2", MemShort).value == 0x1234
+
+# Other method
+assert MemShort(jitter.vm, ms2.get_addr("s2")).value == 0x1234
+
+# Manual cast inside an Array
+ms2.s2[4] = 0xcd
+ms2.s2[5] = 0xab
+assert MemShort(jitter.vm, ms2.s2.index2addr(4)).value == 0xabcd
+
+# void* style cast
+MemPtrVoid = mem(Ptr("I", MemVoid))
+MemPtrMyStruct = mem(Ptr("I", MyStruct))
+p = MemPtrVoid(jitter.vm, addr11)
+p.value = mstruct.get_addr()
+assert p.deref_value.cast(MyStruct) == mstruct
+assert p.cast(MemPtrMyStruct).deref_value == mstruct
+
+print "Some struct reprs:\n"
+print repr(mstruct), '\n'
+print repr(ms2), '\n'
+print repr(cont), '\n'
+print repr(uni), '\n'
+print repr(bit), '\n'
+print repr(bit), '\n'
+print repr(ideas), '\n'
+print repr(mem(Array(Inline(MyStruct2), 2))(jitter.vm, addr)), '\n'
+print repr(mem(Num("f"))(jitter.vm, addr)), '\n'
+print repr(memarray)
+print repr(memsarray)
+print repr(memstr)
+print repr(memstr3)
+
+print "Ok" # That's all folks!