This is a low-level network debugging utility that utilizes raw packet i/o to construct and deconstruct tcp, udp, ipv4, arp, and icmp packets over ethernet.

Dependencies:   mbed

main.cpp

Committer:
etherealflaim
Date:
2010-10-12
Revision:
0:d494b853ce97
Child:
6:66c4cd9073aa

File content as of revision 0:d494b853ce97:

#include "mbed.h"
#include "string.h"

#include "util/types.h"
#include "util/log.h"
#include "util/util.h"
#include "sniffer.h"
#include "scanner.h"

#include <string>
#include <queue>

// The main logger (global scope)
Sniffer sniffer;
Log main_log;
bool main_running = true;

Ethernet_MAC BROADCAST_MAC = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
Ethernet_MAC your_mac;

IP_Address my_ip = {0x00, 0x00, 0x00, 0x00};
IP_Address your_ip;

bool portscan_started = false;
bool ip_determined = false;

LocalFileSystem local("local");
queue<string> commands;

inline void loadCommands()
{
  FILE *fp = fopen("/local/ntcmd.txt", "r");
  if (fp)
  {
    char buf[256];
    while (NULL != fgets(buf, 256, fp))
    {
      if (buf[0] == '#') continue;
      else if (strlen(buf) == 0) continue;
      else if (!strncmp(buf, "ping", 4)) commands.push("ping");
      else if (!strncmp(buf, "portscan", 8)) commands.push("portscan");
      else if (!strncmp(buf, "identify", 8)) commands.push("identify");
      else main_log.printf("Unknown command: %s", buf);
    }
  }
  else
  {
    // Write the ntcmd file with some help
    main_log.printf("No net tool command file found!");
    fp = fopen("/local/ntcmd.txt", "w");
    fprintf(fp, "# Net Tool Command File Help:\n");
    fprintf(fp, "# 1. Comments start with the pound sign\n");
    fprintf(fp, "# 2. Commands are on a line by themselves\n");
    fprintf(fp, "# Known commands:\n");
    fprintf(fp, "# 1. ping - Send a ping to the host computer every 30 seconds and write results to PING.TXT\n");
    fprintf(fp, "# 2. portscan - Scan the host computer and write open TCP ports to PORTSCAN.TXT\n");
    fprintf(fp, "# 3. identify - Write host computer information to IDENTITY.TXT\n");
  }
  fclose(fp);
}

Ticker ping_timer;
void ping()
{
#define PING_BUFEFERSIZE (sizeof(IP_PacketHeader) + sizeof(ICMP_Packet))
    u8 buffer[PING_BUFEFERSIZE];
    IP_PacketHeader *ip_packet = (IP_PacketHeader*)buffer;
    ICMP_Packet *ping_packet = (ICMP_Packet*)ip_packet->data;
    
    memset(buffer, '\0', PING_BUFEFERSIZE);
    
    *ip_packet = (IP_PacketHeader){0x04, 5, 0, sizeof(IP_PacketHeader)+sizeof(ICMP_Packet), 0, 0, 0, 0, 0, 32, IPPROTO_ICMP, 0x00, my_ip, your_ip};
    *ping_packet = (ICMP_Packet){ICMP_ECHO_REQUEST, 0x00, 0x00, 0x00, 0x00};
    
    fix_endian_icmp(ping_packet);
    fix_endian_ip(ip_packet);
    ip_packet->header_checksum = checksum(ip_packet, sizeof(IP_PacketHeader), &ip_packet->header_checksum, 2);
    ping_packet->checksum = checksum(ping_packet, sizeof(ICMP_Packet), &ping_packet->checksum, 2);
    
    
    FILE *fp = fopen("/local/ping.txt", "w");
    fprintf(fp, "PING sent...\n");
    fclose(fp);
    
    sniffer.inject(your_mac, ETHERTYPE_IPV4, buffer, PING_BUFEFERSIZE);
}

void identify()
{
    FILE *fp = fopen("/local/identity.txt", "w");
    fprintf(fp, "Connected host identity:\n");
    
    u8 *octets = your_mac.octet;
    fprintf(fp, "  MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n", octets[0],octets[1],octets[2],octets[3],octets[4],octets[5]);
    
    octets = your_ip.octet;
    fprintf(fp, "  IP  Address: %d.%d.%d.%d\n", octets[0],octets[1],octets[2],octets[3]);
    
    fclose(fp);
}

int main() {
    // Enable logging via USB
    main_log.enable(LOG_USB);
    main_log.printf("");
    
    // Startup sequence
    main_log.printf("Booting...");
    Scanner scanner(&sniffer); // Hooks into TCP handler
    
    main_log.printf("Loading commands...");
    loadCommands();

    main_log.printf("Starting...");
    while(main_running) {
        // Get the next frame
        sniffer.next();
        
        // Handle ICMP packet
        if (sniffer.icmp_packet)
        {
            // If the packet is an ICMP ECHO (Ping) request
            if (sniffer.icmp_packet->type == ICMP_ECHO_REQUEST)
            {   
                // Build the ICMP packet
                sniffer.icmp_packet->type = ICMP_ECHO_REPLY;
                
                // Build the IP packet
                sniffer.ip_packet->destination = sniffer.ip_packet->source;
                sniffer.ip_packet->source = my_ip;
                
                // Inject the packet
                fix_endian_icmp(sniffer.icmp_packet);
                fix_endian_ip(sniffer.ip_packet);
                sniffer.icmp_packet->checksum = checksum(sniffer.icmp_packet, sizeof(ICMP_Packet) + sniffer.data_bytes, &sniffer.icmp_packet->checksum, 2);
                sniffer.ip_packet->header_checksum = checksum(sniffer.ip_packet, sizeof(IP_PacketHeader), &sniffer.ip_packet->header_checksum, 2);
                sniffer.inject(sniffer.frame_header->source, ETHERTYPE_IPV4, sniffer.ip_packet, sizeof(IP_PacketHeader) + sizeof(ICMP_Packet) + sniffer.data_bytes);
            }
            else if (sniffer.icmp_packet->type == ICMP_ECHO_REPLY)
            {
                FILE *fp = fopen("/local/ping.txt", "a");
                fprintf(fp, "PING reply received\n");
                fclose(fp);
            }
        }
        // Handle ARP packet
        else if (sniffer.arp_packet)
        {
            // These conditions can be optimized a lot
            // Check for an ARP request
            if (is_nonzero_mem(sniffer.arp_packet->sender_hardware_address, 6) &&
                is_nonzero_mem(sniffer.arp_packet->sender_protocol_address, 4) &&
                is_nonzero_mem(my_ip.octet, 4) &&
                is_equal_mem(sniffer.arp_packet->target_protocol_address, my_ip.octet, 4) &&
                sniffer.arp_packet->operation == 1)
            {
                //main_log.printf("ARP Requested:");
                //main_log.printf("  Responding with IP - %03d.%03d.%03d.%03d", my_ip.octet[0],my_ip.octet[1],my_ip.octet[2],my_ip.octet[3]);
                Ethernet_MAC *targmac = (Ethernet_MAC*)sniffer.arp_packet->target_hardware_address;
                IP_Address   *targip  = (IP_Address*)sniffer.arp_packet->target_protocol_address;
                Ethernet_MAC *srcmac  = (Ethernet_MAC*)sniffer.arp_packet->sender_hardware_address;
                IP_Address   *srcip   = (IP_Address*)sniffer.arp_packet->sender_protocol_address;
                
                // Set the ARP options
                *targmac = *srcmac;
                *srcmac  = sniffer.mac;
                *targip  = *srcip;
                *srcip   = my_ip; 
                sniffer.arp_packet->operation = 2;
                
                fix_endian_arp(sniffer.arp_packet);
                sniffer.inject(BROADCAST_MAC, ETHERTYPE_ARP, sniffer.arp_packet, sizeof(ARP_Packet));
                
                if (!portscan_started) {
                    portscan_started = true;
                }
            }
            // Check for an ARP announce
            if (is_nonzero_mem(sniffer.arp_packet->sender_hardware_address, 6) &&
                is_zero_mem   (sniffer.arp_packet->sender_protocol_address, 4) &&
                is_zero_mem   (sniffer.arp_packet->target_hardware_address, 6) &&
                sniffer.arp_packet->operation == 1)
            {
                if (ip_determined) continue;
                ip_determined = true;
                
                //main_log.printf("ARP Announce Received:");
                my_ip = your_ip = *(IP_Address*)sniffer.arp_packet->target_protocol_address;
                main_log.printf("Host IP: %03d.%03d.%03d.%03d", my_ip.octet[0],my_ip.octet[1],my_ip.octet[2],my_ip.octet[3]);
                do { my_ip.octet[3]++; } while (!my_ip.octet[3]);
                main_log.printf("Tool IP: %03d.%03d.%03d.%03d", my_ip.octet[0],my_ip.octet[1],my_ip.octet[2],my_ip.octet[3]);
                
                Ethernet_MAC *targmac = (Ethernet_MAC*)sniffer.arp_packet->target_hardware_address;
                IP_Address   *targip  = (IP_Address*)sniffer.arp_packet->target_protocol_address;
                Ethernet_MAC *srcmac  = (Ethernet_MAC*)sniffer.arp_packet->sender_hardware_address;
                IP_Address   *srcip   = (IP_Address*)sniffer.arp_packet->sender_protocol_address;
                
                your_mac = *srcmac;
                
                // Set the ARP options
                *targmac = sniffer.mac;
                *srcmac  = sniffer.mac;
                *targip  = my_ip;
                *srcip   = my_ip; 
                sniffer.arp_packet->operation = 2;
                
                fix_endian_arp(sniffer.arp_packet);
                sniffer.inject(BROADCAST_MAC, ETHERTYPE_ARP, sniffer.arp_packet, sizeof(ARP_Packet));
                
                while (!commands.empty())
                {
                    string command = commands.front();
                    main_log.printf("NetTool> %s", command.c_str());
                    if (command == "ping")
                        ping_timer.attach(&ping, 30);
                    else if (command == "portscan")
                        scanner.start(sniffer.mac, your_mac, my_ip, your_ip);
                    else if (command == "identify")
                        identify();
                    commands.pop();
                }
            }
        }
        else if (sniffer.tcp_packet)
        {
        }
    }
    
    // This shouldn't really happen...
    main_log.printf("Terminating...");
    return 0;
}