Anatomy of a Parasitic Computer 
by Vincent W. Freeh

Listing One
int main (int argc, char *argv[])
{
  int raw;                      // socket that is opened SOCK_RAW
  char *host;                   // targeted machine--the parasite's "host"
  char answer[2];               // value c in 'is a+b equal to c'
  u_short checksum;             // computed checksum
  char *data;                   // data added (a,b in 'is a+b equal to c')
  int datalen;                  // length of data in bytes
  u_long haddr, paddr;          // dotted addr of host and parasite
  int hport, pport;             // IP port of host and parasite
  int ack, seq;                 // acknowledge and sequence numbers

  // ... init code omitted ...
  raw = initCommo(host);
  getIPpacket(raw, haddr, hport, pport, &ack, &seq);
  checksum = computeTCPchecksum((char*)answer, sizeof(u_short)*datalen, paddr,
                       pport, haddr, hport, ackRead, seqRead+1 , ACK|PSH);
  transmit_TCP(raw, (char*)data, sizeof(u_short)*datalen, checksum paddr, 
                       pport, haddr, hport, ackRead, seqRead+1 , ACK|PSH);
  // if there is a response, the query is true
  rc = getIPpacket(raw, haddr, hport, pport, NULL, NULL);
  printf("Answer is %s\n", rc ? "false" : "true");
}
void initCommo(char *host)
{
  // ... omitted locals ...
  /* create raw read socket */
  raw = socket(AF_INET,SOCK_RAW,IPPROTO_TCP);
  if (raw < 0) {
    perror("socket (raw)");
    exit(-1);
  }
  // set mask to make socket async
  val =  fcntl(rd, F_GETFL);
  val |= O_NDELAY;
  if ( fcntl(raw, F_SETFL, val) < 0 ) {
    perror("fcntl");
    exit(1);
  }
  // create and connect to a tcp socket
  // use address family INET and STREAMing sockets (TCP)
  // ... details omitted ...
  s = socket(AF_INET, SOCK_STREAM, 0);
  rc = bind(s, (struct sockaddr *)&sin, sizeof(sin));
  rc = connect(s, (struct sockaddr *)&sin, sizeof(sin));
}
int getIPpacket(int sock, u_long haddr, int hport, int pport, 
                                           int *ack, int *seq)
{
  // ... omitted locals ...
  // raw socket is async and next IP packet may not be from host
  // so may need to read socket several times 
  while (wait < pause) {
    nbytes = recv(sock, buf, 10000, 0);
    if (nbytes < 0) {
      if (errno == EWOULDBLOCK) {       // async: nothing to read, try again
        if (++wait > pause)             
          return -1;
        sigpause(0);
        continue;
      }
      perror("recv");
      exit(-1);
    }
    // check host
    if (buf[12] != host[0] || buf[13] != host[1] ||
        buf[14] != host[2] || buf[15] != host[3]) {
      if (Verbose)
        printf("skipping %u.%u.%u.%u\n",buf[12],buf[13], buf[14], buf[15]);
      continue;
    }
    // check host port
    offset = (buf[0]&0xf)*4;
    tmp = (buf[offset]<<8)+buf[++offset];
    if (hport != tmp) {
      if (Verbose) printf("skipping\n");
      continue;
    }
    // check parasite port
    if (pport != tmp) {
      if (Verbose) printf("skipping\n");
      continue;
    }
    if (proto == 6) {              // buf[9] is proto; TCP is 6
      if (ack && seq) {
        // copy ack and seq numbers out of TCP header
        *ack = LONG(buf+4);
        *seq = LONG(buf+8);
      }
      return 0;
    }
    else
      continue;
  }
  return -1;                     // not reached
}
void transmit_TCP (int fd, char *sp_data, int datalen, u_long paddr, 
            int pport, u_long haddr, int hport, int ack, int seq, int flags)
{
  // ... most locals omitted ...
  char buffer[1500];
  struct sockaddr_in sockaddr;
  // setup IP header fields in buffer
  // set TCP header fields in buffer
  return sendto(fd, buffer, datalen + TCP_BASE + IP_BASE +  ipOptLen, 0,
                                     &sockaddr, sizeof(struct sockaddr));
}






2


