1
2 """
3 The Envi framework allows architecutre abstraction through
4 the use of the ArchitectureModule, Opcode, Operand, and
5 Emulator objects.
6 """
7
8 import types
9 import struct
10 import platform
11
12
13 IF_NOFALL = 0x01
14 IF_PRIV = 0x02
15 IF_CALL = 0x04
16 IF_BRANCH = 0x08
17 IF_RET = 0x10
18
19
20 BR_PROC = 1<<0
21 BR_COND = 1<<1
22 BR_DEREF = 1<<2
23 BR_TABLE = 1<<3
24 BR_FALL = 1<<4
25
26 import envi.bits as e_bits
27 import envi.memory as e_mem
28 import envi.registers as e_reg
29 import envi.memcanvas as e_canvas
30
32 """
33 An architecture module implementes methods to deal
34 with the creation of envi objects for the specified
35 architecture.
36 """
37 - def __init__(self, archname, maxinst=32):
38 self._arch_name = archname
39 self._arch_maxinst = maxinst
40
42 """
43 Return a python string of the byte sequence which corresponds to
44 a breakpoint (if present) for this architecture.
45 """
46 raise ArchNotImplemented("archGetBreakInstr")
47
49 """
50 Return an initialized register context object for the architecture.
51 """
52 raise ArchNotImplemented("archGetRegCtx")
53
55 """
56 Create a new opcode from the specified bytes (beginning
57 at the specified offset)
58 """
59 raise ArchNotImplemented("makeOpcode")
60
62 """
63 Return a default instance of an emulator for the given arch.
64 """
65 raise ArchNotImplemented("getEmulator")
66
68 """
69 Get the size of a pointer in memory on this architecture.
70 """
71 raise ArchNotImplemented("getPointerSize")
72
74 """
75 Return a string representation for a pointer on this arch
76 """
77 raise ArchNotImplemented("pointerString")
78
80 '''
81 Used by objects which are expected to inherit from an
82 architecture module but don't know which one until runtime!
83 '''
84 arch = getArchModule(archname)
85 for name in dir(arch):
86 o = getattr(arch, name, None)
87 if type(o) == types.MethodType:
88 setattr(obj, name, o)
89
93
95 """
96 Raised by opcode parsers when the specified
97 bytes do not represent a valid opcode
98 """
104
106 """
107 Raised by an Emulator extension when you
108 bad-touch memory. (Likely from memobj).
109 """
115
117 """
118 Raised by various Envi components when the architecture
119 does not implement that envi component.
120 """
121 pass
122
124 """
125 A parent for all emulation exceptions so catching
126 them can be easy.
127 """
131
133 return "%s at %s" % (self.__class__.__name__, hex(self.va))
134
136 """
137 Raised by emulators when the given instruction
138 is not implemented by the emulator.
139 """
143
145 return "Unsupported Instruction: 0x%.8x %s" % (self.va, repr(self.op))
146
148 """
149 Raised by an Emulator when a divide/mod has
150 a 0 divisor...
151 """
152
154 """
155 Raised by an emulator when you execute a breakpoint instruction
156 """
157
159 """
160 This exception is raised when a conditional operation is dependant on
161 a flag state that is unknown.
162 """
163
165 """
166 This exception is used in partially defined emulation to signal where
167 execution flow becomes un-known due to undefined values. This is considered
168 un-recoverable.
169 """
170
172 """
173 Raised when the getCallArgs() or setReturnValue() methods
174 are given an unknown calling convention type.
175 """
176
178 """
179 Raised when adding a memory map to a MemoryObject which overlaps
180 with another already existing map.
181 """
183 self.map1 = map1
184 self.map2 = map2
185 margs = (map1[0], map1[1], map2[0], map2[1])
186 EnviException.__init__(self, "Map At 0x%.8x (%d) overlaps map at 0x%.8x (%d)" % margs)
187
189
190 """
191 Thses are the expected methods needed by any implemented operand object
192 attached to an envi Opcode. This does *not* have a constructor of it's
193 pwn on purpose to cut down on memory use and constructor CPU cost.
194 """
195
197 """
198 Get the current value for the operand. If needed, use
199 the given emulator/workspace/trace to resolve things like
200 memory and registers.
201
202 NOTE: This API may be passed a None emu and should return what it can
203 (or None if it can't be resolved)
204 """
205 print "%s needs to implement getOperValue!" % self.__class__.__name__
206 return None
207
209 """
210 Set the current value for the operand. If needed, use
211 the given emulator/workspace/trace to assign things like
212 memory and registers.
213 """
214 print("%s needs to implement setOperValue! (0x%.8x: %s) " % (self.__class__.__name__, op.va, repr(op)))
215
217 """
218 If the given operand will dereference memory, this method must return True.
219 """
220 return False
221
223 '''
224 If the given operand represents an immediate value, this must return True.
225 '''
226 return False
227
229 '''
230 If the given operand represents a register value, this must return True.
231 '''
232 return False
233
235 """
236 If the operand is a "dereference" operand, this method should use the
237 specified op/emu to resolve the address of the dereference.
238
239 NOTE: This API may be passed a None emu and should return what it can
240 (or None if it can't be resolved)
241 """
242 print("%s needs to implement getOperAddr!" % self.__class__.__name__)
243 return None
244
245 - def repr(self, op):
246 """
247 Used by the Opcode class to get a humon readable string for this operand.
248 """
249 return "unknown"
250
251 - def render(self, mcanv, op, idx):
252 """
253 Used by the opcode class when rendering to a memory canvas.
254 """
255 mcanv.addText(self.repr(op))
256
258 return not op == self
259
261 if not isinstance(oper, self.__class__):
262 return False
263
264 return True
265
270
275
280
282 """
283 A universal representation for an opcode
284 """
285 prefix_names = []
286
287 - def __init__(self, va, opcode, mnem, prefixes, size, operands, iflags=0):
288 """
289 constructor for the basic Envi Opcode object. Arguments as follows:
290
291 opcode - An architecture specific numerical value for the opcode
292 mnem - A humon readable mnemonic for the opcode
293 prefixes - a bitmask of architecture specific instruction prefixes
294 size - The size of the opcode in bytes
295 operands - A list of Operand objects for this opcode
296 iflags - A list of Envi (architecture independant) instruction flags (see IF_FOO)
297 va - The virtual address the instruction lives at (used for PC relative immediates etc...)
298
299 NOTE: If you want to create an architecture spcific opcode, I'd *highly* recommend you
300 just copy/paste in the following simple initial code rather than calling the parent
301 constructor. The extra
302 """
303 self.opcode = opcode
304 self.mnem = mnem
305 self.prefixes = prefixes
306 self.size = size
307 self.opers = operands
308 self.repr = None
309 self.iflags = iflags
310 self.va = va
311
313 return not op == self
314
316 if not isinstance(op, Opcode):
317 return False
318 if self.opcode != op.opcode:
319 return False
320 if self.mnem != op.mnem:
321 return False
322 if self.size != op.size:
323 return False
324 if self.iflags != op.iflags:
325 return False
326 if len(self.opers) != len(op.opers):
327 return False
328 for i in range(len(self.opers)):
329 if self.opers[i] != op.opers[i]:
330 return False
331 return True
332
334 return int(hash(self.mnem) ^ (self.size << 4))
335
337 """
338 Over-ride this if you want to make arch specific repr.
339 """
340 return self.mnem + " " + ",".join([o.repr(self) for o in self.opers])
341
343 return int(self.size)
344
345
346
347
349 """
350 Return a list of tuples. Each tuple contains the target VA of the
351 branch, and a possible set of flags showing what type of branch it is.
352
353 See the BR_FOO types for all the supported envi branch flags....
354 Example: for bva,bflags in op.getBranches():
355 """
356 return ()
357
359 """
360 Render this opcode to the memory canvas passed in. This is used for both
361 simple printing AND more complex representations.
362 """
363 mcanv.addText(repr(self))
364
366 """
367 Get the name of the prefixes associated with the specified
368 architecture specific prefix bitmask.
369 """
370 ret = []
371 for byte,name in self.prefix_names:
372 if self.prefixes & byte:
373 ret.append(name)
374 return "".join(ret)
375
379
381 return list(self.opers)
382
383 -class Emulator(e_reg.RegisterContext, e_mem.MemoryObject):
384 """
385 The Emulator class is mostly "Abstract" in the java
386 Interface sense. The emulator should be able to
387 be extended for the architecutures which are included
388 in the envi framework. You *must* mix in
389 an instance of your architecture abstraction module.
390
391 (NOTE: Most users will just use an arch mod and call getEmulator())
392
393 The intention is for "light weight" emulation to be
394 implemented mostly for user-space emulation of
395 protected mode execution.
396 """
398
399 e_mem.MemoryObject.__init__(self, archmod=archmod)
400 e_reg.RegisterContext.__init__(self)
401
402 self._emu_segments = [ (0, 0xffffffff), ]
403 self._emu_call_convs = {}
404
405
406
407
408
409
410 self.op_methods = {}
411 for name in dir(self):
412 if name.startswith("i_"):
413 self.op_methods[name[2:]] = getattr(self, name)
414
416 raise Exception('Emulators *must* implement getArchModule()!')
417
419 """
420 Return the data needed to "snapshot" this emulator. For most
421 archs, this method will be enough (it takes the memory object,
422 and register values with it)
423 """
424 regs = self.getRegisterSnap()
425 mem = self.getMemorySnap()
426 return regs,mem
427
432
438
439 - def run(self, stepcount=None):
440 """
441 Run the emulator until "something" happens.
442 (breakpoint, segv, syscall, etc...)
443 """
444 if stepcount != None:
445 for i in xrange(stepcount):
446 self.stepi()
447 else:
448 while True:
449 self.stepi()
450
455
459
461 """
462 The *default* segmentation is none (most arch's will over-ride).
463 This method may be implemented to return a segment index based on either
464 emulator state or properties of the particular instruction in question.
465 """
466 return 0
467
469 '''
470 Set a base and size for a given segment index.
471 '''
472 if len(self._emu_segments) - idx == 0:
473 self._emu_segments.append( (base, size) )
474 return
475
476 self._emu_segments[idx] = (base,size)
477
479 """
480 Return the value for the operand at index idx for
481 the given opcode reading memory and register states if necissary.
482
483 In partially-defined emulation, this may return None
484 """
485 oper = op.opers[idx]
486 return oper.getOperValue(op, self)
487
489 """
490 Return the address that an operand which deref's memory
491 would read from on getOperValue().
492 """
493 oper = op.opers[idx]
494 return oper.getOperAddr(op, self)
495
497 """
498 Set the value of the target operand at index idx from
499 opcode op.
500 (obviously OM_IMMEDIATE *cannot* be set)
501 """
502 oper = op.opers[idx]
503 return oper.setOperValue(op, self, value)
504
506 """
507 Emulator implementors can implement this method to allow
508 analysis modules a platform/architecture independant way
509 to get stack/reg/whatever args.
510
511 Usage: getCallArgs(3, "stdcall") -> (0, 32, 0xf00)
512 """
513 c = self._emu_call_convs.get(cc, None)
514 if c == None:
515 raise UnknownCallingConvention(cc)
516
517 return c.getCallArgs(self, count)
518
520 """
521 Emulator implementors can implement this method to allow
522 analysis modules a platform/architecture independant way
523 to set a function return value. (this should also take
524 care of any argument cleanup or other return time tasks
525 for the calling convention)
526 """
527 c = self._emu_call_convs.get(cc, None)
528 if c == None:
529 raise UnknownCallingConvention(cc)
530
531 return c.setReturnValue(self, value, argc)
532
534 self._emu_call_convs[name] = obj
535
537 if self._emu_call_convs.get(name) != None:
538 return True
539 return False
540
542 return self._emu_call_conv.get(name)
543
545 return self._emu_call_convs.items()
546
548 """
549 Implement calling conventions for your arch.
550 """
553
556
557
559 raise Exception('getSymbolikArgs() not in %s' % self.__class__.__name__)
560
562 raise Exception('setSymbolikReturn() not in %s' % self.__class__.__name__)
563
564
565
566
567 arch_xlate_32 = {
568 'i386':'i386',
569 'i486':'i386',
570 'i586':'i386',
571 'i686':'i386',
572 'x86':'i386',
573 'i86pc':'i386',
574 '':'i386',
575 'AMD64':'i386',
576 }
577
578 arch_xlate_64 = {
579 'x86_64':'amd64',
580 'AMD64':'amd64',
581 'amd64':'amd64',
582 'i386':'amd64',
583 '':'amd64',
584 }
585
587 """
588 Return an envi normalized name for the current arch.
589 """
590 width = struct.calcsize("P")
591 mach = platform.machine()
592
593 if width == 4:
594 ret = arch_xlate_32.get(mach)
595
596 elif width == 8:
597 ret = arch_xlate_64.get(mach)
598
599 if ret == None:
600 raise ArchNotImplemented(mach)
601
602 return ret
603
605 """
606 return an Envi architecture module instance for the following
607 architecture name.
608
609 Current architectures include:
610
611 i386 - Intel i386
612 amd64 - The new 64bit AMD spec.
613 """
614 if name == None:
615 name = getCurrentArch()
616
617
618 if name in ["i386","i486","i586","i686","x86"]:
619 import envi.archs.i386 as e_i386
620 return e_i386.i386Module()
621
622 elif name == "amd64":
623 import envi.archs.amd64 as e_amd64
624 return e_amd64.Amd64Module()
625
626 elif name == 'arm':
627 import envi.archs.arm as e_arm
628 return e_arm.ArmModule()
629
630 else:
631 raise ArchNotImplemented(name)
632