Setting up PwnDbg with Ghidra

3 minute read

If you’re like me and more used to Windows tooling (even if you have Linux experience) it is a little difficult to setup some of this more complicated Rizin tooling. So, thought I would make a quick guide about setting up Pwndbg with Ghidra.

As a WinDbg use, despite having used gdb before it has a lot of quirks. Quirks which are as easy to get used to as quirks that exist in WinDbg. I also found that gdb is just more of a pain in the ass to use. Luckily, pwndbg helps a lot with using gdb.

Installing PwnDbg

Setting up Pwndbg is the super easy part, simply clone the repo and run the setup.sh script.

git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh

Installing radare2

Again, installing radare2 is super simple;

git clone https://github.com/radareorg/radare2
radare2/sys/install.sh

Installing rizin

I had some issues with building rizin. In order to install it you can follow these commands;

git clone https://github.com/rizinorg/rizin
meson build
ninja -C build

There is one final command you have to use, which is the one I had issues with.

[rizin]$ ninja -C build install                                                                                                                                                      [dev]
ninja: Entering directory `build'
[0/1] Installing files.
Installing subdir /opt/rizin/librz/cons/d/. to /usr/local/share/rizin/0.3.0-git/cons/.
Installation failed due to insufficient permissions.
Attempting to use polkit to gain elevated privileges...
Traceback (most recent call last):
  File "/home/linxz/.local/bin/meson", line 5, in <module>
    from mesonbuild.mesonmain import main
ModuleNotFoundError: No module named 'mesonbuild'
FAILED: meson-install 
/home/linxz/.local/bin/meson install --no-rebuild
ninja: build stopped: subcommand failed.

This happened despite me having meson installed and working. In order to solve this I did the following;

[rizin]$ sudo -i                                                                                                                                                                     [dev]
root@linxz:~# python3 -m pip install meson
Collecting meson
  Downloading meson-0.59.1.tar.gz (1.9 MB)
     |████████████████████████████████| 1.9 MB 4.7 MB/s 
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
Building wheels for collected packages: meson
  Building wheel for meson (PEP 517) ... done
  Created wheel for meson: filename=meson-0.59.1-py3-none-any.whl size=807872 sha256=d6f32750ddb3ddc0f3ec4e52a99e007400ac202d9d16d708461abbfd163260ed
  Stored in directory: /root/.cache/pip/wheels/7f/b0/ab/46cbdb8d0ef8705cb742c3418c858cfafc95ca907f045b4441
Successfully built meson
Installing collected packages: meson
Successfully installed meson-0.59.1
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
root@linxz:~# exit

After doing that and running [rizin]$ ninja -C build install again, it worked. No idea why…

rz-pm

rz-pm is built into r2, however, I had some issues using it to get packages. Namely for some reason, even if I had a package installed, it kept asking me to install it. So I used the .sh script instead and placed it in my /opt directory.

wget https://github.com/rizinorg/rizin/blob/dev/binrz/rz-pm/rz-pm

Installing rz-ghidra

[/opt]$ sudo rz-pm -i rz-ghidra

I also wanted the cutter part, for that you’ll also need to build rz-ghidra as well.

git clone https://github.com/rizinorg/rz-ghidra.git

git submodule init
git submodule update

mkdir build && cd build
cmake -DBUILD_CUTTER_PLUGIN=ON -DCUTTER_SOURCE_DIR=/my/path/cutter -DCMAKE_INSTALL_PREFIX=~/.local ..
make && make install

Testing R2-Ghidra

[space]$ r2 space

[0x08049080]> s main
[0x080491cf]> pdg

// WARNING: Variable defined which should be unmapped: var_8h
// WARNING: [r2ghidra] Var argv is stack pointer based, which is not supported for decompilation.

undefined4 main(void)

{
    int32_t unaff_EBX;
    undefined auStack47 [4];
    int32_t var_27h;
    undefined *puStack16;
    int32_t var_8h;
    
    puStack16 = &stack0x00000004;
    sym.__x86.get_pc_thunk.bx();
    sym.imp.printf(unaff_EBX + 0xe22);
    sym.imp.fflush(**(undefined4 **)(unaff_EBX + 0x20da));
    sym.imp.read(0, auStack47, 0x1f);
    sym.vuln((int32_t)auStack47);
    return 0;
}
[0x080491cf]> 

Great, it works!

Testing Ghidra in Pwndbg!

You need to make sure you add the context to the pwndbg window. You can do this using set context-ghidra. I am using for the purpose of this set context-ghidra always but it does consume a lot of resources so configure it so that it only works when there is source code.

yay, works.

Hope this helps… Keep in mind. I am using tmux with pwndbg. Instructions for that can be found on the pwndbg repo.