Warning
The documentation for envi hasn’t been touched yet! If you want to contribute (or have ideas for better documentation), feel free to send me a pull request or email me.
The Envi framework allows architecutre abstraction through the use of the ArchitectureModule, Opcode, Operand, and Emulator objects.
Bases: envi.EnviException
Raised by various Envi components when the architecture does not implement that envi component.
An architecture module implementes methods to deal with the creation of envi objects for the specified architecture.
Return a python string of the byte sequence which corresponds to a breakpoint (if present) for this architecture.
Bases: envi.EmuException
Raised by an emulator when you execute a breakpoint instruction
Bases: envi.Operand
Bases: envi.EmuException
Raised by an Emulator when a divide/mod has a 0 divisor...
Bases: envi.EnviException
A parent for all emulation exceptions so catching them can be easy.
Bases: envi.registers.RegisterContext, envi.memory.MemoryObject
The Emulator class is mostly “Abstract” in the java Interface sense. The emulator should be able to be extended for the architecutures which are included in the envi framework. You must mix in an instance of your architecture abstraction module.
(NOTE: Most users will just use an arch mod and call getEmulator())
The intention is for “light weight” emulation to be implemented mostly for user-space emulation of protected mode execution.
Emulator implementors can implement this method to allow analysis modules a platform/architecture independant way to get stack/reg/whatever args.
Usage: getCallArgs(3, “stdcall”) -> (0, 32, 0xf00)
Return the data needed to “snapshot” this emulator. For most archs, this method will be enough (it takes the memory object, and register values with it)
Return the address that an operand which deref’s memory would read from on getOperValue().
Return the value for the operand at index idx for the given opcode reading memory and register states if necissary.
In partially-defined emulation, this may return None
The default segmentation is none (most arch’s will over-ride). This method may be implemented to return a segment index based on either emulator state or properties of the particular instruction in question.
Run the emulator until “something” happens. (breakpoint, segv, syscall, etc...)
Set the value of the target operand at index idx from opcode op. (obviously OM_IMMEDIATE cannot be set)
Bases: envi.Operand
Bases: envi.EnviException
Raised by opcode parsers when the specified bytes do not represent a valid opcode
Bases: envi.EnviException
Raised when adding a memory map to a MemoryObject which overlaps with another already existing map.
A universal representation for an opcode
Return a list of tuples. Each tuple contains the target VA of the branch, and a possible set of flags showing what type of branch it is.
See the BR_FOO types for all the supported envi branch flags.... Example: for bva,bflags in op.getBranches():
Get the name of the prefixes associated with the specified architecture specific prefix bitmask.
Thses are the expected methods needed by any implemented operand object attached to an envi Opcode. This does not have a constructor of it’s pwn on purpose to cut down on memory use and constructor CPU cost.
If the operand is a “dereference” operand, this method should use the specified op/emu to resolve the address of the dereference.
Bases: envi.EmuException
This exception is used in partially defined emulation to signal where execution flow becomes un-known due to undefined values. This is considered un-recoverable.
Bases: envi.EmuException
This exception is raised when a conditional operation is dependant on a flag state that is unknown.
Bases: envi.Operand
Bases: envi.EnviException
Raised by an Emulator extension when you bad-touch memory. (Likely from memobj).
Bases: envi.EmuException
Raised when the getCallArgs() or setReturnValue() methods are given an unknown calling convention type.
Bases: envi.EmuException
Raised by emulators when the given instruction is not implemented by the emulator.
A file full of bit twidling helpers
Return a string of one’s and zero’s for the given value.
Parse bitsize bits from the bit offset bitoff beginning at offset bytes.
Example:
Mostly for pulling immediates out of strings...
A byte and mask based decision engine for creating byte sequences (and potential comparison masks) for general purpose signature matching.
Currently used by vivisect function entry sig db and others.
A byte based decision tree which uses all the RAMs but is really fast....
Signatures consist of a byte sequence and an optional mask sequence. If present each mask byte is used to logical and the byte being compared before comparison. This allows the creation of signatures which have parts of the sig generalized.
FIXME allow sigs to have a reliability rating FIXME allow sig nodes to store depth and truncate the tree early (and then mask the rest)
Unified CLI code for things like vivisect and vdb.
This is used to work around the difference between functions and bound methods for extended command modules
Bases: cmd.Cmd
Add an alias to the command line interpreter’s aliases dictionary
Usage: alias <alias_word> rest of the alias command To delete an alias: Usage: alias <alias_word>
Display a binary representation of the given value expression (padded to optional width in bits)
Usage: binstr <val_expr> [<bitwidth_expr>]
Show or edit a config option from the command line
Usage: config [-S section] [option=value]
Evaluate an expression on the CLI to show it’s value.
Usage: eval (ecx+edx)/2
Display either a list of all the memory maps or the memory map details for the given address expression.
Usage: maps [addr_expression]
Show some memory (with optional formatting and size)
Usage: mem [-F <format>] <addr expression> [size]
NOTE: use -F ? for a list of the formats
Compare memory at the given locations. Outputs a set of differences showing bytes at their given offsets....
Usage: memcmp <addr_expr1> <addr_expr2> <size_expr>
Dump memory out to a file.
Usage: memdump <addr_expression> <size_expression> <filename>
Start an interactive python interpreter. The namespace of the interpreter is updated with expression nicities. You may also specify a line of python code as an argument to be exec’d without beginning an interactive python interpreter on the controlling terminal.
Usage: python [pycode]
Execute a python file.
The script file is arbitrary python code which is run with the full compliment of expression extensions mapped in as locals.
Usage: script <scriptfile> [<argv[0]>, ...]
Search memory for patterns.
Usage: search [options] <pattern> -e Encode the pattern with a codec (ie utf-16le, hex, etc) -E The specified pattern is an expression (search for numeric values) -r The specified pattern is a regular expression -R <baseexpr:sizeexpr> Search a specific range only. -X The specified pattern is in hex (ie. 414141424242 is AAABBB)
Over-ride this to have things like the eval command and the python command use more locals than the sybolic defaults.
Do your best to create a humon readable name for the value of this pointer.
Set a new canvas for the CLI and add all the current renderers to the new one.
Bases: envi.cli.EnviCli
Cli extensions which require a mutable memory object (emulator/trace) rather than a static one (viv workspace)
Copy memory from one location to another...
Usage: memcpy <dest_expr> <src_expr> <size_expr>
A module to contain code flow analysis for envi opcode objects...
Bases: object
A CodeFlowContext is used for code-flow (not linear) based disassembly for an envi MemoryObject (which is responsible for knowing the implementation of parseOpcode(). The CodeFlowContext will optionally notify several callback handlers for different events which occur during disassembly:
self._cb_function(fva, metadict) - called once for every function
self._cb_branchtable(tabva, destva) - called for switch tables
Do code flow disassembly from the specified address. Returnes a list of the procedural branch targets discovered during code flow...
Set persist=True to store ‘opdone’ and never disassemble the same thing twice Set exptable=True to expand branch tables in this phase
Analyze the given procedure entry point and flow downward to find all subsequent code blocks and procedure edges.
Unified config object for all vtoys.
Unified expression helpers.
Bases: dict
An object to act as the locals dictionary for the evaluation of envi expressions. You may pass in an envi.resolver.SymbolResolver object to automagically use symbols in your expressions.
Bases: envi.expression.ExpressionLocals
The expression ispoi(value) returns True if the specified value is a valid pointer. Otherwise, False.
The expression mapbase(address) returns the base address of the memory mapped area containing “address”
The expression maplen(address) returns the length of the memory mapped area containing “address”.
This is the interface spec (and a few helper utils) for the unified memory object interface.
NOTE: If your actual underlying memory format is such that over-riding anything (like isValidPointer!) can be faster than the default implementation, DO IT!
Starts at the current EIP (self.getProgramCounter()), and searches each instruction for the instruction requested.
Returns the address of the first found opcode, than returns.
Example: # Find the first ‘popad’ opcode
In [1]: popad_loc = trace.findOpcode(opcode=”popad”,verbose=True) [+] 0x1020cd0L pushad [+] 0x1020cd1L mov esi,0x0101a000 [+] 0x1020cd6L lea edi,dword [esi - 102400] [+] 0x1020cdcL push edi [+] 0x1020cddL or ebp,0xffffffff –SNIP– [+] 0x1020e49L push edi [+] 0x1020e4aL call ebp [+] 0x1020e4cL pop eax [+] 0x1020e4dL popad Location - 0x01020E4D
# Or you can do it simply
#TODO Extend to take in expressions.
Return a tuple of mapva,size,perms,filename for the memory map which contains the specified address (or None).
Parse an opcode from the specified virtual address.
Example: op = m.parseOpcode(0x7c773803)
Check to be sure that the given virtual address and size is contained within one memory map, and check that the perms are contained within the permission bits for the memory map. (MM_READ | MM_WRITE | MM_EXEC | ...)
Example probeMemory(0x41414141, 20, envi.memory.MM_WRITE) (check if the memory for 20 bytes at 0x41414141 is writable)
Change the protections for the given memory map. On most platforms the va/size must exactly match an existing memory map.
Read memory from the specified virtual address for size bytes and return it as a python string.
Example: mem.readMemory(0x41414141, 20) -> “A...”
A quick cheater way to searchMemoryRange() for each of the current memory maps.
Search the specified memory range (address -> size) for the string needle. Return a list of addresses where the match occurs.
A file like object to wrap around a memory object.
Bases: envi.memory.IMemory
An optimized routine which returns the existing segment bytes sequence without creating a new string object AND an offset of va into the buffer. Used internally for optimized memory handling. Returns (offset, bytes)
Take a memory snapshot which may be restored later.
Example: snap = mem.getMemorySnap()
Return the human readable name for a single memory perm enumeration value.
A home for the page lookup construct. Basically it is a python object which implements a similar lookup mechanism to the i386 page table lookups...
Similar to the memory subsystem, this is a unified way to access information about objects which contain registers
Meta registers are registers which are really just directly addressable parts of already existing registers (eax -> al).
To add a meta register, you give the name, the idx of the real register, the width of the meta reg, and it’s left shifted (in bits) offset into the real register value. The RegisterContext will take care of accesses after that.
Return the appropriate realreg, shift, mask info for the specified metareg idx (or None if it’s not meta).
Get a register index by name. (faster to use the index multiple times)
Return an object which can be stored off, and restored to re-initialize a register context. (much like snapshot but it takes the definitions with it)
Return a list of all the “real” (non meta) registers and their indexes.
Example: for regname, regidx in x.getRegisterNameIndexes():
Return the width of the register which lives at the specified index (width is always in bits).
Get all the real registers from this context as a dictionary of name value pairs.
Returns true if registers in this context have been modififed since their import.
Load a register definition. A register definition consists of a list of tuples with the following format: (regname, regwidth)
NOTE: All widths in envi RegisterContexts are in bits.
Load a set of defined “meta” registers for this architecture. Meta registers are defined as registers who exist as a subset of the bits in some other “real” register. The argument metas is a list of tuples with the following format: (regname, reg_shift_offset, reg_width) The given example is for the AX register in the i386 subsystem regname: “ax” reg_shift_offset: 0 reg_width: 16
This may be used to allow a register context to provide extended repr (flags breakouts, etc) info about a register.
Use this to bulk restore the register state.
The API describing what it means to be an envi compliant symbol resolver.
Bases: envi.resolver.Symbol, envi.resolver.SymbolResolver
A file symbol is both a symbol resolver of it’s own, and a symbol.
File symbols are used to do heirarchal symbol lookups and don’t actually add anything but the name to their lookup (it is assumed that the parent Resolver of the FileSymbol takes care of addr lookups.
Bases: envi.resolver.Symbol
Used to represent functions.
Bases: envi.resolver.Symbol
Used for file sections/segments.
NOTE: Nothing should reach directly into a SymbolResolver!
May be used by symbol resolvers who know what type they are resolving to store and retrieve “hints” with indexes.
Used specifically by opcode render methods to resolve any memory dereference info for a given operand.
A couple useful thread related toys...