[ News ] [ Paper Feed ] [ Issues ] [ Authors ] [ Archives ] [ Contact ]

..[ Phrack Magazine ]..
.:: Binary Mangling with Radare ::.

Issues: [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ 14 ] [ 15 ] [ 16 ] [ 17 ] [ 18 ] [ 19 ] [ 20 ] [ 21 ] [ 22 ] [ 23 ] [ 24 ] [ 25 ] [ 26 ] [ 27 ] [ 28 ] [ 29 ] [ 30 ] [ 31 ] [ 32 ] [ 33 ] [ 34 ] [ 35 ] [ 36 ] [ 37 ] [ 38 ] [ 39 ] [ 40 ] [ 41 ] [ 42 ] [ 43 ] [ 44 ] [ 45 ] [ 46 ] [ 47 ] [ 48 ] [ 49 ] [ 50 ] [ 51 ] [ 52 ] [ 53 ] [ 54 ] [ 55 ] [ 56 ] [ 57 ] [ 58 ] [ 59 ] [ 60 ] [ 61 ] [ 62 ] [ 63 ] [ 64 ] [ 65 ] [ 66 ] [ 67 ] [ 68 ]
Current issue : #66 | Release date : 2009-11-06 | Editor : The Circle of Lost Hackers
Phrack Prophile on The PaX TeamTCLH
Phrack World NewsTCLH
Abusing the Objective C runtimenemo
Backdooring Juniper FirewallsGraeme
Exploiting DLmalloc frees in 2009huku
Persistent BIOS infectionaLS and Alfredo
Exploiting UMA : FreeBSD kernel heap exploitsargp and karl
Exploiting TCP Persist Timer Infinitenessithilgore
Malloc Des-Maleficarumblackngel
A Real SMM RootkitCore Collapse
Alphanumeric RISC ARM ShellcodeYYounan and PPhilippaerts
Power cell buffer overflowBSDaemon
Binary Mangling with Radarepancake
Linux Kernel Heap Tampering DetectionLarry H
Developing MacOS X Kernel Rootkitsghalen and wowie
How close are they of hacking your braindahut
Title : Binary Mangling with Radare
Author : pancake
				==Phrack Inc.==

		Volume 0x0d, Issue 0x42, Phile #0x0E of 0x11

|=-----------------=[ manual binary mangling with radare ]=--------------=|
|=--------------------=[ by pancake <at> nopcode.org> ]=-----------------=|

  1 - Introduction
    1.1 - The framework
    1.2 - First steps
    1.3 - Base conversions
    1.4 - The target
  2 - Injecting code in ELF
    2.1 - Resolving register based branches
    2.2 - Resizing data section
    2.3 - Basics on code injection
    2.4 - Mmap trampoline
        2.4.1 - Call trampoline
        2.4.2 - Extending trampolines
  3 - Protections and manipulations
    3.1 - Trashing the ELF header
    3.2 - Source level watermarks
    3.3 - Ciphering .data section
    3.4 - Finding differences in binaries
    3.5 - Removing library dependencies
    3.6 - Syscall obfuscation
    3.7 - Replacing library symbols
    3.8 - Checksumming
  4 - Playing with code references
    4.1 - Finding xrefs
    4.2 - Blind code references
    4.3 - Graphing xrefs
    4.4 - Randomizing xrefs
  5 - Conclusion
  6 - Future work
  7 - References
  8 - Greetings

--[ 1 - Introduction

Reverse engineering is something usually related to w32 environments where
there is lot of non-free software and where the use of protections is more
extended to enforce evaluation time periods or protect intellectual (?)
property, using binary packing and code obfuscation techniques.

These kind of protections are also used by viruses and worms to evade
anti-virus engines in order to detect sandboxes. This makes reverse
engineering a double-edged sword.

The way to do low level analysis does usually involve the development and
use of a lot of small specific utilities to gather information about the
contents of firmware or a disk image to carve for keywords and dump its

Actually we have a wide variety of software and hardware platforms and
reverse engineering tools should reflect this.

Obviously, reverse engineering, cracking and such are not only related to
legal tasks. Crackmes, hacking challenges and learning for the heck of it
are also good reasons to play with binaries. For us, there is a simple
reason behind them all: fun.

--[ 1.1 - The framework

At this point, we can imagine a framework that combines some of the basics
of *nix, offering a set of actions over an abstracted IO layer.

Following these premises I started to write a block based hexadecimal
editor.  It allows to seamlessly open a disc device, file, socket, serial
or process.  You can then both automatize processing actions by scripts and
perform manual interactive analysis.

The framework is composed of various small utilities that can be easily
integrated between them by using pipes, files or an API:

  radare: the entrypoint for everything :)
  rahash: block based hashing utility
  radiff: multiple binary diffing algorithms
  rabin:  extract information from binaries (ELF,MZ,CLASS,MACH0..)
  rasc:   shellcode construction helper
  rasm:   commandline assembler/disassembler
  rax:    inline multiple base converter
  xrefs:  blind search for relative code references

The magic of radare resides in the ortogonality of commands and metadata
which makes easy to implement automatizations.

Radare comes with a native debugger that works on many os/arches and offers
many interesting commands to ease the analysis of binaries without having
the source. 

Another interesting feature is supporting high level scripting languages
like python, ruby or lua. Thanks to a remote protocol that abstracts the
IO, it is allowed the use of immunity debugger, IDA, gdb, bochs, vmware and
many other debugging backends only writing a few lines of script or even
using the remote GDB protocol.

In this article I will introduce various topics. It is impossible to
explain everything in a single article.

If you want to learn more about it I recommend you to pull the latest hg 
tip and read the online documentation at:

  http://www.radare.org [0]

I have also written a book [1] in pdf and html available at:


--[ 1.2 - First steps

To ease the reading of the article I will first introduce the use of radare
with some of its basics.

Before running radare I recommend to setup the ~/.radarerc with this:

  e scr.color=1    ; enable color screen
  e file.id=1      ; identify files when opened
  e file.flag=1    ; automatically add bookmarks (flags) to syms, strings..
  e file.analyze=1 ; perform basic code analysis

Here's a list of points that will help us to better understand how radare
commands are built.

 - each command is identified by a single letter
   - subcommands are just concatenated characters
 - e command stands for eval and is used to define configuration variables
 - comments are defined with a ";" char

This command syntax offers a flexible input CLI that allows to perform
temporal seeks, repeat commands multiple times, iterate over file flags,
use real system pipes and much more.

Here are some examples of commands:

  pdf @@ sym.    ; run "pdf" (print disassembled function) over all
                 ; flags matching "sym."
  wx cc @@.file  ; write 0xCC at every offset specified in file
  . script       ; interpret file as radare commands
  b 128          ; set block size to 128 bytes
  b 1M           ; any math expression is valid here (hex, dec, flags, ..)
  x @ eip        ; dump "block size" bytes (see b command) at eip
  pd | grep call ; disassemble blocksize bytes and pipe to system's grep
  pd~call        ; same as previous but using internal grep
  pd~call[0]     ; get column 0 (offset) after grepping calls in disasm
  3!step         ; run 3 steps (system is handled by the wrapped IO)
  !!ls           ; run system command
  f* > flags.txt ; dump all flags as radare commands into a file

--[ 1.3 - Base conversions

rax is an utility that converts values between bases. Given an hexadecimal
value it returns the decimal conversion and viceversa.

It is also possible to convert raw streams or hexpair strings into
printable C-like strings using the -s parameter:

  $ rax -h
  Usage: rax [-] | [-s] [-e] [int|0x|Fx|.f|.o] [...]
   int   ->  hex           ;  rax 10
   hex   ->  int           ;  rax 0xa
   -int  ->  hex           ;  rax -77
   -hex  ->  int           ;  rax 0xffffffb3
   float ->  hex           ;  rax 3.33f
   hex   ->  float         ;  rax Fx40551ed8
   oct   ->  hex           ;  rax 035
   hex   ->  oct           ;  rax Ox12 (O is a letter)
   bin   ->  hex           ;  rax 1100011b
   hex   ->  bin           ;  rax Bx63
   -e    swap endianness   ;  rax -e 0x33
   -s    swap hex to bin   ;  rax -s 43 4a 50
   -     read data from stdin until eof

With it we can convert a raw file into a list of hexpairs:

  $ cat /bin/true | rax -

There is an inverse operation for every input format, so we can do
things like this:

  $ cat /bin/true | rax - | rax -s - > /tmp/true
  $ md5sum /bin/true /tmp/true
  20c1598b2f8a9dc44c07de2f21bcc5a6 /bin/true
  20c1598b2f8a9dc44c07de2f21bcc5a6 /tmp/true

rax(1) can be also used in interactive mode by reading lines from stdin.

--[ 1.4 - The target

This article aims to explain some practical cases where an scriptable
hexadecimal editor can trivially solve and provide new perspectives to
solve reverse engineering quests.

We will take a x86 [2] GNU/Linux ELF [3] binary as a main target. Radare
supports many architectures (ppc, arm, mips, java, msil..) and operating
systems (osx, gnu/ linux, solaris, w32, wine, bsd), You should take in mind
that commands and debugger features explained in this article can be
applied to any other platform than gnu/linux-x86.

In this article we will focus on the most widely-known platform
(gnu/linux-x86) to ease the reading.

Our victim will suffer various manipulation stages to make reverse
engineering harder keeping functionality intact.

The assembly snippets are written in AT&T syntax [4], which I think it's
more coherent than Intel so you will have to use GAS, which is a nice multi
architecture assembler.

Radare2 has a full API with pluggable backends to assemble and disassemble
for many architectures supporting labels and some basic assembler
directives. This is done in 'rasm2' which is a reimplementation of rasm
using libr.

However, this article covers the more stable radare1 and will only use the
'rasm' command to assemble simple instructions instead of complete

The article exposes multiple situations where low level analysis and
metadata processing will help us to transform part of the program or simply
obtain information from a binary blob.

Usually the best program to start learning radare is the GNU 'true', which
can be completely replaced with two asm instructions, leaving the rest of
the code to play with. However it is not a valid target for this article,
because we are interested in looking for complex constructions to hide
control flow with call trampolines, checksumming artifacts, ciphered code,
relocations, syscall obfuscation, etc.

--[ 2 - Injecting code in ELF

The first question that pops up in our minds is: How the hell we will add
more code in an already compiled program?

What real packers do is to load the entire program structures in memory for
in-memory manipulation, handling all the code relocations and generating a
completely brand new executable.

Program transformation is not an easy task. It requires a complete analysis
which sometimes is impossible to do automatically, due to the need to mix
the results of static, dynamic and manual code analysis.

Instead of this approach, we will do it in a bottom to top way, taking low
level code structures as units and doing transformations without the need
to understand the whole program.

This enables ensuring that transformations won't break the program in any
way because their local and internal dependencies will be easy identified.

Because the target program is generated by a compiler we can make some
assumptions.  For instance, there will be a place to inject code, the
functions will be sequentially defined, access to variables will be 
easier to track and calling conventions will be the same along all the

Our first action will be to find and identify all the parts of the text
section with unused or noppable code.

'noppable' code is defined as code that is never executed, or that can be
replaced by a smaller implementation, taking benefit of the non-overwritten

Compiler-related stubs can be sometimes noppable or replaced, and more of
this is found in non-C native-compiled programs (haskell, C++, ...)

The spaces between functions where no code is executed are called 'function
paddings'.  They exist because the compiler tried to optimize the position
of the functions at aligned addresses to ease to job on the cpu.

Some other compiler-related optimizations will inline the same piece of
code multiple times. By identifying such patterns, we can patch the
spaghetti code into a single loop with an end branch and use the rest for
our own purposes.

Following paragraphs will verbosely explain those situations.

Never executed code:

  We can find this code by doing many execution traces of the program and
  finding the uncovered ranges. This option will probably require human

  Using static code analysis we would not be able to follow runtime pointer
  calculations or call tables. Therefore, this method will also require some
  human interaction and, in the event we get to identify a pattern, we can
  write a script to automatize this task and add N code xrefs from a single
  source address.

  We can also emulate some parts to resolve register values before reaching
  a register based call/branch instruction.

Inlined code and unrolled loops:

  Programmers and compilers usually prefer to inline (duplicate the code of
  a external function in the middle of another one) to reduce the execution
  cost of a 'call' instruction.

  Loops are also unrolled and this produces longer, but more optimal code
  because the cpu doesn't need to compute unnecessary branches all the

  These are common speedup practices, and they are a good target to place
  our code. This process is done in four steps:

  - Find/identify inline code or unrolled loops (repeated similar blocks)
  - Patch to uninline or re-roll the loop
  - ...
  - Profit!

  Radare provides different commands to help to find/identify such kind of
  code blocks. The related commands are not going to do all the job
  automatically. They require some automatization, scripting or manual

  The basic approach to identify such kind of code is by finding repeated
  sequences of bytes allowing a percentage of similarity. Most inline code
  will come from small functions and unrolled loops will be probably small

  There are two basic search commands that can help on this:

  [0xB7F13810]> /?
  /p len   ; search pattern of length 'len'
  /P count ; search patterns of size $$b matching at >N bytes of curblock

  The first command (/p) will find repeated bytes of a specified length.
  The other one (/P) will find a block that matches at least N bytes of the
  current blocksize compared to the current one.

  These pattern search must be restricted to certain ranges, like the .text
  section or the function boundaries:

  The search should be restricted to the text section:
   > e search.from = section._text
   > e search.to = section._text_end

  All search commands (/) can be configured by the 'search.' eval

  The 'section.' flag names are defined by 'rabin'. Calling rabin with
  the -r flag will dump the binary information to stdout as radare commands.

  This is done at radare startup when file.id and file.flag are enabled,
  but this information can be reimported from the shell by calling:

   > .!!rabin -rS ${FILE}

  This command can be understood as a dot command '.', which interprets the
  output of the following command '!' as radare commands. In the example
  below there are two admiration marks (!!). This is because the single '!'
  will run the command through the io subsystem of radare, falling in the
  debugger layer if trying to run a program in the shell which has a name
  that equals a debugger command's.

  The double '!!' is used to directly escape from the io subsystem and run
  the program directly in the system.

  This command can be used to externalize some scripting facilities by
  running other programs, processing data, and feeding radare's core back
  with dynamically generated commands.

  Once all the inlined code is identified, search hits should be analyzed,
  discarding false positives and making all those blocks work as subroutines
  using a call/ret pattern, nopping the rest of the bytes. Unused bytes can
  now be filled with any code.

  Another way to identify inlined code can be done by splitting a function
  code analysis into basic blocks without splitting nodes (e
  graph.split=false) and finding similar basic blocks or repeated.

  Unrolled loops are based on repeated sequences of code with small
  variations based on the iterator variable which must change along the
  repeated blocks in a progressive way (incremental, decremental, etc).

  Language bindings are recommended for implementing such kind of tasks,
  not only because the higher language representation, but also thanks to
  the high level APIs for code analysis that are distributed with radare
  for python and other scripting languages (perl, ruby, lua).

  The '/' command is used to perform searches. A radare command can be
  defined to be executed every time a hit is found, or we can later use
  the '@@' foreach iterator can be used over all the flags prefixed with
  'hit0' later.

  See '/?' for help on search-related commands but, in short, there are
  commands to search in plain text, hexadecimal, apply binary masks to
  keywords, launch multiple keywords at a time, define keywords in a file,
  search+replace, and more.

  One of the search algorithms accessible through the '/' command is called
  '/p', which performs a pattern search. The command accepts a numeric value
  which determines the minimum size for a pattern to be resolved.

  Patterns are identified by a series of consecutive bytes, with a minimum
  length, that appear more than once. The output will return a pattern id,
  the pattern bytes and a list of offsets where the pattern is found.

  This kind of search algorithm can be useful for analyzing huge binary
  files like firmwares, disc images or uncompressed pictures.

  In order to get a global overview of a big file the 'pO' command can be
  used, which will display the full file represented in 'blocksize' bytes
  in hexadecimal. Each byte will represent the number of printable
  characters in the block, the entropy calculation, the number of
  functions identified there, the number of executed opcodes, or whatever
  is set at the 'zoom.byte' eval variable.

      zoom view                  real file
    +-----------+              +----------+
    |         0 |--------------|        0 |
    |         1 | '-.__        |      ... |
    |         2 |      '-.__   |          |
    |         3 |           '-.|      128 | (filesize/blocksize)
    |       ... |              +----------+

  The number of bytes of the real file represented in a byte of the
  zoom view is the quotient between the filesize and the blocksize.

Function padding and preludes:

  Compilers usually pad functions with nop instructions to align the
  following one. They are usually small, but sometimes they are big enough
  to store trampolines that will help obfuscate the execution flow.

  In the 'extending trampolines' chapter I will explain a technique to hide
  function preludes inside a 'call trampoline' which runs the initial code
  of each function and then jumps back to the next instruction.

  By using call tables loaded in .data or memory it will be harder to follow
  for the reverser, because the program can lose all function preludes and
  footers so that it'll be read as a single blob.

Compiler stubs:

  Function preludes and calling conventions can be used as watermarks to
  identify the compiler used. But when compiler optimizations are enabled
  the generated code will be heavily transformed and those preludes will
  probably be lost.

  Some new versions of gcc are using a new function prelude aligning the
  stack before entering the code to make memory access by the cpu on local
  variables. But we can replace them with a shorter hand made one adapted
  to the concrete function needs and this way ripping some more bytes for
  our own fun.
  The entrypoint embeds a system dependent loader that acts as a launcher
  for the constructor/main/destructor. We can analyze the constructor and
  the destructor to check if they are void. 
  Then, we can drop all this code by just adding a branch to the main
  pointer, getting about 190 bytes for a C program. You will probably find
  much more unused code in programs written in D, C++, haskell or any other
  high level language.

  This is how a common gcc's entrypoint looks like:

    0x08049a00, / xor ebp, ebp
    0x08049a02  | pop esi
    0x08049a03  | mov ecx, esp
    0x08049a05  | and esp, 0xf0
    0x08049a08, | push eax
    0x08049a09  | push esp
    0x08049a0a  | push edx
    0x08049a0b  | push dword 0x805b630 ; sym.fini
    0x08049a10, | push dword 0x805b640 ; sym.init
    0x08049a15  | push ecx
    0x08049a16  | push esi
    0x08049a17  | push dword 0x804f4e0 ; sym.main
    0x08049a1c, | call 0x80495b4  ; 1 = imp.__libc_start_main
    0x08049a21  \ hlt 

  By pushing 0's instead of fini/init pointers we can ignore the
  constructor and destructor functions of the program, most of the programs
  will work with no problems without them.

  By analyzing code in both (sym.init and sym.fini) pointers we can 
  determine the number of bytes:

  [0x080482C0]> af @ sym.__libc_csu_fini~size
  size = 4
  [0x080482C0]> af @ sym.__libc_csu_init~size
  size = 89


  Execution traces are wonderful utilities to easily cleanup the view
  of a binary by identifying parts of it as tasks or areas. We can for
  example make a fast identification of the GUI code by starting a
  trace and graphically clicking on all the menus and visual options
  of the target application.

  The most common problem to tracing is the low performance of a !stepall
  operation, which mainly gets stupidly slow on loops, reps and tracing
  already traced code blocks. To speedup this process, radare implements
  a "touchtrace" method (available under the !tt command) which implements
  an idea of MrGadix (thanks!)

  This method consist in keeping a swapped copy of the targeted process
  memory space on the debugger side and replacing it with
  software breakpoint instructions. On intel we would use CC (aka int3).

  Once the program runs, it raises an exception because of the trap
  instruction, which is handled by the debugger. Then the debugger checks
  if the instruction at %eip has been swapped and replaces the userspace
  one, storing information about this step (like timestamp, number of times
  it has been executed and step counter).

  Once the instruction has been replaced, the debugger instructs the 
  process to continue execution. Each time an unswapped instruction is 
  executed the debugger replaces it.

  At the end (giving an end-breakpoint) the debugger have a buffer with
  enough information to determine the executed ranges. Using this easy 
  method we can easily skip all the reps, loops and already analyzed
  code blocks, speeding up the binary analysis.

  Using the "at" command (which stands for analyze traces) it is possible
  to take statistics or information about the traces and, for example..
  serialize the program and unroll loops.

  We can also use !trace, giving a certain debug level as numeric argument,
  to log register changes, executed instructions, buffers, stack changes,
After these steps we can subtract the resulting ranges against the .text
section and get how many bytes we can use to inject code.

If the resulting space is not enough for our purposes we will have to face
section resizing to put our code. This is explained later.

Radare offers the "ar" (analyze ranges) command to manage range lists.
It can perform addition, subtraction and boolean operations.

  > ar+ 0x1000 0x1040 ; manual range addition
  > ar+ 0x1020 0x1080 ; manual add with overlap
  > ari   ; import traces from other places
  > .atr* ; import execution traces information
  > .CF*  ; import function ranges
  > .gr*  ; import code analysis graph ranges
  > ar    ; display non overlapped ranges
  >       ; show booleaned ranges inside text section
  > arb section._text section._text_end

We can also import range information from external files or programs. One
of the nicer characteristics of *nix is the ability to communicate
applications using pipes by just making one program 'talk' in the other
program language. So if we write a perl script that parses an IDA database
(or IDC), we can extract the information we need and print radare commands
('ar' in this case) to stdout, and then parsing the results with the '.'

This time ar gives us information about the number of bytes that are
theoretically not going to be executed and its ranges.

We can now place some breakpoints on these locations to ensure we are not
missing anything. Manual revision of the automated code analysis and
tracing results is recommended.

--[ 2.1 - Resolving register based branchs

  The 'av' command provides subcommands to analyze opcodes inside
  the native virtual machine.

  The basic commands are: 'av-' to restart the vm state, 'avr' to manage
  registers, 'ave' to evaluate VM expressions and 'avx' that will execute N
  instructions from the current seek (will set the eip VM register to the
  offset value).

  Internally, the virtual machine engine translates instructions into
  evaluable strings that are used to manipulate memory and change registers.

  This simple concept allows to easily implement support for new
  instructions or architectures.

  Here is an example. The code analysis has reached a call instruction
  addressing with a register. The code looks like:

  /* --- */
  $ cat callreg.S
  .global main
  .long foo
    xor %eax, %eax
    mov $foo, %ebx
    add %eax, %ebx
    call *%ebx

  $ gcc callreg.S
  $ radare -d ./a.out
  ( ... )
  [0xB7FC6810]> !cont sym.main
  Continue until (sym.main) = 0x08048375
  [0x08048375]> pd 5 @ sym.main
  0x08048375  eip,sym.main:
  0x08048375  / xor eax, eax
  0x08048377 |  mov ebx, 0x8048374 ; sym.foo
  0x0804837c,|  add ebx, eax
  0x0804837e |  call ebx
  0x08048380, \ ret 

  [0x08048375]> avx 4
  Emulating 4 opcodes
  MMU: cached
  Importing register values
  0x08048375    eax ^= eax
     ; eax ^= eax
  0x08048377    ebx = 0x8048374 ; sym.foo
     ; ebx = 0x8048374
  0x0804837c,   ebx += eax
     ; ebx += eax
  0x0804837e   call ebx
     ; esp=esp-4
     ; [esp]=eip+2
     ;==> [0xbf9be388] = 8048382  ((esp]))
     ; write 8048382 @ 0xbf9be388
     ; eip=ebx

  [0x08048375]> avr eip
  eip = 0x08048374

At this point we can continue the code analysis where the 'eip'
register of the virtual machine points.

  [0x08048375]> .afr @ `avr eip~[2]`

--[ 2.2 - Resizing data section

There is no simple way to resize a section in radare1. This process is
completely manual and tricky.

In order to solve this limitation, radare2 provides a set of libraries
(named libr) that reimplement all the functionalities of radare 1.x
following a modular design instead of the old monolithic approach.

Both branches of development are being done in parallel.

Here is where radare2 api (libr) comes in action:

 $ cat rs.c
 #include <stdio.h>
 #include <r_bin.h>
 int main(int argc, char *argv[])
   struct r_bin_t bin;
   if (argc != 4) {
     printf("Usage: %s <ELF file> <section> <size>\n", argv[0]);
   } else {
     if (!r_bin_open(&bin, argv[1], 1, NULL)) {
       fprintf(stderr, "Cannot open '%s'.\n", argv[1]);
     } else
     if (!r_bin_resize_section(&bin, argv[2], r_num_math(NULL,argv[3]))) {
       fprintf(stderr, "Cannot resize section.\n");
     } else {
       return 0;
   return 1;

 $ gcc -I/usr/include/libr -lr_bin rs.c -o rs

 $ rabin -S my-target-elf | grep .data
   idx=24 address=0x0805d0c0 offset=0x000150c0 size=00000484 \
   align=0x00000020 privileges=-rw- name=.data

 $ ./rs my-target-elf .data 0x9400

 $ rabin -S my-target-elf | grep .data
   idx=24 address=0x0805d0c0 offset=0x000150c0 size=00009400 \
   align=0x00000020 privileges=-rw- name=.data

Our 'rs' program will open a binary file (ELF 32/64, PE32/32+, ...) it will
resolve a section named '.data' to change its size and will shift the rest
of sections to keep the elf information as is.

The reason for resizing the .data section is because this one is commonly
linked after the text section. There will be no need to reanalyze the
program code to rebase all the data accesses to the new address.

The target program should keep working after the section resizing and we
already know which places in the program can be used to inject our

   +-------+    +-------+
   | .text |    | .text |
   |       |    |       | <-- inject trampoline
   |-------| -> |-------|
   | .data |    | .data |
   +-------+    |       | <-- inject new code or data
                |       |

Next chapters will explain multiple trampoline methods that will use our
resized data section to store pointer tables or new code.

--[ 2.3 - Basics on code injection

Self modifying code is a nice thing, but usually a dangerous task too. Also
patches/tools like SElinux will not let us to write to an already
executable section.

To avoid this problem we can change in the ELF headers the .text perms to
writable but not executable, and include our decryption function in a new
executable section. When the decryption process is done, it will have to
change text perms to executable and then transfer control to it.

In order to add multiple nested encryption layers the task will be harder
mostly because of the relocation problems, and if the program is not
PIC-ed, rebasing an entire application on the fly by allocating and copying
the program multiple times in memory can be quite complicated.

The simplest implementation consists in these steps:

 - Define from/to ranges
 - Define cipher key and algorithm
 - Inject deciphering code in the entrypoint
   - We will need to use mprotect before looping
 - Statically cipher the section

The from/to addresses can be hardcoded in the assembly snippet or written
in .data or somewhere for later. We can also ask the user for a key and
make the binary work only with a password.

If the encryption key is not found in the binary, the unpacking process
becomes harder, and we will have to implement a dynamic method to find the
correct one. This will be explained later.

Another way to define ranges is by using watermarks and let our injected 
code walk over the memory looking for these marks.

The last step is probably the easier one. We already know the key and the
algorithm, its time to rewrite the inverse one using radare commands and
let the script run over these ranges.

This is an example:

The 'wo' command is a subcommand of the 'w' (write) which offers arithmetic
write operations over the current block.

  [0x00000000]> wo?
  Usage: wo[xrlasmd] [hexpairs]
  Example: wox 90    ; xor cur block with 90
  Example: woa 02 03 ; add 2, 3 to all bytes of cur block
  Supported operations:
    woa  addition        +=
    wos  subtraction     -=
    wom  multiply        *=
    wod  divide          /=
    wox  xor             ^=
    woo  or              |=
    woA  and             &=
    wor  shift right    >>=
    wol  shift left     <<=

It uses cyclic hexpair byte arrays as arguments. Just by seeking on the
"from" address and setting blocksize as "to-from" we will be ready to type
the 'wo' ones.

Implementing this process in macros will make the code more maintainable
and easy to manage. The understanding of functional programming is good
for writing radare macros, split the code in small functions doing
minimal tasks and make them interact with each other.

Macros are defined like in lisp, but syntax is really closer to a mix
between perl and brainfuck. Don't get scary at first instance..it doesn't
hurt as much as you can think and the resulting code is funnier than
expected ;)

  (cipher from to key
    s $0
    b $1-$0
    woa $2
    wox $2)

We can put it in a single line (by replacing newlines with commas ',')
and put it in our ~/.radarerc:

(cipher from to key,s $0,b $1-$0,woa $2,wox $2,)

Now we can call this macro at any time by just prepending a dot before the
parenthesis and feeding it with the arguments.

  f from @ 0x1200
  f to @ 0x9000
  .(cipher from to 2970)

To ease the code injection we can write a macro like this:

 (inject hookaddr file addr
    wa call $2 @ $0
    wf $1 @ $2)

Feeding this macro with the proper values will assemble a call opcode
branching to the place where we inject our code (addr or $2) stored in the
'file' or $1.

Radare has the expanded AES key searching algorithm developed by Victor
Mu~noz. It can be helpful while reversing a program that uses this kind of
ciphering algorithm. As the IO is abstracted it is possible to launch this
search against files, program memory, ram dumps, etc..

For example:

  $ radare -u /dev/mem
  [0x00000000]> /a

WARNING: Most current GNU/Linux distributions comes with the kernel
compiled with the CONFIG_STRICT_DEVMEM option which restricts the access
of /dev/mem to the only first 1.1M.

All write operations are stored in a linked list of backups with the
removed contents. This make possible to undo and redo all changes done
directly on file. This allows you to try different modifications on the
binary without having to restore manually the original one.

These changes can be diffed later with the "radiff -r" command. The command
performs a deltified binary diff between two files, The '-r' displays the
result of the operation as radare commands that transforming the first
binary into the second one.

The output can be piped to a file and used later from radare to patch it
at runtime or statically.

For example:

  $ cp /bin/true true
  $ radare -w true
  [0x08048AE0]> wa xor eax,eax;inc eax;xor ebx,ebx;int 0x80 @ entrypoint
  [0x08048AE0]> u
  03 + 2 00000ae0: 31 ed => 31 c0 
  02 + 1 00000ae2: 5e => 40 
  01 + 2 00000ae3: 89 e1 => 31 db 
  00 + 2 00000ae5: 83 e4 => cd 80 
  [0x08048AE0]> u* | tee true.patch
  wx 31 c0 @ 0x00000ae0
  wx 40 @ 0x00000ae2
  wx 31 db @ 0x00000ae3
  wx cd 80 @ 0x00000ae5

The 'u' command is used to 'undo' write operations. Appending the '*' we
force the 'u' command to list the write changes as radare commands, and we
pipe the output to the 'tee' unix program.

Let's generate the diff:

  $ radiff -r /bin/true true 
  e file.insertblock=false
  e file.insert=false
  wx c0 @ 0xae1
  wx 40 @ 0xae2
  wx 31 @ 0xae3
  wx db @ 0xae4
  wx cd @ 0xae5
  wx 80 @ 0xae6

This output can be piped into radare through stdin or using the '.'
command to interpret the contents of a file or the output of a command.

  [0x08048AE0]> . radiff.patch
  [0x08048AE0]> .!!radiff -r /bin/true $FILE

The '$FILE' environment is exported to the shell from inside radare as well
as other variables like $BLOCK, $BYTES, $ENDIAN, $SIZE, $ARCH, $BADDR, ...

Note that in radare there's not really much difference between memory
addresses and on-disk ones because the virtual addresses are emulated by
the IO layer thanks to the io.vaddr and io.paddr variables which are used
to define the virtual and physical addresses for a section or for the whole

The 'S' command is used to configure a fine-grained setup of virtual and
physical addressing rules for ranged sections of offsets.

Do not care too much about it because 'rabin' will configure these
variables at startup when the file.id eval variable is true.

--[ 2.4 - Mmap trampoline

The problem faced when resizing the .text section is that .data section is
shifted, and the program will try to access it absolutely or relatively.

This situation forces us to rebase all the text section and adapt the rest of

The problem is that we need a deep code analysis to rebase and this is
something that we will probably do wrong if we try to do only a static code
analysis.  This situation usually require a complex dynamic, and sometimes
manual, analysis to fix all the possible pointers.

To skip this issue we can just resize the .data section which is after the
.text one and just write a trampoline in the .text section loading code
from .data and putting it in memory using mmap.

The decision to use mmap is because is the only way to get executable pages
with write permissions in memory even with SELinux enabled.

The C code looks like this:

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

int run_code(const char *buf, int len)
  unsigned char *ptr;
  int (*fun)();
  ptr = mmap(NULL, len,
  if (ptr == NULL)
    return -1;
  fun = (int(*)(void))ptr;
  memcpy(ptr, buf, len);
  mprotect(ptr, len, PROT_READ | PROT_EXEC);
  return fun();

int main()
  unsigned char trap = 0xcc;
  return run_code(&trap, 1);

The manual rewrite in assembly become:

.global main
.global run_code

retaddr: .long 0
shellcode: .byte 0xcc
hello: .string "Hello World\n"

	push %ebp
	mov %esp, %ebp
	push $hello
	call printf
	addl $4, %esp
	pop %ebp

	pop (retaddr)
	/* lcall *0 */
	call tailcall
	push (retaddr)

	/* our snippet */
	push %ebp
	mov %esp, %ebp

	push %ebp
	xor %ebp, %ebp   /* 0 */
	mov $-1, %edi    /* -1 */
	mov $0x22, %esi  /* MAP_ANONYMOUS | MAP_PRIVATE */
	mov $7, %edx     /* PROT_EXEC | PROT_READ | PROT_WRITE */
	mov $4096, %ecx  /* len = 4096 */
	xor %ebx, %ebx   /* 0 */
	mov $192, %eax   /* mmap2 */
	int $0x80
	pop %ebp

	mov %eax, %edi       /* dest pointer */
	mov 0x8(%ebp), %esi  /* get buf  (arg0) */
	mov $128, %ecx
	rep movsb
	mov %eax, %edi

	mov $5, %edx     /* R-X */
	mov $4096, %ecx  /* len */
	mov %edi, %ebx   /* addr */
	mov $125, %eax   /* mprotect */
	int $0x80

	call *%edi
	pop %ebp

	push $shellcode
	call run_code
	add $4, %esp

Running this little program will result on a trap instruction executed on the
mmaped area. I decided to do not checks on return values to make the code

  $ gcc rc.S
  $ ./a.out
  Hello World
  Trace/breakpoint trap

  The size in bytes of this code can be measured with this line in the shell:

  $ echo $((`rabin -o d/s a.out |grep run_code|cut -d ' ' -f 2 |wc -c`/2))

This graph explains the layout of the patch required

                         +----+   /  push dword csu_fini
         .---------------| EP | <    push dword csu_init
         |               +----+   \  push dword main
         V                v
    +------------+     +--------+
    |  csu_init  |     |  main  |   /  push 0x80483490
    |------------|     |--------| <    call getopt
    |    mmap    |   .-|   ...  |   \  mov [esp+30], eax
    | trampoline |   | |        |
    +------------+   | +--------+                   .-----------------.
        ||'||        |                              | this code needs |
        |   |- - - - |- - - - - - - - - - - - - -. <  the mmap tramp  |
        :          __|___       +-----------+    .  | to be executed  |
        .         / hook \ ---> | mmap code |    .  `-----------------'
        .         \getopt/      +-----------+    .
         - - - - - - - - - - - - - -|- - - - - - '
                  +--------+        / fall to the getopt flow
                  | getopt | <-----'

The injection process consists on the following steps:

 * Resize the .data section to get enought space for our code

    f newsize @ section._data_end - section._data + 4096
    !rabin2 -o r/.data/`?v newsize` $FILE

 * Write the code at the end of the unresized .data section

    !!gcc our-code.c
    "!!rabin a.out -o d/s a.out | grep ^main | cut -d ' ' -f 2 > inj.bytes"
    wF inj.bytes @ section._data_end

 * Null the __libc_csu_init pointer at entrypoint (2nd push dword)

    e asm.profile=simple
    s entrypoint
    wa push 0 @ `pd 20~push dword[0]#1`

 * Inject the mmap loader at symbol __libc_csu_init

    # generate mmap.bytes with the mmap trampoline
    !!gcc mmap-tramp.S
    "!!rabin a.out -o d/s a.out | grep ^main | cut -d ' ' -f 2 > mmap.bytes"
    # write hexpair bytes contained in mmap.bytes file at csu_init
    wF mmap.bytes @ sym.__libc_csu_init

 * Hook a call instruction to bridge the execution of our injected code
   and continue the original call workflow.

    - Determine the address of the call to the target symbol to be hooked.
      For example. Having 'ping' program, this script will determine an
      xref to the getopt import PLT entry.

        s entrypoint
        # seek to the third push dword in the entry point (main)
        s `pd 20~push dword[3]#2`

        # Analyze function: the '.' will interpret the output of the command
	# 'af*' that prints radare commands registering xrefs, variable
        # accesses, stack frame changes, etc.

	# generate a file named 'xrefs' containing the code references
        # to the getopt symbol. 
        Cx~`?v imp.getopt`[1] > xrefs

        # create an eNumerate flag at every offset specified in 'xrefs' file
        fN calladdr @@.xrefs

    - Create a proxy hook to bridge execution without destroying the stack.

      This is explained in the following lines.

    - Change the call of the hook to our proxy function

        # write assembly code 'call <addr>'
        # quotes will replace the inner string with the result of the
        # command ?v which prints the hexadecimal value of the given expr.
        wa call `?v dstaddr`

    - Profit

Here is an example assembly code that demonstrates the functionality of the
trampoline for the patched call. This snippet of code can be injected after
the mmap trampoline.

.global main

  push $hookstr
  call puts
  add $4, %esp
  jmp puts

  push $hello
  call trampoline
  add $4, %esp


  .string "hello world"
  .string "hook!"

The previous code cannot be injected directly in the binary, and one of the
main conceptual reasons is that the destination address of the trampoline
will be defined at runtime, when the mmapped region of the data section is
ready with executable permissions, the destination address must be stored
somewhere in the data section.

--[ 2.4.1 - Call trampoline

Once the holes have been identified we can now modify some parts of the
program to obfuscate the control flow, symbol access, function calls and
inlined syscalls in different ways.

To walk through the program code blocks we can use iterators or nested
iterators to run from simple to complex scripted code analysis engines and
retrieve or manipulate the program by changing instructions or moving code.

The control flow of the program can be obfuscated by adding a calltable
trampoline for calling functions. We will have to patch the calls and store
the jump addresses in a table in the data section.

The same hack can be done for long jumps by placing a different trampoline
to drop the stacked eip and use jumps instead of calls.

Iterators in radare can be implemented as macros appending the macro call
after the @@ foreach mark.

 For example: "x @ 0x200"
 will temporally seek to 0x200 and run the "x" command.

 Using: "x @@ .(iterate-functions)"
 will run the iterator macro at every address returned by the macro.

To return values from a macro we can use the null macro body and append the
resulting offset. If no value is given, null is returned and the iterator
will stop.

Heres the implementation for the function-iterator:


We can also use the search engine with cmd.hit eval variable to run a
command when a search hit is found. Obviously, the command can be a macro
or a script file in any language.

  e cmd.hit=ar- $$ $$+5
  /x xx yy zz

But we can also do it after processing the search by just removing the
false positive hits and running a foreach command.

  # configure and perform search
  e search.from=section._text
  e search.to=section._text_end
  e cmd.search=
  /x xx yy zz

  # filtering hit results
  fs search     ; enter into the search flagspace
  f             ; list flags in search space
  f -hit0_3     ; remove hit #3
  # write on every filtered hit
  wx 909090 @@ hit*

Flagspaces are groups of flags. Some of them are automatically created by
rabin while identifying strings, symbols, sections, etc, and others are
updated at runtime like by commands like 'regs' (registers) or 'search'
(search results).

You can switch to or create another flagspace using the 'fs' command. When
a flagspace is selected the 'f' command will only show the flags in the
current flagspace. 'fs *' is used to enable all flagspaces at the same time
(global view). See fs? for extended help.

The internal metadata database can be managed with the C command and stores
information about code and data xrefs, comments, function definitions,
type, data conversions and structure definitions to be used by the
disassembler engine, the code analysis module and user defined scripts.

Data and code xrefs are very useful reference points while reverse
engineering.  It is interesting to obfuscate them all as much as possible
to fool code analysis engines, forcing the reverser to use runtime or
emulated environments to determine when a string or a buffer is used.

To analyze a function in radare is preferably to go into Visual mode with
command 'V', and then press the keys "d" and "f".

This action will make a code analysis from the current seek or where the
cursor points (if in cursor mode, toggleable with the lowercase "c" key in
Visual mode). This code analysis will define multiple things like argument,
local and global variable accesses, feeding the database with xref
information that can be later used to determine which points of the program
are using a certain pointer.

By defining few eval vars in your ~/.radarerc most of this basic code
analysis will be done by default.

  $ cat ~/.radarerc
  e file.id=true    ; identify file type and set arch/baddr...
  e file.analyze=true ; perform basic code analysis at startup
  e file.flag=true  ; add basic flags
  e scr.color=true  ; use color screen

NOTE: By passing the '-n' parameter to radare the startup process will skip
the interpretation of .radarerc.

All this information can be cached, manipulated and restored using project
files (with the -P program flag at startup or enabling this feature in
runtime with the 'P' command).

After this parenthesis we continue obfuscating the xrefs to make reversers
life funnier.

One simple way to do this would be to create an initialization code,
copying some pointers required by the program to run at random mmaped
addresses and defining a way to transform these accesses into a sequence
jigsaw. This can be achieved turning each pointer "random" based on some
rules like a shifted array accessed by a mod.

  # calltable initializer
  (ct-init tramp ctable ctable_end
    f trampoline @ $0
    f calltable @ $1
    f calltable_ptr @ calltable
    wf trampoline.bin @ trampoline
    b $2-$1
    wb 00 ; fill calltable with nops

  ; calltable adder
    ; check if addr is a long call
    ? [1:$$]==0xeb
    ; check if already patched
    ? [4:$$+1]==trampoline
    wv $$+5 @ calltable_ptr
    yt 4 calltable_ptr+4 @ $$+1
    f calltable_ptr @ calltable_ptr+8
    wv trampoline @ $$+1

We can either create a third helper macro that automatically iterates over
every long call instruction in .text and running ct-add on it.

  (ct-run from to tramp ctable ctable_end
    .(ct-init tramp ctable ctable_end)
    s from
      ? [1:$$]==0xeb
      ?? .(ct-add)
      s +$$$
    ? $$ < to

Or we can also write a more fine-grained macro to walk over the function

  e asm.profile=simple
  pD~call[0] > jmps
  .(ct-init 0x8048000 0x8048200)

The trampoline.bin file will be something like this:

 * Calltable trampoline example // --pancake
 * ---------------------------------------------------
 * $ gcc calltrampoline.S -DCTT=0x8048000 -DCTT_SZ 100

#ifndef CTT_SZ
#define CTT_SZ 100
#ifndef CTT
#define CTT call_trampoline_table

.global call_trampoline
.global main

 /* */
 call ct_init
 call ct_test
 /* */
 pushl $hello
 call puts
 add $4, %esp

 pop %esi
 leal CTT, %edi
 movl %esi, 0(%edi)      /* store ret addr in ctable[0] */
 add $8, %edi
 cmpl 0(%edi), %esi      /* check ret addr against ctable*/
 jnz 0b
 movl 4(%edi), %edi      /* get real pointer */
 call *%edi              /* call real pointer */
 jmp *CTT                /* back to caller */

/* initialize calltable */
 leal CTT+8, %edi
 movl $retaddr, 0(%edi)
 movl $puts, 4(%edi)

/* hello world using the calltable */
 push $hello
 call call_trampoline
 add $4, %esp
 .string "Hello World"

 .fill 8*(CTT_SZ+1), 1, 0x00

Note that this trampoline implementation is not thread safe. If two threads
are use the same trampoline call table at the same time to temporally store
the return address, the application will crash.

To fix this issue you should use the %gs segment explained in the 'syscall
obfuscation' chapter. But to avoid complexity no thread support will be
added at this moment.

To inject the shellcode into the binary we will have to make some space in
the .data segment for the calltable. We can do this with gcc -D:

  [0x8048400]> !!gcc calltrampoline.S -DCTT=0x8048000 -DCTT_SZ=100
  > !! rabin -o d/s a.out|grep call_trampoline|cut -d : -f 2 > tramp.hex
  > wF tramp.hex @ trampoline_addr

--[ 2.4.2 - Extending trampolines

We can take some real code from the target program and move it into the
.data section encrypted with a random key. Then we can extend the call
trampoline to run an initialization function before running the function.

Our call trampoline extension will cover three points:

 - Function prelude obfuscation - Function mmaping (loading code from data)
 - Unciphering and checksumming

At the same time we can re-encrypt the function again after calling the end
point address. This will be good for our protector because the reverser
will be forced to manually step into the code because no software
breakpoints will be able to be used on this code because they will be
re-encrypted and the checksumming will fail.

To do this we need to extend our call trampoline table or just add another
field in the call trampoline table specifying the status of the destination
code (if it is encrypted or not) and optionally the checksum.

The article aims to explain guidelines and possibilities when playing with
binaries. But we are not going to implement such kind of extensions to
avoid enlarge too much this article explaining these advanced techniques.

The 'p' command is used to print the bytes in multiple formats, the more
powerful print format is 'pm' which permits to describe memory contents
using a format-string like string and name each of the fields.

When the format-string starts with a numeric value it is handled as an
array of structures. The 'am' command manages a list of named 'pm' commands
to ease the re-use of structure signatures along the execution of radare.

We will start introducing this command describing the format of an entry of
our trampoline call table:

  [0x08049AD0]> pm XX
  0x00001ad0 = 0x895eed31
  0x00001ad4 = 0xf0e483e1

Now adding the name of fields:

  [0x08049AD0]> pm XX from to
        from : 0x00001ad0 = 0x895eed31
          to : 0x00001ad4 = 0xf0e483e1

And now printing a readable array of structures:

  [0x08049AD0]> pm 3XX from to
  0x00001ad0 [0] {
        from : 0x00001ad0 = 0x895eed31
          to : 0x00001ad4 = 0xf0e483e1
  0x00001ad8 [1] {
        from : 0x00001ad8 = 0x68525450
          to : 0x00001adc = 0x0805b6a0
  0x00001ae0 [2] {
        from : 0x00001ae0 = 0x05b6b068
          to : 0x00001ae4 = 0x68565108

There is another command named 'ad' that stands for 'analyze data'. It
automatically analyzes the contents of the memory (starting from the
current seek) looking for recognized pointers (following the configured
endianness), strings, pointers to strings, and more.

The easiest way to see how this command works is by starting a program in
debugger mode (f.ex: radare -d ls) and running 'ad@esp'.

The command will walk through the stack contents identifying pointers to
environment variables, function pointers, etc..

Internal grep '~' syntax sugar can be used to retrieve specific fields of
structures for scripting, displaying or analysis.

  # register a 'pm' in the 'am' command
  [0x08048000]> am foo 3XX from to

  # grep for the rows matching 'from'
  [0x08048000]> am foo~from
          from : 0x00001ad0 = 0x895eed31
          from : 0x00001ad8 = 0x68525450
          from : 0x00001ae0 = 0x05b6b068

  # grep for the 4th column
  [0x08048000]> am foo~from[4]

  # grep for the first row
  [0x08048000]> am foo~from[4]#0

--[ 3 - Protections and manipulations

This chapter will face different manipulations that can be done on binaries
to add some layers of protections to make reverse engineering on the target
binaries a more complicated.

--[ 3.1 - Trashing the ELF header

Corrupting the ELF header is another possible target of a packer for making
the reverser's life little harder.

Just modifying one byte in the ELF header becomes a problem for tools like
gdb, ltrace, objdump, ... The reason is that they depend on section headers
to get information about sections, symbols, library dependencies, etc...
and if they are not able to parse them they just stop with an error. At the
moment of writing, only IDA and radare are able to bypass this issue.

This can be easily done in this way:

 $ echo wx 99 @ 0x21 | radare -nw a.out

A reverser can use the fix-shoff.rs (included in the scripts) directory in
the radare sources, to reconstruct the 'e_sh_off' dword in the ELF header.

  $ cat scripts/fix-shoff.rs
  ; radare script to fix elf.shoff
    s 0            ; seek to offset 0
    s/ .text       ; seek to first occurrence of ".text" string
    s/x 00         ; go next word in array of strings
    ? [1:$$+1]     ; check if this is the last one
    ?!.loop:       ; loop if buf[1] is == 0
    s +4-$$%4      ; align seek pointer to 4
    f nsht         ; store current seek as 'nsht'
    wv nsht @ 0x20 ; write the new section header table at 0x20 (elf.sh_off)

The script is used in this way:

  $ echo ".(fix-shoff) && q" | radare -i scripts/fix-shoff.rs -nw "target-elf"

This script works on any generic bin with a trashed shoff. It will not work
on binaries with stripped section headers (after 'sstrip' f.ex.)

This is possible because GCC stores the section header table immediately
after the string table index, and this section is easily identified because
the .text section name will appear on any standard binary file.

It is not hard to think on different ways to bypass this patch. By just
stripping all the rest of section after setting shoff to 0 will work pretty
well and the reverser will have to regenerate the section headers
completely.  This can be done by using sstrip(1) (double 's' is not a typo)
from the elf-kickers package. This way we eliminate all unnecessary
sections to run the program.

The nice thing of this header bug is that the e_shoff value is directly
passed to lseek(2) as second argument, and we can either try with values
like 0 or -1 to get different errors instead of just giving an invalid
address. This way it is possible to bypass wrong ELF parsers in other ways.

Similar bugs are found in MACH-O parsers from GNU software like setting
number of sections to -1 in the SEGMENT_COMMAND header. These kind of bugs
don't hit kernels because they usually use minimum input from the program
headers to map it in memory, and the dynamic linker at user space do the
rest. But debuggers and file analyzers usually fail when try to extract
corrupted information from headers.

--[ 3.2 - Source level watermarks

If we have the source of the target application there will be more ways to
play with it. For instance, using defines as volatile asm inline macros,
the developer can add marks or paddings usable for the binary packer.

Some commercial packers offer an SDK which is nothing more than a set of
include files offering helper functions and watermarks to make the packers
life easier. And giving to the developer more tools to protect their code.

  $ cat watermark.h
  #define WATERMARK __asm__ __volatile__ (".byte 3,1,3,3,7,3,1,3,3,7");

We will use this CPP macro to watermark the generated binary for later
post-processing with radare. We can specify multiple different watermarks
for various purposes. We must be sure that these watermarks are not already
in the generated binary.

We can even have larger watermarks to pad our program with noisy bytes in
the .text section, so we can later replace these watermarks with our
assembly snippets.

Radare can ease the manual process of finding the watermarks and injecting
code, by using the following command. It will generate a file named
'water.list' containing one offset per line.

  [0x00000000]> /x 03010303070301030307
  [0x00000000]> f~hit[0] > water.list
  [0x00000000]> !!cat water.list

If we want to run a command at every offset specified in the file:

  [0x00000000]> .(fill-water-marks) @@. water.list

Inside every fill-water-mark macro we can analyze the watermark type
depending on the 'hit' flag number (we can search more than one keyword at
a time) or by checking the bytes there and perform the proper action.

If those watermarks have a fixed size (or the size is embedded into the
watermark) we can then write a radare script that write a branch
instruction at to skip the padding. (This will avoid program crash because
it will not execute the dummy bytes of our watermark).

Here's an ascii-art explanation:

 |<-- watermark ------------------------------------------>|
               |<-- unused bytes                        -->|
 | jmp $$+size | .. .. .. .. .. .. .. .. .. .. .. .. .. .. | program
      |                                                      ^

At this point we have some more controlled holes to put our code.

Our variable-sized watermark will be defined in this way:

  .long 0,1,2,3,4,5,6,7,4*20,9,10,11,12,13,14,15,16,17,18,19,20

And the watermark filling macro:

  (fill-water-marks,wa jmp $${io.vaddr}+$$+[$$+8],)

  # run the macro to patch the watermarks with jumps
  .(fill-water-marks) @@. water.list

The io.vaddr specified the virtual base address of the program in memory.

--[ 3.3 - Ciphering .data section

A really common protection in binaries consists on ciphering the data
section of a program to hide the strings and make the static code analysis

The technique presented here aims to protect the data section. This section
generally does not contain program strings (because they are usually
statically defined in the rodata section), but will help to understand some
characteristics of the ELF loader and how programs work with the rw

The PT_LOAD program header type specifies where, which and how part of the
binary should be mapped in memory. By default, the kernel maps the program
at a base address. More over it will map aligned size (asize) of the
program starting at 'physical' on 'virtual' address with 'flags'

  $ rabin -I /bin/ls | grep baddr

  $ rabin -H /bin/ls | grep LOAD
  virtual=0x08060000 physical=0x00018000 asize=0x1000 size=0x0fe0 \
  flags=0x06 type=LOAD name=phdr_0

In this case, 4K is the aligned size of 0xfe0 bytes of the binary will be
loaded at address 0x8060000 starting at address 0x18000 of the file.

By running '.!rabin -rIH $FILE' from radare all this information will be
imported into radare and it will emulate such situation.

The problem we face here, is that the size and address of the mapped area
doesn't match with the offset of the .data section.

Some operations are required to get the correct offsets to statically
modify the program to cipher such range of bytes and inject a snippet
of assembly to dynamically decipher such bytes.

The script looks like:

# flag from virtual address (the base address where the binary is mapped)
# this will make all new flags be created at current seek + <addr>
# we need to do this because we are calculating virtual addresses.
ff $${io.vaddr}

# Display the ranges of the .data section
?e Data section ranges : `?v section._data`- `?v section._data_end`

# set flag space to 'segments'. This way 'f' command will only display the
# flags contained in this namespace.
fs segments

# Create flags for 'virtual from' and 'virtual to' addresses.
# We grep for the first row '#0' and the first word '[0]' to retrieve
# the offset where the PT_LOAD segment is loaded in memory
f vfrom @ `f~vaddr[0]#0`

# 'virtual to' flag points to vfrom+ptload segment size
f vto @ vfrom+`f~vaddr[1]#0`

# Display this information
?e Range of data decipher : `?v vfrom`- `?v vto`= `?v vto-vfrom`bytes

# Create two flags to store the position of the physical address of the
# PT_LOAD segment.
f pfrom @ `f~paddr[0]#0`
f pto @ pfrom+`f~paddr[1]#0`

# Adjust deltas against data section
# ----------------------------------
# pdelta flag is not an address, we set flag from to 0
# pdelta = (address of .data section)-(physical address of PTLOAD segment)
ff 0 && f pdelta @ section._data-pfrom
?e Delta is `?v pdelta`

# reset flag from again, we are calculating virtual and physical addresses
ff $${io.vaddr}
f pfrom @ pfrom+pdelta
f vfrom @ vfrom+pdelta
ff 0

?e Range of data to cipher: `?v pfrom`- `?v pto`= `?v pto-pfrom`bytes

# Calculate the new physical size of bytes to be ciphered.
# we dont want to overwrite bytes not related to the data section
f psize @ section._data_end - section._data
?e PSIZE = `?v psize`

# 'wox' stands for 'write operation xor' which accepts an hexpair list as
# a cyclic XOR key to be applied to at 'pfrom' for 'psize' bytes.
wox a8 @ pfrom:psize

# Inject shellcode

# Setup the simple profile for the disassembler to simplify the parsing
# of the code with the internal grep
e asm.profile=simple

# Seek at entrypoint
s entrypoint

# Seek at address (fourth word '[3]') at line'#1' line of the disassembly
# matching the string 'push dword' which stands for the '__libc_csu_init'
# symbol. This is the constructor of the program, and we can modify it
# without many consequences for the target program (it is not widely used).
s `pd 20~push dword[3]#1`

# Compile the 'uxor.S' specifying the virtual from and virtual to addresses
!gcc uxor.S -DFROM=`?v vfrom` -DTO=`?v vfrom+psize`

# Extract the symbol 'main' of the previously compiled program and write it
# in current seek (libc_csu_init)
wx `!!rabin -o d/s a.out|grep ^main|cut -d ' ' -f 2`

# Cleanup!
?e Uncipher code: `?v $$+$${io.vaddr}`
!!rm -f a.out

The unciphering snippet of code looks like:

.global main
  mov $FROM, %esi
  mov $TO, %edi
  inc %esi
  xorb $0xa8, 0(%esi)
  cmp %edi, %esi
  jbe 0b
  xor %edi, %edi

Finally we run the code:

  $ cat hello.c 
  #include <stdio.h>
  char message[128] = "Hello World";
  int main()
    if (message[0]!='H')
      printf("%s\n", message);
    return 0;
  $ gcc hello.c -o hello
  $ strings hello | grep Hello
  Hello World
  $ ./hello
  Hallo World
  $ radare -w -i xordata.rs hello
  $ strings hello | grep Hello
  $ ./hello
  Hallo World

The 'Hello World' string is no longer in plain text. The ciphering
algorithm is really stupid. The reconstructed data section can be
extracted from a running process using the debugger:

  $ cat unpack-xordata.rs
  e asm.profile=simple
  s entrypoint
  !cont `pd 20~push dword[3]#2`
  f delta @ section._data- segment.phdr_0.rw_.paddr-section.
  s segment.phdr_0.rw_.vaddr+delta
  b section._data_end - section._data
  wt dump
  $ radare -i unpack-xordata.rs -d ./hello
  $ strings dump 
  Hello World

Or statically:

  e asm.profile=simple
  wa ret @ `pd 20~push dword[3]#1`
  wox a8 @ section._data:section._data_end-section.data

This is a plain example of how complicated can be to add a protection and
how easy is to bypass it.

As a final touch for the unpacker, just write a 'ret' instruction at symbol
'__libc_csu_init' where the deciphering loop lives:

  wa ret @ sym.__libc_csu_init

Or just push a null pointer instead of the csu_init pointer in the entrypoint.

  e asm.profile=simple
  s entrypoint
  wa push 0 @ `pd 20~push dword[0]#1`

--[ 3.4 - Finding differences in binaries

Lets draw a scenario where a modified binary (detected by a checksum file
analyzer) has been found on a server, and the administrator or the forensic
analyst wants to understand whats going on that file.

To simplify the explanation the explanation will be based on the previous
chapter example.

At first point, checksum analysis will determine if there's any collision
in the checksum algorithm, and if the files are really different:

  $ rahash -a all hello
  par:     0
  xor:     00
  hamdist: 01
  xorpair: 2121
  entropy: 4.46
  mod255:  84
  crc16:   2654
  crc32:   a8a3f265
  md4:     cbfc07c65d377596dd27e64e0dcac6cd
  md5:     2b3b691d92e34ad04b1affea0ad2e5ab
  sha1:    8ac3f9165456e3ac1219745031426f54c6997781
  sha256:  749e6a1b06d0cf56f178181c608fc6bbd7452e361b1e8bfbcfac1310662d4775
  sha384:  c00abb14d483d25d552c3f881334ba60d77559ef2cb01ff0739121a178b05...
  sha512:  099b42a52b106efea0dc73791a12209854bc02474d312e6d3c3ebf2c272ac...

  $ rahash -a all hello.orig 
  par:     0
  xor:     de
  hamdist: 01
  xorpair: a876
  entropy: 4.29
  mod255:  7b
  crc16:   2f1f
  crc32:   b8f63e24
  md4:     bc9907d433d9b6de7c66730a09eed6f4
  md5:     6085b754b02ec0fc371a0bb7f3d2f34e
  sha1:    6b0d34489c5ad9f3443aadfaf7d8afca6d3eb101
  sha256:  8d58d685cf3c2f55030e06e3a00b011c7177869058a1dcd063ad1e0312fa1de1
  sha384:  6e23826cc1ee9f2a3e5f650dde52c5da44dc395268152fd5c98694ec9afa0...
  sha512:  09b7394c1e03decde83327fdfd678de97696901e6880e779c640ae6b4f3bf...

There is the possibility to generate two different files matching until 3
different checksum algorithms (and maybe more in the future). If any of
them differs we can determine that the file is different.

$ du -bs hello hello.orig 
4913    hello
4913    hello.orig

As both files have the same size it will be worth using a byte-level
diffing, because it is more probable easy to read the differences than
trying to understand them as deltified ones (which is the default diffing

  $ radiff -b hello.orig hello
  000003ed 00
  000003f0 55   |   60 
  000003f1 89   |   be 
  000003f2 e5   |   c0 
  00000406 fe   |   61 
  00000407 ff   |   c3 
  00000408 ff   |   90 
  00000409 8d   |   90 
  0000040a bb   |   90 
  0000040b 18   |   90 
  0000040c ff
  000005bd 00
  000005c0 00   |   a8 
  000005c1 00   |   a8 
  000005c2 00   |   a8 
  000005df 00   |   a8 
  000005e0 48   |   e0 
  000005e1 65   |   cd 
  000005e2 6c   |   c4 
  000005e3 6c   |   c4 
  000005e4 6f   |   c7 
  0000065f 00   |   a8 
  00000660 00

Radiff detects two blocks of changes determined by the '------' lines.

The first block starts at 0x3f0 and the second one (which is bigger) begins
at address 0x5c0.

While watching the massive 00->a8 conversion it is possible to blindly
determine that the ciphering algorithm is XOR and the key is 0xa8. But
let's get a look on the first block of changes and disassemble the code.

  $ BYTES=$(radiff -f 0x3f0 -t 0x40b -b hello.orig hello | awk '{print $4}')
  $ rasm -d "$(echo ${BYTES})"
  mov esi, 0x80495c0
  mov edi, 0x8049660
  inc esi
  xor byte [esi], 0xa8
  cmp esi, edi
  jbe 0x38

Here it is! this code of assembler is looping from 0x80495c0 to 0x8049660
and XORing each byte with 0xa8.

radiff can also dump the results of the diff in radare commands. The
execution of the script will result on a binary patch script to convert one
file to another.

  $ radiff -rb hello hello.orig > binpatch.rs
  $ cat binpatch.rs | radare -w hello
  $ md5sum hello hello.orig
  6085b754b02ec0fc371a0bb7f3d2f34e  hello
  6085b754b02ec0fc371a0bb7f3d2f34e  hello.orig

--[ 3.5 - Removing library dependencies

In some gnu/linux distributions, all the ELF binaries are linked against
libselinux, which is an undesired dependency if we want to make our hello
world portable. SElinux is not available in all gnu/linux distros.

This is a simple example, but we can extend the issue to bad pkg-config
configuration files that can make a binary depend on more libraries than
the minimum required.

Perhaps most users will not care and will probably install those
dependencies, recompile the kernel or whatever else. It is a pity to make
steps in backward instead of telling gcc to not link against those

But we can avoid these dependencies easily: all the library names are
stored as zero-terminated strings in the ELF header, and the loader (at
least the Solaris, Linux and BSD ones) will ignore dependency entries if
the library name is zero length.

The patch consists on finding the non-desired library name (or the prefix,
if there are more than one libraries with similar names) and then write
0x00 in each search result.

  $ radare -nw hello
  [0x00000000]> / libselinux
  ... (results) ...
  [0x00000000]> wx 00 @@ hit
  [0x00000000]> q!

Using -nw radare will run without interpreting the ~/.radarerc and it will
not detect symbols or analyze code (we only need to use the basic
hexadecimal capabilities). The -w flag will open the file in read-write.

Each search result will be stored in the 'search' flagspace with names
predefined by the 'search.flagname' eval variable that will be hit%d_%d by
default. (This is keyword_index and hit_index).

The last command will run 'wx 00' at every '@@' flag matching 'hit' in the
current flagspace.

Use 'q!' if you don't want to be prompted to restore the changes done
before exiting.

--[ 3.6 - Syscall obfuscation

Looking for raw int 0x80 instructions on standard binaries it's going
probably to be a hard task unless these are statically compiled. This is
because they usually live in libraries which are embedded in the program.

Libraries like libc have loads of symbols that are directly mapped to
syscalls, and the reverser could use this information to identify code in a
statically compiled program.

To obfuscate symbols we can embed syscalls directly on the host program,
after trashing the stack to break standard backtraces.

If you go deep enough on the new syscalling system of Linux you will notice
that the int 0x80 syscall mechanism is no longer used in the current x86
platforms because performance reasons.

The new syscall mechanism consists in calling a trampoline function
installed by the kernel as a 'fake' ELF shared object mapped on the running
process memory. This trampoline function implements the most suitable
syscall mechanism for the current platform. This shared object is called

In Linux only two segment registers are used: cs and gs. This is for
simplicity reasons. The first one allows to access to the whole program
memory maps, and the second one is used to store Thread related

Here is a simple segment dumper to get the contents from %gs.

$ cat segdump.S
#define FROM 0 /* 0x8048000 */
#define LEN 0x940
#define TIMES 1
#define SEGMENT %gs /* %ds */

.global main

.fill LEN, TIMES, 0x00

	mov $TIMES, %ecx
	push %ecx

	sub $TIMES, %ecx
	movl $LEN, %eax
	imul %eax, %ecx
	movl %ecx, %esi /* esi = ($TIMES-%ecx)*$LEN */
	addl $FROM, %esi
	lea buffer, %edi
	movl $LEN, %ecx

	rep movsb SEGMENT:(%esi),%es:(%edi)
	movl $4, %eax
	movl $1, %ebx
	lea buffer, %ecx
	movl $LEN, %edx
	int $0x80

	pop %ecx
	xor %eax, %eax
	cmp %eax, %ecx
	dec %ecx
	jnz loopme


At this point we disable the random va space to analyze the contents of the
VDSO map always at the same address during executions.

  $ sudo sysctl -w kernel.randomize_va_space=0

Compile and dump the segment to a file:

  $ gcc segdump.S
  $ ./a.out > gs.segment

And now let's do some little analysis in the debugger:

  $ radare -d ls  ; debug 'ls' program
  ; Inside the debugger we write the contents of the gs.segment file.
  ; In the initial state, the current seek points to 'eip'.

  [0x4A13B8C0]> wf gs.segment
  Poke 100 bytes from gs.segment 1 times? (y/N) y
  file poked.
     offset    0 1  2 3  4 5  6 7  8 9  A B  C D  E F 0123456789ABCDEF
  0x4a13b8c0, c006 e8b7 580b e8b7 c006 e8b7 0000 0000 ....X...........
  0x4a13b8d0, 1414 feb7 ec06 0a93 b305 6beb 0000 0000 ..........k.....
  0x4a13b8e0, 0000 0000 0000 0000 0000 0000 0000 0000 ................
  0x4a13b8f0, 0000 0000 0000 0000 0000 0000 0000 0000 ................
  0x4a13b900, 0000 0000 0000 0000 0000 0000 0000 0000 ................
  0x4a13b910, 0000 0000 0000 0000 0000 0000 0000 0000 ................

  ; Once the file is poked in process memory we have different ways to
  ; analyze the contents of the current data block. One possible option
  ; is to use the 'pm' command which prints memory contents following the
  ; format string we use as argument, it is also possible to specify the
  ; element names as in a structure.
  ; Another option is the 'ad' command which 'analyzes data' reading the
  ; memory as 32bit primitives following pointers and identifying
  ; references to code, data, strings or null pointers.

  [0x4A13B8C0]> pm XXXXXXXXX
  0x4a13b8c0 = 0xb7fe46c0 
  0x4a13b8c4 = 0xb7fe4ac8 
  0x4a13b8c8 = 0xb7fe46c0 
  0x4a13b8cc = 0x00000000 ; eax
  0x4a13b8d0 = 0xb7fff400 ; maps._vdso__0+0x400
  0x4a13b8d4 = 0xff0a0000 
  0x4a13b8d8 = 0x856003b1 
  0x4a13b8dc = 0x00000000 ; eax
  0x4a13b8e0 = 0x00000000 ; eax

  [0x4A13B8C0]> ad
  0x4a13b8c0, int be=0xc046feb7 le=0xb7fe46c0 
  0x4a13b8c4, int be=0xc84afeb7 le=0xb7fe4ac8 
  0x4a13b8c8, int be=0xc046feb7 le=0xb7fe46c0 
     0x4a13b8cc, (NULL)
  0x4a13b8d0, int be=0x00f4ffb7 le=0xb7fff400 maps._vdso__0+0x400
  0xb7fff400,    string "QRU"
  0xb7fff404, int be=0xe50f3490 le=0x90340fe5 

  ; Both analysis result in a pointer to the vdso map at 0x4a13b8d0
  ; Disassembling these contents with 'pd' (print disassembly) we get that
  ; the code uses sysenter.

  [0x4A13B8C0]> pd 17 @ [+0x10]
          _vdso__0:0xb7fff400,   51              push ecx
          _vdso__0:0xb7fff401    52              push edx
          _vdso__0:0xb7fff402    55              push ebp
      .-> _vdso__0:0xb7fff403    89e5            mov ebp, esp
      |   _vdso__0:0xb7fff405    0f34            sysenter 
      |   _vdso__0:0xb7fff407    90              nop 
      |   _vdso__0:0xb7fff408,   90              nop 
      |   _vdso__0:0xb7fff409    90              nop 
      |   _vdso__0:0xb7fff40a    90              nop 
      |   _vdso__0:0xb7fff40b    90              nop 
      |   _vdso__0:0xb7fff40c,   90              nop 
      |   _vdso__0:0xb7fff40d    90              nop 
      `=< _vdso__0:0xb7fff40e    ebf3            jmp 0xb7fff403
          _vdso__0:0xb7fff410,   5d              pop ebp
          _vdso__0:0xb7fff411    5a              pop edx
          _vdso__0:0xb7fff412    59              pop ecx
          _vdso__0:0xb7fff413    c3              ret 

After this little analysis we can use a new way to call syscalls and
transform the "int 0x80" instructions into a bunch of operations.

    push %edi
    push %esi
    movl $0x10, %esi
    movl %gs:(%esi), %edi
    call *%edi
    pop %esi
    pop %edi

Using this 'big' primitive we are able to add more trash code and make
static analysis harder.

Using dynamic analysis it is possible to bypass this protection by writing
a simple script that dumps the backtrace every time a syscall is executed.

    e scr.tee=log.txt

Or with a shell single liner:

  $ echo '(syscall-bt,e scr.tee=log.txt,label:,!contsc,!bt,.label:,) \
    &&.(syscall-bt)' | radare -d ./a.out

A way to make the analysis harder is to trash the stack contents with a
random offset every time we run a syscall. By decreasing the stack pointer
and later incrementing it we will make the backtrace fail.

To trash the stack we can just increment the stack before the syscall and
decrement it after calling it. The analyst will have to patch these inc/dec
opcodes for every syscall trampolines to get proper backtrace and resolve
the xrefs for each entry.

Radare implements a "!contsc" command that makes the debugger stop before
and after a syscall. This can be scripted together with "!bt" and "!st" to
get a handmade version of the strace utility.

Another trick that we can exploit for writing our homebrew packer is to use
instructions needed to be patched for proper analysis as cipher keys.
Making the program crash when trying to decipher a section using invalid
keys for example.

--[ 3.7 - Replacing library symbols

Statically linked binaries are full of unused bytes, we can take use of
this to inject our code.

Lot of library symbols (for example from libc) can be directly replaced by
system calls at the symbol or directly in-place where it is called. For

  call exit

can be replaced these (also 5 byte length) instructions:

  xor eax,eax
  inc eax
  int 0x80

  $ rasm 'xor eax,eax;inc eax;int 0x80'
  31 c0 40 cd 80 

This way we can just go into the statified libc's exit implementation and
overwrite it with our own code.

If the binary is statically compiled with stripped symbols we will have to
look for signatures or directly find the 'int 0x80' instruction and then
analyze code backward looking for the beginning of the implementation and
then find for xrefs to this point.

Most compilers append libraries at the end of the binary, so we can easily
'draw' an imaginary line where the program ends and libraries start.

There's another tool that may help to identify which libraries and versions
are embedded in our target program. It is called 'rsc gokolu'. The name
stands for 'g**gle kode lurker' and it will look for strings in the given
program in the famous online code browser and give approximated results of
the source of the string.

When we have debugging or symbolic information the process becomes much
easier and we can directly overwrite the first bytes of the embedded glibc
code with the small implementation in raw assembly using syscalls.

rabin is the utility in radare which extracts information from the headers
of a given program. This is like a multi-architecture multi-platform and
multi-format 'readelf' or 'nm' replacement which supports ELF32/64,
PE32/32+, CLASS and MACH0. 

The use of this tool is quite simple and the output is quite clean to ease
the parsing with sed and other shell tools.

  $ rabin -vi a.out
  Memory address	File offset	Name
  0x08049034	0x00001034	__gmpz_mul_ui
  0x08049044	0x00001044	__cxa_atexit
  0x08049054	0x00001054	memcmp
  0x08049064	0x00001064	pcap_close
  0x08049074	0x00001074	__gmpz_set_ui

  $ rabin -ve a.out
  Memory address:	0x080494d0

  $ rabin -vs a.out
  Memory address	File offset	Name
  0x0804d86c	0x0000586c	__CTOR_LIST__
  0x0804d874	0x00005874	__DTOR_LIST__
  0x0804d87c	0x0000587c	__JCR_LIST__
  0x08049500	0x00001500	__do_global_dtors_aux
  0x0804dae8	0x00005ae8	completed.5703
  0x0804daec	0x00005aec	dtor_idx.5705
  0x08049560	0x00001560	frame_dummy

  $ rabin -h
  rabin [options] [bin-file]
   -e        shows entrypoints one per line
   -i        imports (symbols imported from libraries)
   -s        symbols (exports)
   -c        header checksum
   -S        show sections
   -l        linked libraries
   -H        header information
   -L [lib]  dlopen library and show address
   -z        search for strings in elf non-executable sections
   -x        show xrefs of symbols (-s/-i/-z required)
   -I        show binary info
   -r        output in radare commands
   -o [str]  operation action (str=help for help)
   -v        be verbose

 See manpage for more information.

The same flags can be used for any type of binary for any architecture.

Using the -r flag the output will be formatted in radare commands, this way
you can import the binary information. This command imports the symbols,
sections, imports and binary information.

  [0x00000000]> .!!rabin -rsSziI $FILE

This is done automatically when loading a file if you have file.id=true, if
you want to disable the analysis run 'radare' with '-n' (because this way
it will not interpret the ~/.radarerc).

Programs with symbols or debug information are mostly analyzed by the code
analysis of 'radare' thanks to the hints given by 'rabin'. So,
theoretically we will be able to automatically resolve the crossed
references to functions. But if we are not that lucky we can just setup a
simple disassembly output format (e asm.profile=simple) and disassemble the
whole program code grepping for 'call 0x???????' to resolve calls to our
desired owned symbol.

  [0x08049A00]> e scr.color=false
  [0x08049A00]> e asm.profile=simple
  [0x08049A00]> s section._text
  [0x08049A00]> b section._text_end-section._text
  [0x08049A00]> pd~call 0x80499e4
  0x08049fd9    call 0x80499e4  ; imp.exit
  0x0804fa89    call 0x80499e4  ; imp.exit
  0x0805047b    call 0x80499e4  ; imp.exit

If we are not lucky and do not have symbols we will have to identify which
parts of the binary are part of our target binary.

  $ rsc syms-dump /lib/libc.so.6 24 > symbols

--[ 3.8 - Checksumming

The most common procedure to check for undesired runtime or static program
patches is done by using checksumming operations over sections, functions,
code or data blocks.

These kind of protections are usually easy to patch, but allow the end user
to get a grateful error message instead of a raw Segmentation Fault.

The error message string can be a simple entrypoint for the reverser to
catch the position of the checksumming code.

Radare offers a hashing command under the "h" char and allows you to
calculate block-based checksums while debugging or statically by opening
the file from disk.

Heres an usage example:


It is also possible to use these hashing instructions to find pieces of the
program matching a certain checksum value, or just recalculate the new sum
to not patch the hash check.

The 'h' command can be also performed from the shell by using the "rahash"
program which permits to calculate multiple checksums for a single file
based on blocks of bytes. This is commonly used on forensics, when you want
a checksum to not only give you a boolean reply (if the program has been
modified), because this way you can reduce the problem on a smaller piece
of the binary because you have multiple checksums at different offsets for
the same file.

This action can be done over hard disks, device firmwares or memory dumps
of the same size.

If you are dealing similar file with deltified contents or you require a
more fine grained result you should try "radiff" which implements multiple
bindiffing algorithms that goes from byte level detecting deltas to code
level diffing using information of basic blocks, variables accessed and
functions called.

We will also have to decide a protection method for the checksumming
algorithm, because this will be the first patch required to enable software
breakpoints and user defined patches to be done.

To protect the hasher we just put it distributed along the program by
mixing its code with the rest of the program making more difficult to
identify the its position. We can also choose to put this code into a
ciphered area in .data together with other necessary code to make the
program run.

One of the main headaches for reversers is the layering of protections that
can be represented by lot of entrypoints to the same code making more
difficult to locate and patch in a proper way.

The checksumming of a section can be used as a deciphering key for other
ciphered sections, to avoid easy patching, the program should check for the
consistence of the deciphered code. This can be done by checking for
another checksum or by comparing few bytes at the beginning of the
deciphered and mmap code.

There is another possible design to implement the checksumming algorithm in
a more flexible way which consists on checksumming the code in runtime
instead of hardcoding the resulting value somewhere.

This method allows us to 'protect' multiple functions without having to
statically calculate the checksum value of the region. The problem with
this method is that it doesn't provide us protection against static
modifications on the binary.

This snippet can be compiled with DEBUG=0 to get a fully working
checksumming function which returns 0 when the checksum matches.

#define CKSUM 0x68
#define FROM 0x8048000
#define SIZE 1024

.asciz "Checksum: 0x%08x\n"

.global cksum
	movl $FROM, %esi
	movl $SIZE, %ecx
	xor %eax, %eax
	xorb 0(%esi), %al
	add $1, %esi
	loopnz 1b
	pushl %eax
	pushl $str
	call printf
	addl $8, %esp
	sub $CKSUM, %eax
	jnz 2f

.global main
	call cksum;
	mov $20, %eax
	int $0x80
	mov $37, %ebx
	mov $9, %ecx
	xchg %eax, %ebx
	int $0x80

To get the bytes of the function to be pushed we can use an 'rsc' script that
dumps the hexpairs contained managed by a symbol in a binary:

  $ gcc cksum.S -DDEBUG
  $ ./a.out
  Checksum: 0x69

  $ gcc -c cksum.S
  $ rsc syms-dump cksum.o | grep cksum
  cksum: 60 be 00 80 04 08 b9 00 04 00 00 31 c0 32 06 83 c6 01 e0 f9 2d d2 04 \
  00 00 75 02 61 c3 b8 14 00 00 00 cd 80 bb 25 00 00 00 b9 09 00 00 00 93 cd 80 

The offsets to patch with our ranged values are:

  +2: original address (4 bytes in little endian)
  +7: size of buffer (4 bytes in little endian)
  +21: checksum byte (1 byte)

We can use this hexdump from a radare macro that automatically patches the
correct bytes while inserting the code in the target program.

  $ rsc syms-dump cksum.o | grep cksum | cut -d : -f 2 > cksum.hex
  $ cat cksum.macro
  (cksum-init ckaddr size,f ckaddr @ $0,f cksize @ $1,)
  (cksum hexfile size
    # kidnap some 4 opcodes from the function
    f kidnap @ `aos 4`
    yt kidnap ckaddr+cksize
    wa jmp $$+kidnap @ ckaddr+cksize+kidnap
    wa call `?v ckaddr`
    wF $0 @ ckaddr
    f cksize @ $$w
    f ckaddr_new @ ckaddr+cksize+50
    wv $$ @ ckaddr+2
    wv $1 @ ckaddr+7
    wx `hxor $1` @ ckaddr+21
    f ckaddr @ ckaddr_new

  $ cat cksum.hooks

  $ radare -w target
  [0x8048923]> . cksum.macro
  [0x8048923]> .(cksum-init 0x8050300 30)
  [0x8048923]> .(cksum cksum.hex 100) @@. cksum.hooks

--[ 4 - Playing with code references

The relationship between parts of code in the program are a good source of
information for understanding the dependencies between code blocks,

Following sub-chapters will explain how to generate, retrieve and use the
code references for retrieving information from a program in memory or
statically on-disk.

--[ 4.1 - Finding xrefs

One of the most interesting information we need when understanding how a
program works or what it does is the flow graph between functions. This
give us the big picture of the program and allows us to find faster the
points of interest.

There are different ways to obtain this information in radare, but you will
finally manage it with the 'Cx' and 'CX' commands (x=code xref, X=data
xref).  This means that you can even write your own program to extract this
information and import it into radare by just interpreting the output of
the program or a file.

  [0x8048000]> !!my-xrefs-analysis a.out > a.out.xrefs
  [0x8048000]> . a.out.xrefs
  [0x8048000]> .!my-xrefs-analysis a.out

At the time of writing this, radare implements a basic code analysis
algorithm that identifies function boundaries, splits basic blocks, finds
local variables and arguments, tracks their access and also identifies code
and data references of individual instructions.

When 'file.analyze' is 'true', this code analysis is done recursively over
the entrypoint and all the symbols identified by rabin. This means that it
will not be able to automatically resolve code references following pointer
tables, register branches and so on and lot of code will remain unanalyzed.

We can manually force to analyze a function at a certain offset by using
the '.afr@addr' command which will interpret ('.') the output of the
command 'afr' that stands for 'analyze function recursively' at (@) a
certain address (addr).

When a 'call' instruction is identified, the code analysis will register a
code xref from the instruction to the endpoint. This is because compilers
uses these instructions to call into subroutines or symbols.

As we did previously, we can disassemble the whole text section looking for
a 'call' instruction and register code xrefs between the source and
destination address with these two lines:

  [0x000074E0]> e asm.profile=simple
  [0x000074E0]> "(xref,Cx `pd 1~[2]`)"
  [0x000074E0]> .(xref) @@=`pd 100~call[0]`

We use the simple asm.profile to make the disassembly text parsing easier.

The first line will register a macro named 'xref' that creates a code xref
at address pointed by the 3rd word of the disassembled instruction.

In the second line it will run the previous macro at every offset specified
by the output of the "pd 100~call[0]" instruction. This is the offset of
every call instruction of the following 100 instructions.

When disassembling code (using the 'pd' command (print disasm)) xrefs will
be displayed if asm.xrefs is enabled. Optionally, we can set asm.xrefsto to
visualize the xref information at both end-points of the code reference.

--[ 4.2 - Blind code references

The xrefs(1) program that comes with radare implements a blind code
reference search algorithm based on identifying sequences of bytes matching
a certain pattern.

The pattern is calculated depending on the offset. This way the program
calculates the relative delta between the current offset and the
destination address and tries to find relative branches from one point to
another of the program.

The current implementation supports x86, arm and powerpc, but allows to
define templates of branch instructions for other architectures by using
the option flags to determine the instruction size, endianness, the way to
calculate the delta, etc.

The main purpose of this program was to identify code xrefs on big files
(like firmwares), where the code analysis takes too long or requires many
manual interaction, it is not designed to identify absolute calls or jumps.

Here's an usage example:

  $ xrefs -a arm bigarmblob.bin 0x6a390

--[ 4.3 - Graphing xrefs

Radare ships some commands to manage and create interactive graphs to
display code analysis based on basic blocks, function blocks or whatever we
want by using the 'gu' command (graph user)

The most simple way to use the graphing capabilities is to use the 'ag'
command that will directly popup a gtk window with a graphed code analysis
from the current seek, splitting the code by basic blocks. (use the eval
graph.jmpblocks and graph.callblocks to split blocks by jumps or calls to
analyze basic blocks or function blocks).

The graph is stored internally, but if we want to create our own graphs
we can use the 'gu' command which provides subcommands to reset a graph,
create nodes, edges and display them.

  [0x08049A00]> gu?
  Usage: gu[dnerv] [args]
   gur              user graph reset
   gun $$ $$b pd    add node
   gue $$F $$t      add edge
   gud              display graph in dot format
   guv              visualize user defined graph

This is a radare script that will generate a graph between analyzed
function by using the xrefs metadata information.

After configuring the graph we can display it using the internal viewer
(guv) or using graphviz's dot.

"(xrefs-to from,f XT @ `Cx~$0[3]`,)" 
"(graph-xrefs,.(xrefs-to `?v $$`),gue $$F XT,)"
"(graph-viz,gud > dot,!!dot -Tpng -o graph.png dot,!!gqview graph.png,)"

.(graph-xrefs) @@= `Cx~[1]`

Here's the explanation of the previous script:

Note that all commands are quoted '"' because this way the inner special
characters are ignored ('>', '~' ...)

"(xrefs-to from,f XT @ `Cx~$0[3]`,)" 

   Register a macro named 'xrefs-to' that accepts one argument named 'from'
   and aliased as $0 inside the macro body.

   The macro executes the 'f XT' (create a flag named XT) at ('@') the
   address where the code xref (Cx) points (3rd column of the row
   matching $0 (the first argument of the macro (from)).


   The 'graph-xrefs-init' macro resets the graph user metadata.

"(graph-xrefs,.(xrefs-to `?v $$`),gue $$F XT,)"

   This macro named 'graphs-xrefs' that run commands separated by commas:

   .(xrefs-to `?v $$`)

      execute the macro 'xrefs-to' at current seek ($$), the value is
      concatenated to the output of executing '?v $$' which evaluates
      the '$$' special variable and prints the value in hexadecimal.

   gue XF XT

      Adds an 'graph-user' edge between the beginning of the function at
      current seek and XT.

"(graph-viz,gud > dot,!!dot -Tpng -o graph.png dot,!!rsc view graph.png,)"

   These commands will generate a dot file, render it in png and display it.

.(graph-xrefs) @@= `Cx~[1]`

   Then, we bundle all those macros and the xrefs graph will be displayed

--[ 4.4 - Randomizing xrefs

Another annoying low level manipulation we can do is to repeat functions at
random places with random modifications to make the program code more
verbose and hard to analyze because of complex control flow paths.

By doing a cross-references (xrefs) analysis between the symbols we will be
able to determine which symbols are referenced more from than one single

The internal grep syntax can be tricky to retrieve lists of offsets for
xrefs at a given position.

  [0x0000c830]> Cx
  Cx 0x00000c59 @ 0x00000790
  Cx 0x00000c44 @ 0x000007b0
  Cx 0x00000c35 @ 0x00000810
  Cx 0x00000c26 @ 0x000008a0

These numbers specify the caller address and the called one. That is:

  0xc59 -(calls)-> 0x790

To disassemble the opcodes referencing code to other positions we can use the
'pd' command with a foreach statement:

  [0x0000c830]> pd 1 @@= `C*~Cx[1]`

This command will run 'pd 1' on every address specified in the 1st column
of the output of the 'C*~Cx[1]'

--[ 5 - Conclussion

This article has covered many aspects of reverse engineering, low level
program manipulation, binary patching/diffing and more, despite being a
concrete task it has tried to expose a variety of scenarios where a command
line hexadecimal editor becomes an essential tool.

Several external scripting languages can be used, don't care about the
cryptic scripting of the radare commands, there are APIs for perl, ruby and
python for controlling radare and analyze code or connect to remote

Being used in batch mode enables the ability to automatize many analysis
tasks, generate graphs of code, determine if it is packed or infected, find
vulnerabilities, etc.

Maybe the more important characteristic of this software is the abstraction
of the IO which allows you to open hard disk images, serial connections,
process memory, haret wince devices, gdb-enabled applications like bochs,
vmware, qemu, shared memory areas, winedbg and more.

There are lot of things we have not covered in this article but the main
concepts have been exposed while explaining multiple protection techniques
for binaries.

Using scriptable tools for implementing binary protection techniques eases
the development and permits to recycle and accelerate the analysis and
manipulation of files.

--[ 6 - Future work

The project was born in 2006, and it has grown pretty fast.

At the moment of writing this paper the development is done on two
different branches: radare and radare2.

The second one is a complete refactoring of the original code aiming to
reimplement all the features of the radare framework into multiple

This design permits to bypass some limitations of the design of r1 enabling
full scripting support for specific or composed set of libraries. Each
module extends its functionalities into plugins.

While using parrot as a virtual machine, multiple scripting languages can
be used together. Being scripting language agnostic enables the possibility
to mix multiple frameworks together (like metasploit [5], ERESI [6], etc)

The modular design based on libraries, plugins and scripts will open new
ways to extend the framework by third party developers and additionally
make the code much more maintainable and bugfree.

New applications will appear on top of the r2 set of libraries, there are
some projects aiming to integrate it from web frontends and graphical

Plugins extend the modules adding support for new architectures, binary
formats, code analysis modules, debugging backends, remote protocols,
scripting facilities and more.

At the moment of writing this, radare2 (aka libr) is actually under
development but implements some test programs that try to reimplement the
applications distributed with radare.

--[ 7 - References
 [0] radare homepage

 [1] radare book (pdf)

 [2] x86-32/64 architecture

 [3] ELF file format

 [4] AT&T syntax

 [5] Metasploit, ruby based exploit development framework

 [6] ERESI

--[ 8 - Greetings

Thanks to JV for his support during the write-up of this article, and to
the Phrack staff to make the publication possible.

I would also like to greet some people for their support while the
development of radare and this article:

  SexyPandas .. for the great quals, ctfs and moments
  nopcode .. for those great cons, feedback and beers
  nibble  .. for those pingpong development sessions and support
  killabyte .. for the funny abstract situations we faced everyday
  esteve .. for the talks, knowledge and the arm/wince reversing tips
  wzzx .. for the motivators, feedback and luls
  lia .. my gf which supported me all those nightly hacking hours :)


Thanks to all the people who managed to read the whole text and also to the
rest for being part of that ecosystem named 'underground' and computer
security which bring us lot of funny hours.

There is still lot of work to be done, and ideas or contributions are
always welcome. Feel free to send me comments.


--------[ EOF
[ News ] [ Paper Feed ] [ Issues ] [ Authors ] [ Archives ] [ Contact ]
© Copyleft 1985-2014, Phrack Magazine.