With SetFlags and SetIdentification set in IP, IP identification not honored

38 views
Skip to first unread message

Kelly Roestel

unread,
Jan 10, 2014, 4:55:39 PM1/10/14
to libcr...@googlegroups.com
First, I want to thank everyone that wrote this library, so far it has proven invaluable.

No for my problem( See my code below):

I am trying to set the IP Identification to 0x0000 and the IP flags to 0x00.  However, when I set the IP flags it libcrafter does not honor the setting of IP Identification.  If I do not set the IP flags, the Identification is honored.  Most of this code is from http://code.google.com/p/libcrafter/wiki/DNSQuery, with my modification below defined by the asterisk.  My question is what am I doing wrong to have the ip_header.SetIdentification not be honored? 

Thank you for any response.


        /* Create an IP header */
        IP ip_header;

        /* Set the Source and Destination IP address */
        ip_header.SetSourceIP(MyIP);
        ip_header.SetDestinationIP(dns_server);
        *ip_header.SetDiffServicesCP(0x04); 
        *ip_header.SetFlags(0x00);
        *ip_header.SetIdentification(0x0000);



 and


        /* Create a packet... */
        *ip_header.Print();
        Packet packet = ip_header / udp_header / dns_header;


Esteban Pellegrino

unread,
Jan 11, 2014, 10:52:03 AM1/11/14
to libcr...@googlegroups.com
That's because when you craft a packet from the IP layer to the top like :

Packet packet = ip_header / udp_header / dns_header;

the underlaying engine on libcrafter use RAW SOCKETS to write the packet on the wire. When you set those fields to NULL you are telling the kernel to fill the values with default ones, which I guess is a random number for the ID and some other for the flags field... Is something that can't be controlled with libcrafter, is how your current system works.

However, if you want to have full control on the values of the field, you should use PACKET SOCKETS. To do that, you need to craft packets using the ethernet layer also... Something like :

Packet packet = ether_header / ip_header / udp_header / dns_header;

The only problem is that you will need to craft the ethernet header by setting the destination MAC addresses. You can use libcrafter to so that also. The full code will be :


#include <iostream>
#include <string>
#include <crafter.h>

/* Collapse namespaces */
using namespace std;
using namespace Crafter;

int main() {

       
/* Set the interface */
       
string iface = "wlan0";

       
/* Get the IP address associated to the interface */
       
string MyIP = GetMyIP(iface);
       
string dns_server = "192.168.0.1";

        /* Create Ethernet layer */

        Ethernet ether_header;

        ether_header
.SetSourceMAC(
GetMyMAC(iface));  
        ether_header
.SetDestinationMAC(
GetMAC(
dns_server, iface));  


       
/* Create an IP header */

        IP ip_header
;

       
/* Set the Source and Destination IP address */
        ip_header
.SetSourceIP(MyIP);
        ip_header
.SetDestinationIP(dns_server);

        ip_header.SetDiffServicesCP(0x04); 
        ip_header.SetFlags(0x00);
        ip_header.SetIdentification(
0x0000);

        /* Create a UDP header */
        UDP udp_header
;

       
/* Set the source and destination ports */
        udp_header
.SetSrcPort(RNG16());
        udp_header
.SetDstPort(53);

       
/* Create a DNS layer */
        DNS dns_header
;

       
/* Set a random ID */
        dns_header
.SetIdentification(RNG16());

       
/* Create a DNSQuery class. This class IS NOT a <Layer> class */
        DNS
::DNSQuery dns_query("www.google.com");
       
/* Set the type */
        dns_query
.SetType(DNS::TypeA);

       
/* Push the query into a container inside the DNS header */
        dns_header
.Queries.push_back(dns_query);


       
/* Create a packet... */

       
Packet packet =
ether_header / ip_header / udp_header / dns_header;

       
/* Send and wait for an answer */
       
Packet* rcv = packet.SendRecv(iface);

       
if(rcv) {
               
/*
                 * An application protocol is always get from the network as a raw layer. There is
                 * no way to know which protocol is on the top of a transport layer (unless we rely on
                 * standard ports numbers, which is not always the case).
                 */

                DNS dns_rcv
;
               
/* Fill the DNS layer information from a raw layer */
                dns_rcv
.FromRaw(*(rcv->GetLayer<RawLayer>()));
               
/* Finally print the response to STDOUT */
                dns_rcv
.Print();
               
/* Delete the received packet */
               
delete rcv;
       
} else
                cout
<< "[@] No response from DNS server" << endl;

       
return 0;
}

Be aware that if the the DNS server is not on your current internal network, the destination MAC address on the ethernet header should be the MAC address of your current default gateway.


--
You received this message because you are subscribed to the Google Groups "libcrafter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to libcrafter+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Esteban Pellegrino

unread,
Jan 11, 2014, 10:55:09 AM1/11/14
to libcr...@googlegroups.com
Please look at man 7 packet and man 7 raw to see the difference between raw sockets and packet socket. When you craft packets in libcrafter starting with the IP layer you are using raw sockets, and when you start with any other layer you are using packet sockets

Kelly Roestel

unread,
Jan 13, 2014, 3:28:02 PM1/13/14
to libcr...@googlegroups.com
Thank you for the help.  This solved my problem
Reply all
Reply to author
Forward
0 new messages