Build a debugger in 5 minutes (1/5)

Let’s tap into the internals of native processes with our own custom-made debugger.

Prerequisites

We will build a simple, interactive debugger with a Qml-based GUI on top of the Frida cross-platform instrumentation toolkit. The debugger will inject code into processes to be debugged. We’ll leverage frida-qml, Frida’s Qml plugin. I would recommend downloading the prebuilt binary for Mac or the prebuilt binary for Windows to get up and running quickly. And by the way, remember to download Qt 5.3 first. Just create a “Frida” directory in your Qt installation’s qml plugin directory and pop in the three files you just downloaded. On Mac this is typically “~/Qt/5.3/clang_64/qml/Frida/”, and on Windows it’s “C:\Qt\5.3\msvc2013\qml\Frida\”. If you’re on Linux you will have to build the plugin yourself for now — just follow the Frida build instructions and proceed to building frida-qml the standard Qt way (qmake && make).

Create the project

First, let’s fire up Qt Creator and create a new project. Use the “Qt Quick UI” template in the “Applications” category. Name it “geoshark” and go ahead with default settings for the remaining steps. We’ll now have some boilerplate code generated by Qt Creator:

Our canvas is ready

Inject some code

Let’s inject some code, shall we? First, let’s import the Frida plugin by adding this line below the other imports:

import Frida 1.0

Frida lets us inject JavaScript into any process, and these scripts have access to a quite comprehensive API. But let’s start with something really simple — let’s just have the remote process write something to stdout. Inside “ApplicationWindow”, add a “Script” object:

Script {

id: script

source: "console.log('Hello from Frida!');"

}

So that’s our script, just sitting there. Let’s take our “Hello World” button and make it do something useful:

Button {

text: qsTr("Inject")

anchors.horizontalCenter: parent.horizontalCenter

anchors.verticalCenter: parent.verticalCenter

onClicked: {

Frida.localSystem.inject(script, 1234);

}

}

The important line here is the injection of the script:

Frida.localSystem.inject(script, 1234);

The first argument is the script from above, and the second is the process ID. We’ll fill in this later.

If you’re on Mac or Linux, fire up “/bin/cat” in a terminal and let’s use that as our guinea pig. If you’re on Windows you can run “more” in a cmd shell. Then just replace “1234” with the process ID of the guinea pig.

The code should now look like this:

View diff

It’s showtime! Hit that “Run” button:

Voilà!

Observe the terminal as you hit the “Inject” button, and watch the magic:

That concludes the first minute of our five-minute tutorial.

Next part