manticore/tests/test_abi.py
feliam 520a9be47d Dev - events (#341)
* 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
2017-06-26 18:06:18 -03:00

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)