I am using ghidra to do some reverse engineering of an ARM binary. I am wondering whether there is a way to get the basic blocks related to all the listing. Is there a function through the IDE or a script through the script manager that I could used in order to get basic blocks at least within a function. Though I found scripts to decompile the binary I couldn't find a function that listed the basic blocks. Apart from ghidra is there any other reverse engineering tools that would help me to achieve this job? Thank you!
You can obtain the list of all defined basic blocks using BasicBlockModel
Example
from ghidra.program.model.block import BasicBlockModel
from ghidra.util.task import TaskMonitor
bbm = BasicBlockModel(currentProgram)
blocks = bbm.getCodeBlocks(TaskMonitor.DUMMY)
block = blocks.next()
while block:
print "Label: {}".format(block.name)
print "Min Address: {}".format(block.minAddress)
print "Max address: {}".format(block.maxAddress)
print
block = blocks.next()
Output
Label: LAB_0048b428
Min Address: 0048b428
Max address: 0048b43f
Label: httpStringPut
Min Address: 0048b440
Max address: 0048b46b
Label: 0048b46c
Min Address: 0048b46c
Max address: 0048b47f
Label: LAB_0048b480
Min Address: 0048b480
Max address: 0048b4b3
Label: httpBoundaryGet
Min Address: 0048b4c0
Max address: 0048b4cf
<snip>
Update
If you want to print disassembly of the basic blocks you can modify the script as
from ghidra.program.model.block import BasicBlockModel
from ghidra.util.task import TaskMonitor
def print_disassembly(block):
listing = currentProgram.getListing()
ins_iter = listing.getInstructions(block, True)
while ins_iter.hasNext():
ins = ins_iter.next()
print "{} {}".format(ins.getAddressString(False, True), ins)
bbm = BasicBlockModel(currentProgram)
blocks = bbm.getCodeBlocks(TaskMonitor.DUMMY)
block = blocks.next()
while block:
print_disassembly(block)
block = blocks.next()
print
Output
00409fcc lui gp,0xb
00409fd0 addiu gp,gp,0x68b4
00409fd4 addu gp,gp,t9
00409fd8 addiu sp,sp,-0x20
00409fdc sw gp,0x10(sp)
00409fe0 sw ra,0x1c(sp)
00409fe4 sw gp,0x18(sp)
00409fe8 bal 0x00409ff0
00409fec _nop
00409ff0 lui gp,0x4c
00409ff4 addiu gp,gp,0x880
00409ff8 lw t9,-0x7fe8(gp)
00409ffc nop
0040a000 addiu t9,t9,-0x5e80
0040a004 jalr t9
0040a008 _nop
0040a00c lw gp,0x10(sp)
0040a010 nop
0040a014 bal 0x0040a01c
0040a018 _nop
<snip>
-
-
Is there a method that could help me to get the assembly mnemonics that belong to each basic block?
block.getAddresses(True)
will give me an iterator, but what I need is a set of mnemonics that belong to the basic block – hEShaN Mar 20 '20 at 20:05 -
-
0xec has answered you but if you are interested in functions you can iterate as below
#TODO Lists Functions in a given program
#@author blabb
#@category _NEW_
funcs = currentProgram.getFunctionManager().getFunctions(True)
f1 = funcs.next()
print("Function Name",f1.getName())
print("Function Body" , f1.getBody())
print("Function Entry" , f1.getEntryPoint())
print("Functions Calls",f1.getCalledFunctions(ghidra.util.task.TaskMonitor.DUMMY))
print("Function is Called From",f1.getCallingFunctions(ghidra.util.task.TaskMonitor.DUMMY))
will result in details as below for the first function use hasnext() or while( next) to loop
functions.py> Running...
('Function Name', u'MmFreeIndependentPages')
('Function Body', [[140001010, 140001172] [1401d4c1a, 1401d4c8c] ])
('Function Entry', 140001010)
('Functions Calls', [MiReturnPoolCharges, MiPteInShadowRange, memset, MiIsPfnFromSlabAllocation,
MiWritePteShadow,MI_READ_PTE_LOCK_FREE,MiLockAndDecrementShareCount,MiReleasePtes, MiPteHasShadow])
('Function is Called From', [MmFreeIsrStack, FUN_14098fe9c, IopLiveDumpAllocateDumpBuffers,
IopLiveDumpWriteDumpFile, KiStartDynamicProcessor, IopLiveDumpWriteDumpFileWithHvPages,
HvlDeleteProcessor,IopLiveDumpFreeDumpBuffers,ExDeletePoolTagTable, HvlStartBootLogicalProcessors,
KeStartAllProcessors, HvlpInitializeHvCrashdump, IopLiveDumpReleaseResources])
@0xec's answer is great. This script will help you get blocks function wise.
from ghidra.program.model.block import BasicBlockModel
blockiterator = BasicBlockModel(currentProgram).getCodeBlocks(monitor)
# dictionary contains function wise basic block information
functions = {}
def add_block(function, block):
if function not in functions:
functions[function] = []
functions[function].append(block)
# For each block, look through the function list until we find a match
while blockiterator.hasNext():
cur_block = blockiterator.next().getMinAddress()
function = getFirstFunction()
found = False
# Search functions until we find a match or run out of functions
while function is not None:
b = function.getBody()
if b.contains(cur_block):
add_block(function.getName(), cur_block)
found=True
break
# Update function to next and loop again
function = getFunctionAfter(function)
# Done searching functions. If we never found it, add to unknown list
if not found:
add_block("_unknown", cur_block)
print(functions)