doubt with libcrafter and layers

240 views
Skip to first unread message

sogico

unread,
Jul 18, 2012, 3:31:05 AM7/18/12
to libcr...@googlegroups.com
Hi,

I don't know if there is someone here but I do ask anyway. I am using libcrafter because I need to sniff packets leaving internet browser in order to add some propietary layers that we are testing for a new hardware. I capture those packets with a sniffer and then I need to get all the layers above Ethernet. How can I do this?

I thought that if I get the Ethernet Layer I would have the above layers inside the payload but that isn't right, is it?

Thank you


Esteban Pellegrino

unread,
Jul 18, 2012, 9:02:26 AM7/18/12
to libcr...@googlegroups.com
Hi!

The payload of a layer in libcrafter is not made by the layers. The payload is a part of a layer that has variable size. Is like a "field" of variable size that was added to provide more flexibility to the layer. For example is were the DNS queries/responses are saved, is where the DHCP options are saved, etc (is different from scapy)

There are a lot of ways to access to layers within a packet. Depends on what you want to do. If you give me a simple snippet of your code, I could be of more help.

You can access the layers one by one,
TCP* tcp_layer = sniff_packet->GetLayer<TCP>()
IP* tcp_layer = sniff_packet->GetLayer<IP>()
ICMP* tcp_layer = sniff_packet->GetLayer<ICMP>()

Using iterators,
LayerStack::const_iterator it = sniff_packet->begin() + 1; /* <-- If you know that the 1st one is Ethernet */
for(; it != sniff_packet->end() ; it++)
   
/* (*it) gives a pointer to the layer */
    DoSomething
( *(*it) );

Or using the [] operator, very similar to iterators.

I don't know which version you are using, but I recommend you to use the latest one in the git tree (fed14827a...). You have a few more features than the 0.2 version. For example, you can discard the Ethernet layer, and create a "subpacket" with the layers above.
Packet above_ether = sniff_packet->SubPacket(sniff_packet->begin() + 1, sniff_packet->end());
/* <above_ether> packet will have = IP / TCP / Whatever... , without the link layer */

I know there is not much documented, so don't hesitate to ask here any questions/doubts you may have.

sogico

unread,
Jul 19, 2012, 8:02:37 AM7/19/12
to libcr...@googlegroups.com
I got problems installing the version from repository...:S If I can later I will post you the concrete error that I get.

I have two virtual machines running on my computer (VM1 and VM2).
                                                                    
eth0 (PC) ------------------------ vboxnet1 (PC) ----------eth0 (Virtual Machine 1) --------eth1 (Virtual Machine 1) --------eth0 (Virtual Machine 2)

In VM2 I run an internet browser and in eth1 of VM1 I capture the packets generated by the browser. In VM1 I have to add to the IP packets received some lower layer propietary protocols and send through eth0 of VM1. Then in my PC I have to undo the process and remove the lower layers in order to send my packets through internet.

I've configured the interfaces as follows:
eth0(PC): 192.168.1.190/24
vboxnet1(PC):192.168.23.1/24
eth0(VM1):192.168.23.2/24
eth1(VM1):192.168.57.1/24
eth0(VM2):192.168.57.2/24

In VM1 there isn't any route between eth0 and eth1 because I want to control the net connection of the browser, enabling and disabling it when I want.
In PC there is a route with 192.168.57.0/24.

I am trying a first test that consists on:
-> ping www.google.es from my VM2
->capture the packets with libcrafter in VM1 (eth1)
->resend the packet with libcrafter in VM1(eth0)
->capture the ping response in VM1(eth0)
->resend the respone in VM!(eth1)
->receive the ping response in VM2

But I don't receive the response in VM2. However, if I use wireshark on eth0(VM1) I can prove that I am receiving ARP messages with the content:
Who is 192.168.57.2? Tell 192.168.23.1.

And in eth1(VM1) I receive malformed packets. :S

Any idea??

My program test is this:

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


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



void SendToSocket_Femto(Packet* sniff_packet, void* user)
{
    //Print the packet intercepted
    cout << "Packet captured " << endl;

    /* Print Packet Information */
    cout << "Before sending" << endl;
    if(sniff_packet)
        sniff_packet->Print();

    /* Get the Payload of the Ethernet Packet */
    Ethernet *mypacket_eth = sniff_packet->GetLayer<Ethernet>();
    cout << "GetLayer de EthLayer" << endl;
    if(sniff_packet)
    {
        mypacket_eth->Print();
        cout << "Paquete ethernet, me quedo con las capas superiores" << endl;


        LayerStack::const_iterator it = sniff_packet->begin() + 1; /* <-- If you know that the 1st one is Ethernet */

        Packet resend_p;
        if(sniff_packet->begin() < sniff_packet->end())
        {

            for(; it != sniff_packet->end() ; it++)
            {
                /* (*it) gives a pointer to the layer */
                resend_p.PushLayer( *(*it) );
            }

            //Reenvio el paquete
            resend_p.Send("eth0");
            resend_p.Print();
            cout << "Tras enviar" << endl;
        }


    }
}





void SendToSocket_App(Packet* sniff_packet, void* user)
{
    //Print the packet intercepted
    cout << "Packet captured in eth0" << endl;

    /* Print Packet Information */
    cout << "Before sending" << endl;
//    if(sniff_packet)
//        sniff_packet->Print();

    /* Get the Payload of the Ethernet Packet */
    Ethernet *mypacket_eth = sniff_packet->GetLayer<Ethernet>();
    cout << "GetLayer de EthLayer" << endl;
    if(sniff_packet)
    {
        mypacket_eth->Print();
        //cout << "Paquete ethernet, me quedo con las capas superiores" << endl;


        LayerStack::const_iterator it = sniff_packet->begin() + 1; /* <-- If you know that the 1st one is Ethernet */

        Packet resend_p;
        if(sniff_packet->begin() < sniff_packet->end())
        {

            for(; it != sniff_packet->end() ; it++)
            {
                /* (*it) gives a pointer to the layer */
                if(*it->)
                resend_p.PushLayer( *(*it) );
            }

            //Reenvio el paquete
            resend_p.Send("eth1");
            //resend_p.Print();
            //cout << "Tras enviar" << endl;
        }


    }

}


int main()
{
   
    /* Init the library */
    InitCrafter();

    /* Set the interface */
    string eth1 = "eth1";
    string eth0 = "eth0";

    /*
     * First, you should create a sniffer
     * - 1st argument: Filter expression (tcpdump syntax)
     * - 2nd argument: Interface
     * - 3rd argument: A function that will be executed when a packet
     * captured satisfies the filter expression (the default behavior is to
     * print the packets to STDOUT).
     */


    //Sniffer sniff("tcp and dst port 80",iface,PacketHandler);
    Sniffer sniff_eth1("src host 192.168.57.2 and dst host 8.8.8.8",eth1,SendToSocket_Femto);
    Sniffer sniff_eth0("",eth0,SendToSocket_App);

    /* Spawn the sniffer (ad-infinitum) */
    sniff_eth1.Spawn(-1);
    sniff_eth0.Spawn(-1);

    while(1);

    /* Shut down cleanly the sniffer */
    sniff_eth1.Cancel();

    /* Clean up library stuff... */
    CleanCrafter();

    return 0;

Esteban Pellegrino

unread,
Jul 19, 2012, 8:48:51 PM7/19/12
to libcr...@googlegroups.com
On Thu, Jul 19, 2012 at 9:02 AM, sogico <sgimen...@gmail.com> wrote:
I got problems installing the version from repository...:S If I can later I will post you the concrete error that I get.

Did you run ./autogen.sh  before configuring libcrafter? Like

$ ./autogen.sh && ./configure && make && sudo make install
 
I have two virtual machines running on my computer (VM1 and VM2).
                                                                    
eth0 (PC) ------------------------ vboxnet1 (PC) ----------eth0 (Virtual Machine 1) --------eth1 (Virtual Machine 1) --------eth0 (Virtual Machine 2)

In VM2 I run an internet browser and in eth1 of VM1 I capture the packets generated by the browser. In VM1 I have to add to the IP packets received some lower layer propietary protocols and send through eth0 of VM1. Then in my PC I have to undo the process and remove the lower layers in order to send my packets through internet.

I've configured the interfaces as follows:
eth0(PC): 192.168.1.190/24
vboxnet1(PC):192.168.23.1/24
eth0(VM1):192.168.23.2/24
eth1(VM1):192.168.57.1/24
eth0(VM2):192.168.57.2/24

In VM1 there isn't any route between eth0 and eth1 because I want to control the net connection of the browser, enabling and disabling it when I want.
In PC there is a route with 192.168.57.0/24.

I am trying a first test that consists on:
-> ping www.google.es from my VM2
->capture the packets with libcrafter in VM1 (eth1)
->resend the packet with libcrafter in VM1(eth0)
->capture the ping response in VM1(eth0)
->resend the respone in VM!(eth1)
->receive the ping response in VM2

But I don't receive the response in VM2. However, if I use wireshark on eth0(VM1) I can prove that I am receiving ARP messages with the content:
Who is 192.168.57.2? Tell 192.168.23.1.

And in eth1(VM1) I receive malformed packets. :S

Any idea??


The libcrafter part is OK. A few observations:

1. There is no need to check the sniff_packet pointer on the Sniffer "callback" function. If that function is executed is because a packet was captured a that pointer is pointing to a valid object. Of course, check it makes no harm, but you could end up with a cleaner code.

2. When you use Send, the packet is sent with the original IP header. Is not going to "update" the packet with the source IP address of the local machine. So, if you capture a packet that was sent from another machine *I THINK* you should update the IP header before send it again i.e. put the source IP address of the machine where you capture the packet. Is that correct or I'm missing something?

sogico

unread,
Jul 23, 2012, 5:05:40 AM7/23/12
to libcr...@googlegroups.com
It's ok. Thank you, now it works. :)

Now I only have to filter because I receive a lot of duplicated packets, because packets sent in one interface are captured again and sent to the other interface creating a loop :o

Thank you!

sogico

unread,
Jul 23, 2012, 7:54:19 AM7/23/12
to libcr...@googlegroups.com
Now I have another question. I've achieved filtering and now I can do ping from VM2 to outside (Internet) and with no duplicates. But I think I am missing something or I am composing wrong packets because I can't access Internet in a browser from VM2. I capture packets with Wireshark and I can see some TCP retransmission packets and as a response of the server, a RST TCP packet that resets my connection.

Do you think this can be related to malformed packets? Why my TCP packets are marked as retrasmission? How the server knows I am retrasmitting the packets?

Thank you!!

Esteban Pellegrino

unread,
Jul 23, 2012, 10:56:01 AM7/23/12
to libcr...@googlegroups.com
The retransmission thing is a wireshark interpretation of the communication, I think you can disable that on the menu. I think that happens when a TCP seq-ack packet is repeated.

Anyway, I don think the RST packet is related to malformed packets. The problem on this approach is that you are trying to establish a TCP connection on kernel's back on VM1 and on the machine where you send the packet to internet. All the TCP packets generated on VM2 are captured on subsequent machines with the IP layer modified, and the kernel on those machines will reset the connection because was not established in a normal way (through sockets).

As a final step, I think you'll need to work a bit with iptables on those machine to tell the kernel to stay out of your way on this TCP connection. What is probably happening here is that VM1 or PC's kernel reset the connection to the server, and from VM2 you are trying to continue a connection that was reseted (i.e. no longer exists on the server).

I think that's why you are capturing RST packets on VM2. For example, if the server IP is 3.3.3.3 (the one VM2's browser connects to) and the port is 80, you can add a rule on VM1 and PC  like:

/sbin/iptables  -A INPUT -s 3.3.3.3 -p tcp --sport 80 -j DROP

This means that all packets coming from 3.3.3.3:80 should be ignored by the kernel. Remember that libcrafter doesn't mind about local firewalls rules... You still can catch those packet with libcrafter's sniffer.

sonali...@gmail.com

unread,
Jul 14, 2014, 11:59:14 PM7/14/14
to libcr...@googlegroups.com


I have this error while  installation  of libracrafter
 
[root@localhost crafter-0.3]# sudo apt-get install libpcap0.8 libpcap0.8-dev
sudo: apt-get: command not found

    plz rply me solution for this
Reply all
Reply to author
Forward
0 new messages