Ghidra: Scripting: any way to force not to create a basic block on CALL?

Created on 29 Jul 2019  路  2Comments  路  Source: NationalSecurityAgency/ghidra

Hello,
when we look at the "program graph" of a function, we can see basic blocks containing CALL instruction, which means that CALL does not create a new basic block. However, when getting an iterator using API, we always get basic blocks that are created with CALL too. For example,

```
sbm=SimpleBlockModel(currentProgram, False)
function = getFirstFunction()
while function is not None:
entry_addr=function.getEntryPoint()
blocks=sbm.getCodeBlocksContaining(function.getBody(), monitor)
while (blocks.hasNext()):
bb = blocks.next();
dest=bb.getDestinations(monitor)
while (dest.hasNext()):
dbb = dest.next();
print "\t[*] 0x%x:" % dbb.getDestinationAddress().getOffset()
function = getFunctionAfter(function)

```When we run the above code, we also get target destination (for getDestinationAddress().getOffset()) that are CALL to other functions and then the code iterate on those functions.
Any suggestions?

ScriptinPython Question

Most helpful comment

Hey thanks for submitting this issue @tosanjay. I didn't realize there were differences between SimpleBlockModel and BasicBlockModel. Switching from simple to basic solved part of my problem as well. As you've stated, for some reason when iterating over basic blocks, we're getting the root basic block from any calls.

Until this is resolved, I've been using getFunctionAt() to determine if the destination block is the result of a call. getFunctionAt() is useful because it returns None (python) if the address provided is not the entry point of a function. So we can use it to ignore basic blocks we don't want. Here's an example:

from ghidra.program.model.block import BasicBlockModel
from ghidra.util.task import ConsoleTaskMonitor

funcName = 'main'
blockModel = BasicBlockModel(currentProgram)
monitor = ConsoleTaskMonitor()
func = getGlobalFunctions(funcName)[0]

print("Basic block details for function '{}':".format(funcName))
blocks = blockModel.getCodeBlocksContaining(func.getBody(), monitor)

# print first block
print("\t[*] {} ".format(func.getEntryPoint()))

# print any remaining blocks
while(blocks.hasNext()):
    bb = blocks.next()
    dest = bb.getDestinations(monitor)
    while(dest.hasNext()):
        dbb = dest.next()
        if not getFunctionAt(dbb.getDestinationAddress()):
            print("\t[*] {} ".format(dbb))

Here's the output of my target binary:

Basic block details for function 'main':
    [*] 00100690 
    [*] 001006b1 -> 00100700 
    [*] 001006fc -> 00100700 
    [*] 00100709 -> 001006b3 
    [*] 00100709 -> 0010070b 

If anyone has a better way to do this, please let me know. Thanks!

All 2 comments

I think I got the answer by reading a bt more into the API doc. if we use BasicBlockModel(), we get what I asked for. HOwever, on a closer look, I found another problem: For a given function, I am getting references that are not contained in the function! any idea what happens when we use function.getBody() ?

Hey thanks for submitting this issue @tosanjay. I didn't realize there were differences between SimpleBlockModel and BasicBlockModel. Switching from simple to basic solved part of my problem as well. As you've stated, for some reason when iterating over basic blocks, we're getting the root basic block from any calls.

Until this is resolved, I've been using getFunctionAt() to determine if the destination block is the result of a call. getFunctionAt() is useful because it returns None (python) if the address provided is not the entry point of a function. So we can use it to ignore basic blocks we don't want. Here's an example:

from ghidra.program.model.block import BasicBlockModel
from ghidra.util.task import ConsoleTaskMonitor

funcName = 'main'
blockModel = BasicBlockModel(currentProgram)
monitor = ConsoleTaskMonitor()
func = getGlobalFunctions(funcName)[0]

print("Basic block details for function '{}':".format(funcName))
blocks = blockModel.getCodeBlocksContaining(func.getBody(), monitor)

# print first block
print("\t[*] {} ".format(func.getEntryPoint()))

# print any remaining blocks
while(blocks.hasNext()):
    bb = blocks.next()
    dest = bb.getDestinations(monitor)
    while(dest.hasNext()):
        dbb = dest.next()
        if not getFunctionAt(dbb.getDestinationAddress()):
            print("\t[*] {} ".format(dbb))

Here's the output of my target binary:

Basic block details for function 'main':
    [*] 00100690 
    [*] 001006b1 -> 00100700 
    [*] 001006fc -> 00100700 
    [*] 00100709 -> 001006b3 
    [*] 00100709 -> 0010070b 

If anyone has a better way to do this, please let me know. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Barakat picture Barakat  路  3Comments

marcushall42 picture marcushall42  路  3Comments

ghost picture ghost  路  3Comments

lab313ru picture lab313ru  路  3Comments

tambry picture tambry  路  3Comments