5

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!

3 Answers 3

6

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>
2
  • 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, 2020 at 20:05
  • @hEShaN Check updated answer.
    – 0xec
    Mar 20, 2020 at 21:38
5

@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)
0
4

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])
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.