-
Notifications
You must be signed in to change notification settings - Fork 471
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make unicorn be pull-based #97
Conversation
5fc8ec6
to
dadeb66
Compare
dadeb66
to
4451c56
Compare
fccc3f8
to
0e13c9c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spectacularly awesome, true hero power!
I still need to review the _to_raise / _should_try_again logic.
manticore/core/cpu/abstractcpu.py
Outdated
try: | ||
implementation = getattr(self, name) | ||
except AttributeError as ae: | ||
logger.debug("UNIMPLEMENTED INSTRUCTION: 0x%016x:\t%s\t%s\t%s", instruction.address, ' '.join(map(lambda x: '%02x'%x, instruction.bytes)), instruction.mnemonic, instruction.op_str) | ||
# Make sure we're referencing the instruction look up | ||
if name not in ae.message: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or...
if hasattr(self.name): raise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have any strong thoughts on this? One argument for the current situation is not having an instruction is an exceptional situation, not normal control flow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class B(object):
def two(self):
return 2
class A(object):
def one(self):
b = B()
return b.one()
a = A()
try :
a.one()
except Exception,e:
print "'one' in e:", 'one' in e.message
print e
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant :
if hasattr(self.name):
instead of:
if name not in ae.message:
manticore/core/memory.py
Outdated
@@ -403,6 +403,9 @@ def page_mask(self): | |||
def maps(self): | |||
return self._maps | |||
|
|||
def map_of_address(self, address): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not used?
$ grep map_of_address . -Rn
./manticore/core/memory.py:406: def map_of_address(self, address):
manticore/utils/emulate.py
Outdated
self._emu = self._unicorn() | ||
|
||
# Copy in the concrete values of all needed registers. | ||
registers = set(self._cpu.canonical_registers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to at least document that ...
Ideally here we should only concretize registers that are going to be used/read. Otherwise we may destroy a lot of symbolic state that we don't need to.
There is some support for this in Capstone.instruction..regs_access()
Attempted here:
https://github.com/trailofbits/manticore/blob/dev-fix-unicorn/manticore/core/cpu/abstractcpu.py#L416-L432
manticore/utils/emulate.py
Outdated
val = self._cpu.read_register(reg) | ||
if issymbolic(val): | ||
from ..core.cpu.abstractcpu import ConcretizeRegister | ||
raise ConcretizeRegister(reg, "Concretizing register for emulation.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lookout this will use default concretization policy (I think MINMAX?).
10 symbolic regs will spawn... a lot of states?
We should consider adding a policy='ONE' here.
Policy 'ONE' does not exist.
manticore/core/cpu/arm.py
Outdated
@@ -277,26 +277,26 @@ def __setstate__(self, state): | |||
self._last_flags = state['_last_flags'] | |||
self._force_next = state['_force_next'] | |||
|
|||
def _concretize_registers(cpu, instruction): | |||
def _concretize_registers(self, instruction): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not used, was left from your code. Okay to remove and then re-add once we capstone adds the functionality?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes remove everywhere and lets re implement it when needed, if needed
manticore/core/cpu/abstractcpu.py
Outdated
@@ -544,18 +454,21 @@ class Syscall(CpuInterrupt): | |||
def __init__(self): | |||
super(Syscall, self).__init__("CPU Syscall") | |||
|
|||
# TODO(yan): Move this into State or a more appropriate location | |||
_ValidPolicies = ['MINMAX', 'ALL', 'SAMPLED', 'ONE'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes it sound like we need a base Concretize(Exception).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
manticore/utils/emulate.py
Outdated
# XXX(yan): We might need to raise here | ||
pass | ||
|
||
if logger.getEffectiveLevel() == logging.DEBUG: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logger.isEnabledFor()
might be the preferred api here https://docs.python.org/2/howto/logging.html#optimization
manticore/utils/emulate.py
Outdated
uc.mem_map(address & ~0xFFF, 0x1000) | ||
|
||
from ..core.cpu.abstractcpu import InvalidPCException | ||
self._to_raise = InvalidPCException(address) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we know we are trying to execute from address?
Also normally provide the mapping for the current single instruction executed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That mapping gets added/memory brought in on line 191. And the offending address is a param to the hook
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can it be the case we are executing on not mapped memory if we provide a map for the initial emulation and we emulate only 1 instruction?
Also how do you discern READ from EXECUTE ? Can't that access be a buggy operand trying to access those arm special addresses ?
manticore/utils/emulate.py
Outdated
from ..core.cpu.abstractcpu import InvalidPCException | ||
self._to_raise = InvalidPCException(address) | ||
else: | ||
self._to_raise = MemoryException("Can't read at", address) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't X86 et.al also raise an exception here? (I may be seeing the indentation wrong)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will, just the line above is a bit redundant. MemoryException will be raised on line 220 if we return False from here. I'll remove the above line during next cleanup.
manticore/utils/emulate.py
Outdated
self._should_try_again = False | ||
return False | ||
|
||
# XXX(yan): handle if this points to an incorrect mapping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah no. Here is where we should check the mcore maps and raise if not mapped there.
manticore/utils/emulate.py
Outdated
|
||
try: | ||
m = self._create_emulated_mapping(uc, address, size) | ||
except: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we filter for specific exceptions here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch (updating now)
).decode('hex') | ||
|
||
# Map a TLS segment | ||
self._arm_tls_memory = cpu.memory.mmap(None, 4, 'rw ') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not only tls in this memory, it's "kernel user helper memory" technically, so i think a rename would make it more accurate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is only TLS memory though. What else can be in it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, my mistake, should have read more closely :(
manticore/utils/emulate.py
Outdated
|
||
def _step(self, instruction): | ||
''' | ||
A single attempt at execution an instruction. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo
manticore/utils/emulate.py
Outdated
if saved_PC == mu_pc: | ||
self._cpu.PC = saved_PC + instruction.size | ||
|
||
# Raise the exception from a hook that Uniocrn would have eaten |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo
|
||
#Unicorn hack. On single step unicorn wont advance the PC register | ||
mu_pc = self.get_unicorn_pc() | ||
if saved_PC == mu_pc: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A jump to self may be a problem here (if Unicorn actually wont update the pc for that one)
No description provided.