viv-utils
viv-utils (version 0.8.1) is a Python library providing utilities for binary analysis, specifically designed to complement vivisect. It offers helper functions and abstractions for common tasks like extracting information from vivisect workspaces, navigating control flow graphs, and working with function metadata. Its release cadence is somewhat infrequent, driven by the needs of its primary developers and the broader vivisect ecosystem.
Common errors
-
ModuleNotFoundError: No module named 'vivisect_v8'
cause The `vivisect_v8` package, a core dependency, is not installed or not accessible.fixInstall the required vivisect package: `pip install vivisect-v8` -
AttributeError: 'NoneType' object has no attribute 'arch'
cause You likely passed `None` instead of a `vivisect.VivWorkspace` object to `viv_utils.api.from_vivisect()`.fixEnsure `vw` in `viv_api.from_vivisect(vw)` is an actual, initialized `vivisect.VivWorkspace` instance, not `None`. -
AttributeError: 'VivWorkspace' object has no attribute 'getVivTaint'
cause An older or incomplete `vivisect` installation might be missing methods required by `viv_utils.emulator.VivEmulator`.fixUpgrade `vivisect_v8` to the latest version (`pip install --upgrade vivisect-v8`). If you have conflicting `vivisect` installations, remove the older ones.
Warnings
- breaking Starting with `viv-utils` v0.8.0, the library explicitly requires `vivisect_v8>=1.0.0`. Older versions of `vivisect` (e.g., those installed directly from GitHub without the `_v8` suffix or prior to `vivisect_v8`'s release) are no longer compatible.
- gotcha The `viv_utils` API relies on a fully analyzed `vivisect.VivWorkspace` object. If the underlying workspace (`vw`) has not been properly loaded from a binary and `vw.analyze()` called, many `viv-utils` methods like `get_functions()` or `get_function()` might return empty results or raise `AttributeError` if attempting to access unpopulated fields.
- gotcha Some functionalities, especially related to emulation (`viv_utils.emulator.VivEmulator`), might expect specific methods or data structures to be present in the `vivisect.VivWorkspace` object or its internal components. Using a partially initialized or very old `vivisect` workspace can lead to `AttributeError`.
Install
-
pip install viv-utils
Imports
- from_vivisect
import viv_utils; viv_utils.from_vivisect(...)
from viv_utils.api import from_vivisect
- VivEmulator
from viv_utils import VivEmulator
from viv_utils.emulator import VivEmulator
Quickstart
import viv_utils.api as viv_api
from unittest.mock import MagicMock
# --- Start Minimal Mock for Demonstrative vivisect Workspace ---
# In a real scenario, 'vw' would be an actual vivisect.VivWorkspace
# loaded with a binary and analyzed (e.g., vw.loadFromFile("path/to/binary"); vw.analyze()).
class MockVivWorkspace:
def __init__(self):
self.arch = "amd64" # Required by viv_utils
self._functions = {
0x1000: {"name": "entry_point", "blocks_count": 3},
0x1050: {"name": "utility_func", "blocks_count": 2},
}
def getMetaInfo(self, key, default=None):
# viv_utils queries meta info, e.g., 'Platform'
return {"Platform": "windows"}.get(key, default)
def getFunctions(self):
return list(self._functions.keys())
def getFunction(self, va):
if va not in self._functions:
return None
# viv_utils expects specific attributes on the function object
func_data = self._functions[va]
mock_func = MagicMock()
mock_func.va = va
mock_func.name = func_data["name"]
mock_func.basic_blocks = [MagicMock() for _ in range(func_data["blocks_count"])] # Simulate basic blocks
mock_func.getBasicBlocks.return_value = {0x1000: (0x10, 5)} # dummy for internal access if needed
return mock_func
def getComments(self, va): return None # Often queried
def getCodeBlocks(self): return [] # Often queried
def getVivTaint(self): return MagicMock() # For emulator, though not used in this quickstart
vw = MockVivWorkspace()
# --- End Minimal Mock ---
# Wrap the mock vivisect workspace with viv-utils API
utils_workspace = viv_api.from_vivisect(vw)
print("Listing functions from the viv-utils wrapped workspace:")
for func in utils_workspace.get_functions():
print(f" Function VA: {hex(func.va)}, Name: '{func.name}', Basic Blocks: {len(func.basic_blocks)}")
# Example: Access a specific function by VA
target_va = 0x1050
target_func = utils_workspace.get_function(target_va)
if target_func:
print(f"\nDetails for function '{target_func.name}' at {hex(target_func.va)}:")
print(f" Number of basic blocks: {len(target_func.basic_blocks)}")
else:
print(f"\nFunction at {hex(target_va)} not found.")