* Wip refactoring * Executor and exceptions refactor wip wip * Fixing all_insts auto tests * Visited and generate testcase now at manticore api level * Aggregating state statistics into executor statistics * Wip refactoring * Executor and exceptions refactor wip wip * Fixing all_insts auto tests * Visited and generate testcase now at manticore api level * Aggregating state statistics into executor statistics * forwarding events wip * state setstate fix and setup_stack merge fix * will_terminate_state fix and tests skipped * Update all ConcretizeRegister and ConcretizeMemory * Wip refactoring * Executor and exceptions refactor wip wip * Fixing all_insts auto tests * Visited and generate testcase now at manticore api level * Aggregating state statistics into executor statistics * Wip refactoring * Executor and exceptions refactor wip wip * Fixing all_insts auto tests * Visited and generate testcase now at manticore api level * Aggregating state statistics into executor statistics * forwarding events wip * state setstate fix and setup_stack merge fix * will_terminate_state fix and tests skipped * Update all ConcretizeRegister and ConcretizeMemory * Exceptions are crazy crazy crazy * fix last merge * Merge merge until it pass * Instructions count default to 0 * will/did execute/emulate * Delayed keybpoard interrupt now shutdowns nicely * fix auto test generator x86 * Undo bad merge * utterly hopeless * basic working * Fix merge bugs and github comments * Remove unnecesary comment - github comments * trace_item not used there * model-platform and system.py fixed * backup/restore to store/load -- cpu.instruction property * Slightly better did/will naming and dynamic signal forwarding * platform.constraints and cpu.instruction as properties * Fix forward signals getattr * set las decoded pc at decode_instruction() / reenable instruction_cache * Signals name convention: did/will/on * Forward normal signals * Maintain last decoded pc in abstractcpu * Changed context manager so it just wont raise interrupt * Decree now forwards signals and sets constraints * linux.SymbolicFile does not need to maintain constraints * remove debbug print * Assimilating some PR commets * size_total == size * better merge of manticore.py * typo * Forwarding only specified objects in signal arguments * Fix few broken tests * revert + merge * remove some unused stuff from manticore() * manticore context <-> executor context * manticore context <-> executor context2 * context context context * forgotten return * Fix basix.arm * arm bitwise fix * fix context * Comment 1 * Comment 2 * Comment 3 * Comment 4 * Comment 5 * Comment 6 * Fix (still needs refactor but it works) profiling * Fix (still needs refactor but it works) profiling * The forgotten bit * Update tests to reflect current output * Verbosity fix * Fix verbosity test
431 lines
12 KiB
Python
431 lines
12 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import unittest
|
|
import sys
|
|
import shutil
|
|
import tempfile
|
|
import os
|
|
import hashlib
|
|
import subprocess
|
|
import collections
|
|
import time
|
|
|
|
from manticore import Manticore, issymbolic
|
|
from manticore import variadic
|
|
from manticore.core.smtlib import BitVecVariable
|
|
from manticore.core.cpu.abstractcpu import ConcretizeArgument, ConcretizeRegister, ConcretizeMemory
|
|
from manticore.core.cpu.arm import Armv7Cpu, Armv7LinuxSyscallAbi, Armv7CdeclAbi
|
|
from manticore.core.cpu.x86 import I386Cpu, AMD64Cpu, I386LinuxSyscallAbi, I386StdcallAbi, I386CdeclAbi, AMD64LinuxSyscallAbi, SystemVAbi
|
|
from manticore.core.memory import SMemory32, Memory32, SMemory64
|
|
from manticore.core.smtlib import ConstraintSet, Operators
|
|
|
|
class ABITests(unittest.TestCase):
|
|
_multiprocess_can_split_ = True
|
|
def setUp(self):
|
|
mem32 = SMemory32(ConstraintSet())
|
|
mem32.mmap(0x1000, 0x1000, 'rw ')
|
|
mem64 = SMemory64(ConstraintSet())
|
|
mem64.mmap(0x1000, 0x1000, 'rw ')
|
|
|
|
self._cpu_arm = Armv7Cpu(mem32)
|
|
self._cpu_arm.SP = 0x1080
|
|
self._cpu_arm.func_abi = Armv7CdeclAbi(self._cpu_arm)
|
|
self._cpu_arm.syscall_abi = Armv7LinuxSyscallAbi(self._cpu_arm)
|
|
|
|
self._cpu_x86 = I386Cpu(mem32)
|
|
self._cpu_x86.ESP = 0x1080
|
|
self._cpu_x86.func_abi = I386CdeclAbi(self._cpu_x86)
|
|
self._cpu_x86.syscall_abi = I386LinuxSyscallAbi(self._cpu_x86)
|
|
|
|
self._cpu_x64 = AMD64Cpu(mem64)
|
|
self._cpu_x64.RSP = 0x1080
|
|
self._cpu_x64.func_abi = SystemVAbi(self._cpu_x64)
|
|
self._cpu_x64.syscall_abi = AMD64LinuxSyscallAbi(self._cpu_x64)
|
|
|
|
def write(mem, where, val, size):
|
|
mem[where:where+size/8] = [Operators.CHR(Operators.EXTRACT(val, offset, 8)) for offset in xrange(0, size, 8)]
|
|
for val in range(0, 0x100, 4):
|
|
write(mem32, 0x1000+val, val, 32)
|
|
for val in range(0, 0x100, 8):
|
|
write(mem64, 0x1000+val, val, 64)
|
|
|
|
def test_executor(self):
|
|
pass
|
|
|
|
def test_arm_abi_simple(self):
|
|
cpu = self._cpu_arm
|
|
|
|
for i in range(4):
|
|
cpu.write_register('R{}'.format(i), i)
|
|
|
|
cpu.LR = 0x1234
|
|
|
|
def test(one, two, three, four):
|
|
self.assertEqual(one, 0)
|
|
self.assertEqual(two, 1)
|
|
self.assertEqual(three, 2)
|
|
self.assertEqual(four, 3)
|
|
return 34
|
|
|
|
cpu.func_abi.invoke(test)
|
|
|
|
# result is correctly captured
|
|
self.assertEquals(cpu.R0, 34)
|
|
# sp is unchanged
|
|
self.assertEquals(cpu.SP, 0x1080)
|
|
# returned correctly
|
|
self.assertEquals(cpu.PC, cpu.LR)
|
|
|
|
def test_arm_abi(self):
|
|
cpu = self._cpu_arm
|
|
|
|
for i in range(4):
|
|
cpu.write_register('R{}'.format(i), i)
|
|
|
|
cpu.LR = 0x1234
|
|
|
|
self.assertEqual(cpu.read_int(cpu.SP), 0x80)
|
|
|
|
def test(one, two, three, four, five, six, seven):
|
|
self.assertEqual(one, 0)
|
|
self.assertEqual(two, 1)
|
|
self.assertEqual(three, 2)
|
|
self.assertEqual(four, 3)
|
|
self.assertEqual(five, 0x80)
|
|
self.assertEqual(six, 0x84)
|
|
self.assertEqual(seven, 0x88)
|
|
|
|
self.assertEqual(cpu.SP, 0x1080)
|
|
return 34
|
|
|
|
cpu.func_abi.invoke(test)
|
|
|
|
# result is correctly captured
|
|
self.assertEquals(cpu.R0, 34)
|
|
# sp is unchanged
|
|
self.assertEquals(cpu.SP, 0x1080)
|
|
# returned correctly
|
|
self.assertEquals(cpu.PC, cpu.LR)
|
|
|
|
def test_arm_abi_concretize_register(self):
|
|
cpu = self._cpu_arm
|
|
|
|
for i in range(4):
|
|
cpu.write_register('R{}'.format(i), i)
|
|
|
|
previous_r0 = cpu.R0
|
|
self.assertEqual(cpu.read_int(cpu.SP), 0x80)
|
|
|
|
def test(one, two, three, four, five, six):
|
|
raise ConcretizeArgument(cpu, 0)
|
|
|
|
with self.assertRaises(ConcretizeRegister) as cr:
|
|
cpu.func_abi.invoke(test)
|
|
|
|
self.assertEquals(cpu.R0, previous_r0)
|
|
self.assertEquals(cr.exception.reg_name, 'R0')
|
|
self.assertEquals(cpu.SP, 0x1080)
|
|
|
|
def test_arm_abi_concretize_memory(self):
|
|
cpu = self._cpu_arm
|
|
|
|
for i in range(4):
|
|
cpu.write_register('R{}'.format(i), i)
|
|
|
|
previous_r0 = cpu.R0
|
|
self.assertEqual(cpu.read_int(cpu.SP), 0x80)
|
|
|
|
def test(one, two, three, four, five):
|
|
raise ConcretizeArgument(cpu, 4)
|
|
|
|
with self.assertRaises(ConcretizeMemory) as cr:
|
|
cpu.func_abi.invoke(test)
|
|
|
|
self.assertEquals(cpu.R0, previous_r0)
|
|
self.assertEquals(cr.exception.address, cpu.SP)
|
|
self.assertEquals(cpu.SP, 0x1080)
|
|
|
|
def test_i386_cdecl(self):
|
|
cpu = self._cpu_x86
|
|
|
|
base = cpu.ESP
|
|
|
|
self.assertEqual(cpu.read_int(cpu.ESP), 0x80)
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
def test(one, two, three, four, five):
|
|
self.assertEqual(one, 0x80)
|
|
self.assertEqual(two, 0x84)
|
|
self.assertEqual(three, 0x88)
|
|
self.assertEqual(four, 0x8c)
|
|
self.assertEqual(five, 0x90)
|
|
return 3
|
|
|
|
cpu.func_abi.invoke(test)
|
|
|
|
self.assertEquals(cpu.EAX, 3)
|
|
self.assertEquals(base, cpu.ESP)
|
|
self.assertEquals(cpu.EIP, 0x1234)
|
|
|
|
def test_i386_stdcall(self):
|
|
cpu = self._cpu_x86
|
|
|
|
base = cpu.ESP
|
|
|
|
bwidth = cpu.address_bit_size / 8
|
|
self.assertEqual(cpu.read_int(cpu.ESP), 0x80)
|
|
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
def test(one, two, three, four, five):
|
|
self.assertEqual(one, 0x80)
|
|
self.assertEqual(two, 0x84)
|
|
self.assertEqual(three, 0x88)
|
|
self.assertEqual(four, 0x8c)
|
|
self.assertEqual(five, 0x90)
|
|
return 3
|
|
|
|
abi = I386StdcallAbi(cpu)
|
|
abi.invoke(test)
|
|
|
|
self.assertEquals(cpu.EAX, 3)
|
|
self.assertEquals(base + bwidth * 5, cpu.ESP)
|
|
self.assertEquals(cpu.EIP, 0x1234)
|
|
|
|
def test_i386_stdcall_concretize(self):
|
|
cpu = self._cpu_x86
|
|
|
|
bwidth = cpu.address_bit_size / 8
|
|
self.assertEqual(cpu.read_int(cpu.ESP), 0x80)
|
|
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
eip = 0xDEADBEEF
|
|
base = cpu.ESP
|
|
cpu.EIP = eip
|
|
def test(one, two, three, four, five):
|
|
raise ConcretizeArgument(cpu, 2)
|
|
|
|
abi = I386StdcallAbi(cpu)
|
|
with self.assertRaises(ConcretizeMemory) as cr:
|
|
abi.invoke(test)
|
|
|
|
# Make sure ESP hasn't changed if exception was raised
|
|
self.assertEquals(base, cpu.ESP)
|
|
# Make sure EIP hasn't changed (i.e. return value wasn't popped)
|
|
self.assertEquals(cpu.EIP, eip)
|
|
|
|
def test_i386_cdecl_concretize(self):
|
|
cpu = self._cpu_x86
|
|
|
|
base = cpu.ESP
|
|
prev_eax = 0xcc
|
|
cpu.EAX = prev_eax
|
|
|
|
self.assertEqual(cpu.read_int(cpu.ESP), 0x80)
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
def test(one, two, three, four, five):
|
|
raise ConcretizeArgument(cpu, 0) # 0x1068
|
|
return 3
|
|
|
|
with self.assertRaises(ConcretizeMemory) as cr:
|
|
cpu.func_abi.invoke(test)
|
|
|
|
# Make sure we're concretizing
|
|
self.assertEquals(cr.exception.address, 0x1080)
|
|
# Make sure eax is unchanged
|
|
self.assertEquals(cpu.EAX, prev_eax)
|
|
# Make sure EIP wasn't popped
|
|
self.assertEquals(base, cpu.ESP+4)
|
|
self.assertNotEquals(cpu.EIP, 0x1234)
|
|
|
|
|
|
def test_i386_vararg(self):
|
|
cpu = self._cpu_x86
|
|
|
|
cpu.push(3, cpu.address_bit_size)
|
|
cpu.push(2, cpu.address_bit_size)
|
|
cpu.push(1, cpu.address_bit_size)
|
|
|
|
# save return
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
@variadic
|
|
def test(params):
|
|
for val, idx in zip(params, range(1, 4)):
|
|
self.assertEqual(val, idx)
|
|
|
|
cpu.func_abi.invoke(test)
|
|
self.assertEquals(cpu.EIP, 0x1234)
|
|
|
|
|
|
def test_amd64_basic_funcall(self):
|
|
cpu = self._cpu_x64
|
|
|
|
cpu.RDI = 1
|
|
cpu.RSI = 2
|
|
cpu.RDX = 3
|
|
cpu.RCX = 4
|
|
cpu.R8 = 5
|
|
cpu.R9 = 6
|
|
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
def test(one, two, three, four, five, six):
|
|
self.assertEqual(one, 1)
|
|
self.assertEqual(two, 2)
|
|
self.assertEqual(three, 3)
|
|
self.assertEqual(four, 4)
|
|
self.assertEqual(five, 5)
|
|
self.assertEqual(six, 6)
|
|
|
|
cpu.func_abi.invoke(test)
|
|
|
|
self.assertEqual(cpu.RIP, 0x1234)
|
|
|
|
def test_amd64_reg_mem_funcall(self):
|
|
cpu = self._cpu_x64
|
|
|
|
cpu.RDI = 1
|
|
cpu.RSI = 2
|
|
cpu.RDX = 3
|
|
cpu.RCX = 4
|
|
cpu.R8 = 5
|
|
cpu.R9 = 6
|
|
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
def test(one, two, three, four, five, six, seven, eight):
|
|
self.assertEqual(one, 1)
|
|
self.assertEqual(two, 2)
|
|
self.assertEqual(three, 3)
|
|
self.assertEqual(four, 4)
|
|
self.assertEqual(five, 5)
|
|
self.assertEqual(six, 6)
|
|
self.assertEqual(seven, 0x80)
|
|
self.assertEqual(eight, 0x88)
|
|
|
|
cpu.func_abi.invoke(test)
|
|
|
|
self.assertEqual(cpu.RIP, 0x1234)
|
|
|
|
def test_amd64_basic_funcall_concretize(self):
|
|
cpu = self._cpu_x64
|
|
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
def test(one, two, three, four, five, six):
|
|
raise ConcretizeArgument(cpu, 0)
|
|
|
|
with self.assertRaises(ConcretizeRegister) as cr:
|
|
cpu.func_abi.invoke(test)
|
|
|
|
# Should not update RIP
|
|
self.assertNotEqual(cpu.RIP, 0x1234)
|
|
self.assertEquals(cr.exception.reg_name, 'RDI')
|
|
|
|
def test_amd64_vararg(self):
|
|
cpu = self._cpu_x64
|
|
|
|
cpu.RDI = 0
|
|
cpu.RSI = 1
|
|
cpu.RDX = 2
|
|
|
|
# save return
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
@variadic
|
|
def test(params):
|
|
for val, idx in zip(params, range(3)):
|
|
self.assertEqual(val, idx)
|
|
|
|
cpu.func_abi.invoke(test)
|
|
|
|
self.assertEquals(cpu.RIP, 0x1234)
|
|
|
|
def test_i386_syscall(self):
|
|
cpu = self._cpu_x86
|
|
|
|
cpu.EAX = 5
|
|
for idx, reg in enumerate(['EBX', 'ECX', 'EDX', 'ESI', 'EDI', 'EBP']):
|
|
cpu.write_register(reg, idx)
|
|
|
|
def test(one, two, three, four, five, six):
|
|
self.assertEqual(one, 0)
|
|
self.assertEqual(two, 1)
|
|
self.assertEqual(three, 2)
|
|
self.assertEqual(four, 3)
|
|
self.assertEqual(five, 4)
|
|
self.assertEqual(six, 5)
|
|
return 34
|
|
|
|
self.assertEqual(cpu.syscall_abi.syscall_number(), 5)
|
|
|
|
cpu.syscall_abi.invoke(test)
|
|
|
|
self.assertEqual(cpu.EAX, 34)
|
|
|
|
def test_amd64_syscall(self):
|
|
cpu = self._cpu_x64
|
|
|
|
cpu.RAX = 5
|
|
for idx, reg in enumerate(['RDI', 'RSI', 'RDX', 'R10', 'R8', 'R9']):
|
|
cpu.write_register(reg, idx)
|
|
|
|
def test(one, two, three, four, five, six):
|
|
self.assertEqual(one, 0)
|
|
self.assertEqual(two, 1)
|
|
self.assertEqual(three, 2)
|
|
self.assertEqual(four, 3)
|
|
self.assertEqual(five, 4)
|
|
self.assertEqual(six, 5)
|
|
return 34
|
|
|
|
self.assertEqual(cpu.syscall_abi.syscall_number(), 5)
|
|
|
|
cpu.syscall_abi.invoke(test)
|
|
|
|
self.assertEqual(cpu.RAX, 34)
|
|
|
|
def test_test_prefix(self):
|
|
cpu = self._cpu_x86
|
|
|
|
cpu.push(2, cpu.address_bit_size)
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
def test(prefix, extracted):
|
|
self.assertEquals(prefix, 1)
|
|
self.assertEquals(extracted, 2)
|
|
|
|
cpu.func_abi.invoke(test, prefix_args=(1,))
|
|
|
|
self.assertEquals(cpu.EIP, 0x1234)
|
|
|
|
def test_fail_concretize_prefix_arg(self):
|
|
cpu = self._cpu_x86
|
|
|
|
def test(prefix, extracted):
|
|
raise ConcretizeArgument(cpu, 0)
|
|
|
|
with self.assertRaises(AssertionError) as cr:
|
|
cpu.func_abi.invoke(test, prefix_args=(1,))
|
|
|
|
def test_funcall_method(self):
|
|
cpu = self._cpu_x86
|
|
|
|
cpu.push(2, cpu.address_bit_size)
|
|
cpu.push(1, cpu.address_bit_size)
|
|
cpu.push(0x1234, cpu.address_bit_size)
|
|
|
|
class Kls(object):
|
|
def method(self, a, b):
|
|
return a+b
|
|
|
|
obj = Kls()
|
|
result = cpu.func_abi.invoke(obj.method)
|
|
|
|
self.assertEquals(result, 3)
|
|
|