Part 15 - Debugging double

Let's review 0x06_double.c as follows.

#include <stdio.h>
#include "pico/stdlib.h"

int main() 
{
  stdio_init_all();

  while(1) 
  {
    double x = 40.5;

    printf("%f\n", x); 

    sleep_ms(1000);
  }

  return 0;
}

Let's fire up in our debugger.

radare2 -w arm -b 16 0x06_double.elf

Let's auto analyze.

aaaa

Let's seek to main.

s main

Let's go into visual mode by typing V and then p twice to get to a good debugger view.

We see the format specifier in [0x0000033c].

:> psz @ [0x0000033c]
%f

The double is at [0x00000340].

:> pff @ [0x00000340]
0x00004000 = 9.32830524e-09

Ok... Same deal as the float lesson so why did I waste time on choosing 40.5?

I wanted to show you definitive proof that the compiler will treat this the same as it is within the bounds of a float when the Pico SDK functionality does it's magic as there is NO co-processor.

Let's examine a MOD to our program.

#include <stdio.h>
#include "pico/stdlib.h"

int main() 
{
  stdio_init_all();

  while(1) 
  {
    double x = 40.55555555555555555555;

    printf("%.16f\n", x) 

    sleep_ms(1000);
  }

  return 0;
}

When we compile and run this program we get the following.

40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000

OK well... This looks different. Let us for the first time in this course look at a Dynamic Reverse Engineering analysis in GDB.

It is NOT critical here that you run this and set this all up in GDB as there are a great deal of steps in addition to another Pico needed in a configuration such as the following below.

The scope of this course is to understand Static Reverse Engineering however I wanted to depart and show you what GDB is showing us with this new binary.

It is NOT necessary to use Dynamic Reverse Engineering unless you are dealing with a situation where you have a packed binary that you have to dynamically load and write out the code. It does make things easier when you are using Dynamic Reverse Engineering however I want to show you that Static Reverse Engineering can get you everything you need without having to set up a remote process to actually run the binary on.

If you did find it necessary to try this you would need to first install the OpenOCD repo into the pico folder that we created at the beginning of this course. You can find details at the link below and go to 5.1 Installing OpenOCD in the datasheet.

https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf

You will then need to visit the page below and download the uf2 located at Debugging using another Raspberry Pi Pico and then flash the first Pico with the uf2.

https://www.raspberrypi.org/documentation/rp2040/getting-started/\#board-specifications

TERMINAL 1: You will then need to set up a first terminal to go into the openocd folder and run the following.

src/openocd -f interface/picoprobe.cfg -f target/rp2040.cfg -s tcl

TERMINAL 2: You will need to go into the build folder of your project and run the following.

arm-none-eabi-gdb 0x06_double.elf
target extended-remote localhost:3333
load
monitor reset init
b main
c

TERMINAL 3: You will need to run the screen emulator which will start with a blinking cursor.

screen /dev/tty.usbmodem14101 115200

Nonetheless with that brief explanation, lets' review this dynamically in GDB.

We see two values at 0x10000340 and 0x10000344.

Let's delete all breakpoints and break right before the call to the printf wrapper.

d
b *0x1000032e
c

Let's examine the values at each of these locations.

p/x *0x10000340
0x71c71c72

p/x *0x10000344
0x4044471c

We know that the following output is what prints.

40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000
40.5555555560000000

What is happening is that these values are now in R2 and R3 respectively.

p/x $r2
0x71c71c72

p/x $r3
0x4044471c

In ARM 32 Assembly the arguments to the functions are passed in r0-r3 and if you need more args they are put on the stack. In our case r0 has our format modifier.

x/s $r0
0x10007070:    "%.16f\n"

We see in r1 a value pointing to the stack.

x/w $r1
0x0:    0x20041f00

p/x *0x20041f00
0xa

This is another piece going into the printf wrapper in order to properly print the string to the STDOUT.

In our next lesson we will hack statically.

results matching ""

    No results matching ""