예제 #1
0
void main(int argc, char** argv)
{
    if(geteuid() != 0)
    {
        fprintf(stderr, "You need root permissions\n");
        exit(1);
    }

    //TODO : Add a debug mode
    char* interface;
    if(argc > 1)
        interface = argv[1];
    else
    {
        fprintf(stderr, "Please specify network interface to use\n");
        exit(1);
    }

//    printf("Interface = %s\n", interface);

    int sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
	
	//Set receive timeout
	struct timeval tv;
	tv.tv_usec = 0;
	tv.tv_sec = 10; //10 seconds in case of latency on the network
	setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

    //retrieve ethernet NIC index and HW address
    struct hw_eth_iface iface = find_iface(sock, interface); // TODO : Check interface existency, and print a list of possible NIC

    struct sockaddr_ll target;
    memset(&target, 0, sizeof(target));
    target.sll_family   = PF_PACKET;
    target.sll_protocol = htons(ETH_P_IP);
    target.sll_ifindex  = iface.index;
    target.sll_hatype   = ARPHRD_ETHER;
    target.sll_pkttype  = PACKET_HOST;
    target.sll_halen    = ETH_ALEN;

    memset(target.sll_addr, 0xff, 6);

    char buffer[BUFF_SIZE];

//    struct dhcp_pkt *dhcp = (struct dhcp_pkt*)(buffer + sizeof(struct udpheader) + sizeof(struct ipheader));
    struct dhcp_pkt dhcp;
    int dhcp_len = build_dhcp_discover(&dhcp, iface.hw_addr, iface.addr_len);

    int len = build_ip4_udp_pkt(buffer, BUFF_SIZE, (unsigned char*)&dhcp, dhcp_len, "0.0.0.0", "255.255.255.255", 68, 67, IPPROTO_UDP);

	//Send the packet over the network
    if(sendto(sock, buffer, len, 0, (struct sockaddr *)&target, sizeof(target)) < 0)
    {
        perror("Error while writing to socket");
        exit(1);
    }

	//Now, wait for the server response, and read it

receive:
    memset(buffer, 0, BUFF_SIZE);

	//Read a packet
    int read_len = recvfrom(sock, buffer, BUFF_SIZE, 0, NULL, NULL);
    if(read_len <= 0)
    {
        perror("Cannot read");
        exit(1);
    }

    struct ipheader *rip   = (struct ipheader*) buffer;
    struct udpheader *rudp = (struct udpheader*)(buffer + sizeof(struct ipheader));
    struct dhcp_pkt *rdhcp = (struct dhcp_pkt*)(buffer + sizeof(struct udpheader) + sizeof(struct ipheader));

    //Check packet validity
	// if dest port isn't our or packet is not a dhcp one, drop the packet
    if(rip->iph_protocol != IPPROTO_UDP || rudp->udph_destport != htons(68) || !is_dhcp(rdhcp) || rdhcp->op != OP_BOOT_REPLY)
        goto receive;

//    printf("Data Recieved, length = %d\n", read_len);

	//Find the IP attributed to us by the server
    struct in_addr raddr;
    raddr.s_addr = rdhcp->yi_addr;

    printf("IPADDR=%s\n", inet_ntoa(raddr));

	//Now check DHCP options, and process them
    struct dhcp_opt *opt = NULL;
    int offs = 0;
    opt = get_dhcp_option(rdhcp, &offs);
    while(opt != NULL)
    {
//        printf("OPT FOUND offset = %d\n", offs);
        switch(opt->id)
        {
            case OPTION_ROUTER: // If the option is the gateway address
				if(opt->len == 4)
				{
					raddr.s_addr = char_to_ip(opt->values);
					printf("GATEWAY=%s\n", inet_ntoa(raddr));
				}
                break;

            case OPTION_SUBNET_MASK: // If the option is the netwmask
				if(opt->len == 4)
				{
					raddr.s_addr = char_to_ip(opt->values);
					printf("NETMASK=%s\n", inet_ntoa(raddr));
				}
                break;

            case OPTION_DNS: // If option is the DNS addresses
				if(opt->len % 4 == 0)
				{
					int i = 0;
					printf("NAMESERVER=");
					int max = opt->len / 4;
					for(i = 0; i < max; i++)
					{
						raddr.s_addr = char_to_ip(opt->values + 4*i);
						printf("%s", inet_ntoa(raddr));
						if(i < max - 1)
							printf(",");
					}
					printf("\n");
				}
                break;

            default:
                break;
        }
        opt = get_dhcp_option(rdhcp, &offs);
    }

    close(sock);
    exit(0);
}
예제 #2
0
void dhcp_reply(struct dhcp_packet *p, struct sockaddr* client_address, socklen_t client_addrlen)
{
	int packet_len;
	u_char *opt;
	u_char optlen;
	struct dhcp_packet re;
	int res;

	DBG("dhcp_reply start");

	if (check_dhcp_packet(p) == -1) {
		DBG("got a invalid dhcp packet");
		return;
	}
	if (get_dhcp_message_type(p) == DHCPDISCOVER) {
		DBG("got a DHCPDISCOVER on dhcp");
	} else {
		DBG("got a non-DHCPDISCOVER dhcp packet");
		return;
	}

	/* check vendor class identifier ("PXEClient") */
	res = get_dhcp_option(p, DHO_VENDOR_CLASS_IDENTIFIER, &opt, &optlen);
	if (res == -1 || strncmp((char*)opt, PXE_IDENTIFIER_STRING, strlen(PXE_IDENTIFIER_STRING)) != 0) {
		LOG("got a non-PXE dhcp packet");
		return;
	}

	/* create response */
	init_packet(&re, p, DHCPOFFER);
	/* re.ciaddr is 0.0.0.0 */
	/* re.yiaddr is 0.0.0.0 */
	re.siaddr = tftp_ip;
	memcpy(re.chaddr, p->chaddr, sizeof(re.chaddr));
	strcpy(re.file, nbp_name);

	/* set vendor class identifier */
	res = add_dhcp_option(&re, DHO_VENDOR_CLASS_IDENTIFIER,
		(u_char*)PXE_IDENTIFIER_STRING,
		strlen(PXE_IDENTIFIER_STRING)+1);
	if (res == -1) {
		DBG("add_dhcp_option() failed");
		return;
	}

	/* set vendor options */
	{
		u_char vop[3];
		vop[0] = PXE_DISCOVERY_CONTROL;
		vop[1] = 1;
		vop[2] = PXE_DISCOVERY_CONTROL_BIT3;
		if (add_dhcp_option(&re, DHO_VENDOR_ENCAPSULATED_OPTIONS, vop, 3) == -1) {
			DBG("add_dhcp_option() failed");
			return;
		}
	}

	/* send the response */
	packet_len = get_dhcp_packet_len(&re);
	res = sendto(server_socket, &re, packet_len, 0,
		(struct sockaddr*)&bcast_address, sizeof(bcast_address));
	if (res != packet_len) {
		LOG("sendto() failed or was not complete: %s", strerror(errno));
		return;
	}

	DBG("dhcp_reply end");
}
예제 #3
0
/*
 * parses the request and send the spoofed reply
 */
static void dhcp_spoofing_req(struct packet_object *po)
{
   char dhcp_hdr[LIBNET_DHCPV4_H];
   struct libnet_dhcpv4_hdr *dhcp;
   u_int8 *options, *opt, *end;
   struct ip_addr client, server;
   char tmp[MAX_ASCII_ADDR_LEN];
   
   DEBUG_MSG("dhcp_spoofing_req");

   /* get a local copy of the dhcp header */
   memcpy(dhcp_hdr, po->DATA.data, LIBNET_DHCPV4_H);

   dhcp = (struct libnet_dhcpv4_hdr *)dhcp_hdr;

   /* get the pointers to options */
   options = po->DATA.data + LIBNET_DHCPV4_H;
   end = po->DATA.data + po->DATA.len;

   /* use the same dhcp header, but change the type of the message */
   dhcp->dhcp_opcode = LIBNET_DHCP_REPLY;

   /* 
    * if the client is requesting a particular IP address,
    * release it. so we don't mess the network too much...
    * only change the router ip ;)
    */

   /* get the requested ip */
   if ((opt = get_dhcp_option(DHCP_OPT_RQ_ADDR, options, end)) != NULL)
      ip_addr_init(&client, AF_INET, opt + 1);
   else {
      /* search if the client already has the ip address */
      if (dhcp->dhcp_cip != 0) {
         ip_addr_init(&client, AF_INET, (u_char *)&dhcp->dhcp_cip);
      } else
         return;
   }
  
   /* set the requested ip */
   dhcp->dhcp_yip = ip_addr_to_int32(&client.addr);
  
   /* this is a dhcp ACK */
   dhcp_options[2] = DHCP_ACK;
   
   /* 
    * if it is a request after an offer from a server,
    * spoof its ip to be stealth.
    */
   if ((opt = get_dhcp_option(DHCP_OPT_SRV_ADDR, options, end)) != NULL) {
      /* get the server id */
      ip_addr_init(&server, AF_INET, opt + 1);
   
      /* set it in the header */
      dhcp->dhcp_sip = ip_addr_to_int32(&server.addr);

      /* set it in the options */
      ip_addr_cpy((u_char*)dhcp_options + 5, &server);
   
      send_dhcp_reply(&server, dhcp_addr_reply(&po->L3.src), po->L2.src, (u_char*)dhcp_hdr, (u_char*)dhcp_options, dhcp_optlen);
      
   } else {
      /* 
       * the request does not contain an identifier,
       * use our ip address
       */
      dhcp->dhcp_sip = ip_addr_to_int32(&GBL_IFACE->ip.addr);
      
      /* set it in the options */
      ip_addr_cpy((u_char*)dhcp_options + 5, &GBL_IFACE->ip);
   
      send_dhcp_reply(&GBL_IFACE->ip, dhcp_addr_reply(&po->L3.src), po->L2.src, (u_char*)dhcp_hdr, (u_char*)dhcp_options, dhcp_optlen);
   }

   USER_MSG("DHCP spoofing: fake ACK [%s] ", mac_addr_ntoa(po->L2.src, tmp));
   USER_MSG("assigned to %s \n", ip_addr_ntoa(&client, tmp));
}