/*
 *   TEXT segment to file dumper
 *
 *   dreyer v0.03 
 */

/* Explicacion por IRC (14/10/2002 00:44)
 *
 * <dreyer> imaginate que tiens un prog que sea asi:
 * <dreyer> printf("%d\n",getpid());
 * <dreyer> sleep(5)
 * <dreyer> execlp("/bin/bash","bash",NULL);
 * <dreyer> ejecutalo
 * <dreyer> y cuando imprima su pid
 * <dreyer> coge el gdb y haz un attach a el
 * <dreyer> y una vez dentro dale a continuar
 * <dreyer> luego mira en /proc/eseproceso/maps
 * <dreyer> weno he dicho /bin/bash pero podia haberte dicho /bin/ls
 * <dreyer> int main ()
 * <dreyer> {
 * <dreyer>   printf("%d\n",getpid());
 * <dreyer>   sleep(5);
 * <dreyer>   execlp("/bin/ls","ls",(char *)0);
 * <dreyer> }
 * <dreyer>  ./t1 &
 * <dreyer> [1] 4797
 * <dreyer> 4797
 * <dreyer> > gdb t1 4797
 * <dreyer> ...
 * <dreyer> 0x400cd711 in __libc_nanosleep () from /lib/libc.so.6
 * <dreyer> (gdb) cont
 * <dreyer> Continuing.
 * <dreyer> Program received signal SIGTRAP, Trace/breakpoint trap.
 * <dreyer> 0x40001ef0 in _start () at rtld.c:169
 * <dreyer> 169     rtld.c: No such file or directory.
 * <dreyer> (gdb)
 * <dreyer> > cat /proc/4797/maps
 * <dreyer> 08048000-08053000 r-xp 00000000 03:01 289743     /bin/ls
 * <dreyer> ves?
 * <dreyer> se ha hecho el cambio de imagen en memoria
 * <dreyer> con lo que ahora podria hacer yo a saco paco
 * <dreyer> x/20i 0x08048000
 * <dreyer> y estaria mirando el codigo del ls
 * <dreyer> y mira cuales eran los permisos de mi ls
 * <dreyer> > ls -l /bin/ls
 * <dreyer> -rwx--x--x    1 root     bin         45408 May 29  2001 /bin/ls*
 ****
 * Ampliacion:
 *
 * <dreyer> mira en binfmt_elf.c
 * <dreyer> static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 * <dreyer> ...
 * <dreyer> ...
 * <dreyer>     if (current->ptrace & PT_PTRACED)
 * <dreyer>                 send_sig(SIGTRAP, current, 0);
 * <dreyer> de ahi viene el sigtrap que aparece en el gdb
 * <dreyer> lo que ahora no localizo lo de que no se utiliza el suid si esta ptraced
 * <dreyer> ta aki
 * <dreyer> exec.c
 * <dreyer> void compute_creds(struct linux_binprm *bprm)
 * <dreyer> ...
 * <dreyer>  if (must_not_trace_exec(current)
 * <dreyer> || atomic_read(&current->fs->count) > 1
 * <dreyer>                     || atomic_read(&current->files->count) > 1
 * <dreyer>                     || atomic_read(&current->sig->count) > 1) {
 * <dreyer>                         if(!capable(CAP_SETUID)) {
 * <dreyer>                                 bprm->e_uid = current->uid;
 * <dreyer>                                 bprm->e_gid = current->gid;
 * <dreyer> ahi es donde pierde los privilegios
 * <dreyer> static inline int must_not_trace_exec(struct task_struct * p)
 * <dreyer> {
 * <dreyer>         return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP);
 * <dreyer> }
 */


#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#define OUTPUT "binfile.out"

void usage (char *p)
{
  printf("dumper by dreyer\n");
  printf("Uso: %s <archivo>\n",p);
  exit(1);
}

void killer (int v)
{
  if (ptrace(PTRACE_KILL,v,0,0)) {
          perror("ptrace: PTRACE_KILL");
          exit(2);
   } 
}

int main (int argc, char *argv[])
{
   int victim,status,fd,data,cont=1;
   char parse[101],map[101],perm[11],junk[104],real[1001],name[1001];
   char **newargs;
   FILE *command;
   long int diri, dirf,i;


   if (argc!=2) usage(argv[0]);


   newargs=&argv[1];

   printf("Executing %s\n",argv[1]);
   if (!(victim=fork()))
   {
     execvp(argv[1],newargs);
     perror("execvp");
     exit(1);
   }

   realpath(argv[1],real);

   printf("Attaching to pid %d...",victim);
   snprintf(parse,100,"cat /proc/%d/maps|awk '{print $1,$2,$6}'",victim);
   snprintf(map,100,"cat /proc/%d/maps",victim);

   if (ptrace(PTRACE_ATTACH, victim,0,0)) {
         perror("ptrace: PTRACE_ATTACH");
         exit(2);
   }
   waitpid(victim, NULL, WUNTRACED);
   printf(" attached\n");

   if (ptrace(PTRACE_CONT,  victim,0,0)) {
         perror("ptrace: PTRACE_CONT");
         exit(2);
   }
   waitpid(victim, NULL, WUNTRACED);
   printf("Continuing...\n");
   printf("Content of map file:\n");
   system(map);
   printf("--------------------\n"); 

   command=popen(parse,"r"); 
   while(cont)
   {
      if(fscanf(command,"%x-%x %s %s",&diri,&dirf,perm,name)==EOF) 
      {
         printf("Process Image not found in memory\nExiting...\n");
         killer(victim);
         exit(2);
      }
      fgets(junk,100,command);
      if(!strcmp(name,real) && !strcmp(perm,"r-xp")) cont=0;
   }

   printf("Processing %p-%p,%s,%s\n",diri,dirf,perm,name);

   pclose(command);     

   fd=open(OUTPUT,O_WRONLY|O_TRUNC|O_CREAT,0700);

   // a por el contenido del binario!!!!
   for (i=diri;i<dirf;i+=4) 
   {
       data=ptrace(PTRACE_PEEKTEXT,victim, i, 0);
       write(fd,&data,sizeof(data));
   }   
   close(fd);
   printf("Image copied to %s\n",OUTPUT);

   //Y matamos al proceso 
   killer(victim);
   
   exit(0);
}

