20/07/2010

Dump me this !@#$%^ binary

Je mets en ligne un programme qui m'est souvent utile lors de wargames blackbox, j'entends par là des binaires où nous n'avons pas les droits de lecture ( les commandes : strings, gdb, objdump et j'en passe, impossibles à exécuter sur le binaire ).

C'est pourquoi j'ai développé ce tool'z fort utile pour dumper la mémoire du binaire et aller voir tranquillement tout ce qui s'y passe à l'intérieur. Je le mets en ligne ça me servira de post-it et peut être utile à d'autres.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>

int dump(pid_t pid, unsigned long start, unsigned long end);

int
main(int argc, char **argv)
{
  pid_t son;
  int status;
  unsigned long start_address;
  unsigned long stop_address;
  
  if (argc < 4)
    {
      printf("[-] %s : Usage <binaire> <start_addr> <end_addr>\n", argv[0]);
      printf("Example : <start_addr> = 0x0804800 ; <end_addr> = 0x08049b5c\n");
      exit(EXIT_FAILURE);
    }
  start_address = strtoul(argv[2], NULL, 0);
  stop_address = strtoul(argv[3], NULL, 0);
  if (start_address == (unsigned long) - 1 || start_address >= stop_address)
  {
    printf("[-] Bad start or stop address\n");
    exit(EXIT_FAILURE);
  }
  if ((son = fork()) == -1)
    {
      perror("[-] fork()");
      exit (EXIT_FAILURE);
    }
  if (son == 0)
    {
      sleep(1);
      if ( ptrace(PT_TRACE_ME, 0, 0, 0) < 0 )
        {
          perror("[-] ptrace()");
          exit(EXIT_FAILURE);
        }
      if (execl(argv[1], argv[1], NULL) < 0)
        {
          perror("[-] execl()");
          exit(EXIT_FAILURE);
        }
    }
  else
    {
      wait(&status);
      if (WIFEXITED(status))
          exit(EXIT_FAILURE);
      if (dump(son, start_address, stop_address) == 1)
        printf("[-] Dump() failed\n");
      ptrace(PT_KILL, son, 0, 0);
    }
  return 0;
}

int 
dump(pid_t pid, unsigned long start, unsigned long end)
{
  int fd;
  unsigned long dword;
  unsigned long i;

  printf("[+] Dumping ...\n");
  if ((fd = open("dump", O_WRONLY|O_CREAT, 0755)) < 0)
    {
      perror("[-] open()");
      exit(EXIT_FAILURE);
    }
  for (i=start; i<end; i+=4) 
  {
      dword = ptrace(PT_READ_I, pid, (caddr_t)i, 0);
      if (write(fd, &dword, sizeof(dword)) < 0)
          {
          close(fd);
          return 1;
        }
   }
   close(fd);
   printf("[+] Dump from 0x%8.8lx to 0x%8.8lx finish !\n", start, end);
   return 0;
}

Exemple d'utilisation sur le binaire test :

> gcc -o dmtfb dump.c
> ./dmtfb test 0x08048000 0x08049b5c
[+] Dumping ...
[+] Dump from 0x08048000 to 0x08049b5c finish !
> strings dump
/libexec/ld-elf.so.1
FreeBSD
_Jv_RegisterClasses
libc.so.7
printf
environ
__progname
_init_tls
atexit
_end
FBSD_1.0
$FreeBSD: src/lib/csu/i386-elf/crti.S,v 1.7.22.1.2.1 2009/10/25 01:10:29 kensmith Exp $
i = %d
$FreeBSD: src/lib/csu/i386-elf/crtn.S,v 1.6.22.1.2.1 2009/10/25 01:10:29 kensmith Exp $