Execution
The OcGraph application is a standalone application which tries to transforms disassembled binaries into a graphical visualization using the graphviz library. There are two different ways to execute the functionality, either by executing the tool on command line or inside python code as as module.
Command line
Synopsis
ocgraph [-h] [-f] [-d] [-a] [-c] [-s] [-t] [-v] [-o] [-l] [-lf]
Arguments
Required arguments
The command line interface supports many options, but at least three are necessary for a successful run:
- -f <filepath>, --file <filepath>
The path to the text file of the disassembled binary
- -d <preset>, --diss <preset>
The used disassembler name, currently available options are:
objdump
objdump-msp430
For all used architecture/disassembler combinations the default objdump implementation was appropriate, except for the MSP430.
- -d <preset>, --diss <preset>
The used architecture name, currently available options are:
ARM
PowerPC
MSP430
SPARCv8
x86
There are some extra arguments to configure some features.
CoverageReader
The Coverage-Reader reads
- -c <filepath>, --coverage <filepath>
The path to the coverage file. The only supported format is CSV.
- -s <address>, --start <address>
The start address of the function within the coverage file address space. Only use this option if the address space of the disassembly and the coverage file are different.
- -t <filetype>, --type <filetype>
Tell the coverage reader how the coverage file is formatted. Choices are OCCTRE or TSIM.
Drawer
The drawer is the internal module which draws the calculated graph structure. It is relies on the GraphViz ecosystem but the output option are limited to simplify the usage.
- -v, --view
The target output format is the generated dot format, instead of a pdf.
- -o <filepath>, --output <filepath>
The path to the output file.
Logger
The logger module enables the user to analyze the behavior
- -l <preset>, --logger <preset>
The selected preset, there are some pre-defined configurations available for the common scenarios:
- “default”: The default configuration if nothing is given:
write log messages at INFO-level
write sparse to console
write all to file (default is occtre.log)
- “module”: Minimum logging if used as module:
write log messages at ERROR-level
write nothing to file.
write sparse to console
- “development”: Extensive logging for development purposes:
write log messages at DEBUG-level
write all to console
write all to file (default is occtre.log)
- -o <filepath>, --output <filepath>
The path to the log file.
Batch update
#!/bin/bash
# SPDX-License-Identifier: GTDGmbH
# Sample function/labels inside the binary
function_array=(
atan2
fmin
sinf
fmaf
)
objdump=objdump
application=./qualification/code/app.exe
coverage_file=./qualification/code/app.exe.csv
asm_folder=./qualification/asm
pdf_folder=./qualification/pdf
mkdir -p $asm_folder
mkdir -p $pdf_folder
for i in "${function_array[@]}"
do
$objdump -d $application | sed -ne "/<$i>:/,/^$/p" > "$asm_folder/$i.asm"
poetry run ocgraph -c "$coverage_file" -d 'OBJDUMP' -a sparc -f "$asm_folder/$i.asm"
done
mv ./*.pdf "$pdf_folder/"
rm -f ./*.gv
Python module
Nominal case with all available options.
from ocgraph.interface import (
Analyzer,
CoverageReader,
Drawer,
Logger,
ArchitectureFactory,
DisassemblerFactory
)
# Preparation, create the
logger = Logger("default", "test.log")
diss = DisassemblerFactory.create("objdump")
arch = ArchitectureFactory.create("SPARCv8")
analyser = Analyzer(diss, arch, logger)
# Read in the lines
lines = read_lines("disassembled.txt")
analyser.parse_lines(lines)
# Add coverage information
cov_reader = CoverageReader(analyser.instructions, arch)
cov_reader.update_by_csv("coverage_file.csv", 0x0)
# Run the graph algorithm
analyser.analyze()
# Print result
drawer = Drawer(arch, logger)
drawer.draw_cfg(
analyser.function_name or "",
analyser.basic_blocks,
"output.pdf",
)