Reversing ARM Cortex-M Bit Band addresses

While reverse-engineering the firmware on the Digoo DG-HOSA device which I have a couple of posts on already. I ran across some memory addresses that did not directly map to peripherals. I found the address ranges are called the Bit-band range and had special functionality allowing direct access to individual bits on peripherals. This post will give a quick summary of what these addresses are and how to unmap them to the normal peripheral addresses.

What is Bit Banding?

The Bit Banding is a feature of the ARM Cortex-M3/M4 allowing you to directly access specific bits within the Peripheral and SRAM regions. Normally you need to write a whole register at a time even if you want to change a single bit. There are memory regions allocated for this purpose they are named “Bit band alias” in this snip of the Processor memory map table.

From Cortex-M3 Technical Reference

To calculate the Bit band address for a specific bit on a port you use the following formula. This formula is also found in the Cortex-M3 Technical reference.

bit_word_addr = bit_band_base + ((byte_offset x 32) + (bit_number × 4))

bit_word_offset – position of the target bit in the bit-band memory region.
bit_word_addr – address of the word in the alias memory region that maps to the targeted bit.
bit_band_base – starting address of the alias region.
byte_offset – number of the byte in the bit-band region that contains the targeted bit.
bit_number – bit position (0-7) of the targeted bit.

This was a quick introduction to bit banding if you are looking for more information check out his post which goes into great detail on this feature.

Now to reverse a bit mapped address

Now that we how to forward map an address I wrote up some python code that takes in the address, unmaps it, and lists the original port and register information.


def find_base_addr(bitmapped):
    if (0x22000000 < bitmapped and bitmapped < 0x23FFFFFF):
        bit_band_base = 0x22000000
        base_address = 0x20000000
    elif (0x42000000 < bitmapped and bitmapped < 0x43FFFFFF):
        bit_band_base = 0x42000000
        base_address = 0x40000000
        bit_band_base = 0
        base_address = 0
    return bit_band_base, base_address

def bitunmapper(bitmapped):
    bit_band_base, base_address = find_base_addr(bitmapped)
    unmap_port = int(((bitmapped - bit_band_base) & 0xfffff00) / 32)
    unmap_bits = int((bitmapped & 0x000000FF) / 4)
    if unmap_bits > 32:
        unmap_port += 0x4
        unmap_bits %= 32
    unmapped_address = base_address + int(unmap_port)
    print("Base Address: " + hex(unmapped_address))
    print("Port: " + hex(unmapped_address & 0xFFFFFF00))
    print("Register: " + hex(unmapped_address & 0x000000FF))
    print("Bit Map: " + str(int(unmap_bits)))

bitunmapper(0x42218188) # GPIOB 2
bitunmapper(0x42218198) # GPIOB 6

I have also created a Ghidra plugin using this code to quickly resolve these addresses when working through a binary. You can download it from this link:

Finally, here is a couple of screenshots of the plugin in action.

Enter Address
Results in the console

Compiling Ghidra Plugins

Recently I found a Ghidra plugin that did not have a build for the current version for Ghidra I was using, and this motivated me to figure out how to build a plugin from its source. After looking around, I did not find many writeups on building existing plugins. This writeup covers both building out the development environment that could be used for writing plugins and extending Ghidra itself and then how to compile the plugin.

Create Build Environment

The first thing you will need to do is create a development environment for compiling the plugin. I found this fantastic article from Void Start Security describing creating a Ghidra development environment using the ghidra-builder Docker container and helper scripts. I made a fork for the repo, integrating the article’s changes and other enhancements. This makes it pretty to create an image used moving forward. Here are the commands I used.

# Clone the repository
$ git clone
$ cd ghidra-builder
# Build the Docker image
$ docker-tpl/build

After the Docker image build completed, you will have two options building the plugin; you can build against the Dev source tree or the Public release. First, I will cover the Public build preparation steps.

Prepare for a Public Build

Building a plugin against the current Public build is pretty straightforward. First, you will download the current archive from the NSA Github and extract it to a folder you will create named out in the ghidra-builder folder structure. In my example, I saved the file to the ‘Downloads‘ folder in my home directory. The example commands I ran are:

# Starting in the root of the ghidra-builder folder
$ mkdir out && cd out 
# Downloaded the current Public release to Downloads
$ cp ~/Downloads/ .
$ unzip 

.... snip...

The following section covers creating a development archive of Ghidra.

Prepare for a Dev Build

To make a Dev build of a plugin, you will first need to make a development build of Ghidra. The script (part of this container) automatically clones from the GitHub repository, builds the source and places an archive in the out folder.

$ cd workdir
$ ../docker-tpl/run ./

After the build of Ghidra has been completed successfully, you will need to expand the archive created by the build into the out folder.

$ cd out/
$ ls
$ unzip 
   creating: ghidra_10.1.1_DEV/
... snip ...
  inflating: ghidra_10.1.1_DEV/Extensions/Ghidra/  
   creating: ghidra_10.1.1_DEV/Ghidra/Extensions/
$ cd ..

Now that we have the environment setup, we can build the plugin from its source.

Build the plugin

I initially found these instructions in wrongbaud’s posts about plugin development. In the out directory, you will need to clone or download the source of the plugin you are building. The connect to a shell in the Docker container and navigate into the source directory for the plugin. Then set the location of the Ghidra build’s directory you prepared earlier in a shell environment variable. Finally, execute the gradle command to build the plugin.

$ cd out
$ git clone
Cloning into 'gotools'...
remote: Enumerating objects: 146, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 146 (delta 0), reused 1 (delta 0), pack-reused 143
Receiving objects: 100% (146/146), 38.12 KiB | 424.00 KiB/s, done.
Resolving deltas: 100% (45/45), done.
$ ../docker-tpl/run /bin/bash
+++ dirname ../docker-tpl/run
++ cd ../docker-tpl
++ pwd
+ start_dir=/home/locutus/src/ghidra-builder/docker-tpl
+ build_command=/bin/bash
+ image=dukebarman/ghidra-builder
+ docker run -it -v /home/locutus/src/ghidra-builder/workdir:/files -w /files --user dockerbot:dockerbot --rm dukebarman/ghidra-builder sh -c /bin/bash
dockerbot@c7310895154d:/files$ cd gotools/
dockerbot@c7310895154d:/files/gotools$ export GHIDRA_INSTALL_DIR=/files/out/ghidra_10.1.1_DEV/
dockerbot@c7310895154d:/files/gotools$ gradle

Welcome to Gradle 7.3!

.... snip ....

7 actionable tasks: 7 executed
dockerbot@c7310895154d:/files/gotools$ ls dist/

Now you have built the plugin for the version of Ghidra! You can install the zip archive in the version of Ghidra you are running that you built for or are using.