loading...

A (Very Basic) Example of Patching with Radare2

aibhstin profile image Aibhstin ・4 min read

For an ethical hacking & cybersecurity student, I've so far not written anything about cybersecurity. Whilst I intend on writing something up about why Haskell is the best for cybersecurity and writing secure code, I first wanted to write something that I struggled with for what was probably way too long: patching a binary with Radare2.

Installation

Radare2 can be downloaded and compiled from here. The instructions are pretty clear, so I won't go over them here. Alternatively, you can just grab a Kali virtual machine that already has R2 installed and configured, which is what I personally recommend.

A Program to Patch

First, we'll create a little C program. This is the source code (Which I've called hello.c):

#include <stdio.h>

int main(void) {
  int i;
  for(i=0;i<5;i++){
    printf("Hello, world\n");
  }
  return 0;
}

And compile:

~ gcc -o hello hello.c

Running the program does exactly what you'd expect:

Hello, world
Hello, world
Hello, world
Hello, world
Hello, world

Patching with R2

We're going to be patching the program with the intention of changing the number of times "Hello, world" is printed. We first need to open our program with Radare2 with the write option:

~ r2 -w hello

No we need to analyse the file. There are varying degrees of analysis possible, in this case we can go with the maximum as it is a really small program:

[0x00001050]> aaaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
[x] Enable constraint types analysis for variables

We can change the address we are currently at by seeking to it with the s command.

[0x00001050]> s main

We can print the disassembled main function with pdf:

[0x00001135]> pdf
/ (fcn) main 46
|   main (int argc, char **argv, char **envp);
|           ; var int local_4h @ rbp-0x4
|           ; DATA XREF from entry0 (0x106d)
|           0x00001135      55             push rbp
|           0x00001136      4889e5         mov rbp, rsp
|           0x00001139      4883ec10       sub rsp, 0x10
|           0x0000113d      c745fc000000.  mov dword [local_4h], 0
|       ,=< 0x00001144      eb10           jmp 0x1156
|       |   ; CODE XREF from main (0x115a)
|      .--> 0x00001146      488d3db70e00.  lea rdi, qword str.Hello__world ; 0x2004 ; "Hello, world!"
|      :|   0x0000114d      e8defeffff     call sym.imp.puts           ; int puts(const char *s)
|      :|   0x00001152      8345fc01       add dword [local_4h], 1
|      :|   ; CODE XREF from main (0x1144)
|      :`-> 0x00001156      837dfc50       cmp dword [local_4h], 0x05  ; 'P'
|      `==< 0x0000115a      7eea           jle 0x1146
|           0x0000115c      b800000000     mov eax, 0
|           0x00001161      c9             leave
\           0x00001162      c3             ret

Looking closely at this function (Even if you don't fully understand assembly), you can see something being compared to 5 at the instruction at 0x00001156. It's followed immediately after by a 'jump if less than or equal' operation. It's a fair assumption to make that changing this comparison value will change the amount of times "Hello, world" is printed. To do this, we first need to enter Visual mode with V:

[0x00001135]> V

We then need to press p once to get into a much nicer view

[0x00001135 [xAdvc] 26% 160 hello]> pd $r @ main                                                                                                
/ (fcn) main 46                                                                                                                                 
|   main (int argc, char **argv, char **envp);                                                                                                  
|           ; var int local_4h @ rbp-0x4                                                                                                        
|           ; DATA XREF from entry0 (0x106d)                                                                                                    
|           0x00001135      55             push rbp                                                                                             
|           0x00001136      4889e5         mov rbp, rsp                                                                                         
|           0x00001139      4883ec10       sub rsp, 0x10                                                                                        
|           0x0000113d      c745fc000000.  mov dword [local_4h], 0                                                                              
|       ,=< 0x00001144      eb10           jmp 0x1156                  ;[1]                                                                     
|       |   ; CODE XREF from main (0x115a)                                                                                                      
|      .--> 0x00001146      488d3db70e00.  lea rdi, qword str.Hello__world    ; 0x2004 ; "Hello, world!"                                        
|      :|   0x0000114d      e8defeffff     call sym.imp.puts           ;[2] ; int puts(const char *s)                                           
|      :|   0x00001152      8345fc01       add dword [local_4h], 1                                                                              
|      :|   ; CODE XREF from main (0x1144)                                                                                                      
|      :`-> 0x00001156      837dfc05       cmp dword [local_4h], 5                                                                              
|      `==< 0x0000115a      7eea           jle 0x1146                  ;[3]                                                                     
|           0x0000115c      b800000000     mov eax, 0                                                                                           
|           0x00001161      c9             leave                                                                                                
\           0x00001162      c3             ret                                                                                                  
            0x00001163      662e0f1f8400.  nop word cs:[rax + rax]                                                                              
            0x0000116d      0f1f00         nop dword [rax] 

Now we need to press c to enter cursor mode. You'll notice a little cursor appears over the hex section. Move this cursor down to the line with the comparison, and specifically over the 05. Pressing i puts us into insert mode, where we can insert our own 2-digit hexadecimal number. For now, put 10:

|      :|   0x00001152      8345fc01       add dword [local_4h], 1                                                                              
|      :|   ; CODE XREF from main (0x1144)                                                                                                      
|      :`-> 0x00001156   3  837dfc10       cmp dword [local_4h], 0x10                                                                           
|      `==< 0x0000115a      7eea           jle 0x1146                  ;[3]                                                                     
|           0x0000115c      b800000000     mov eax, 0 

Notice how now the 5 has been replaced with 0x10? Now, press q to quit visual mode and type exit to exit out of R2. Now if we run the binary again:

Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world

We get "Hello, world" printed 16 times, instead of 5.

(Alternatively, when you've selected the line containing the assembly you want to edit, you can press A to replace that line with assembly of your own, with R2 automatically generating the hex codes)

Conclusion

I'm still very new to Radare2, but I have committed to spending time to learn how to use it as much as possible. I'll be making actual tutorials and posts with it soon, this is more of a taster, in a sense.

Posted on by:

aibhstin profile

Aibhstin

@aibhstin

I'm an Ethical Hacking & Cybersecurity student and a Haskell programmer.

Discussion

markdown guide