An Illegal Method For Improving Search Standings

 

Somebody I know was in need of web visitors; this was about 3 years ago (maybe 5). I thought I'd help her out by writing a web client that would keep connecting to her site in a loop, and submitting a "GET / HTTP" at the end of each loop; the command to get the default web page. After 50 iterations of the GET loop, I decided she should have more visitors then just me. I visited http://packetstormsecurity.org  and downloaded a web client that spoofed ip addresses. After visiting her web site 100 times I thought I should give her a call too see if she was OK with this ethically questionable technique. I was immediately rebuked and was asked to cease and desist.

I've always heard that web activity takes about 3 months to be reflected in a web search; i.e., if a bunch of people visit your website it won't improve your web search standings for about 3 months. I thought I'd test this out by sending a hit to my web site every second for 24 hours; see how long it took to make me rise up in a web search.  I went back to http://packetstormsecurity.org to download that spoofing client again; I didn't find it. I did a search on the word "spoof" (a site search) and came up with an interesting article on how to spoof your ip address when visiting a website; viewable at http://examples.oreilly.de/english_examples/9780596510305/tools/blind-spoof.html

 

This article gets into the nitty grity about how you actually connect  to a web server. I found  this fascinating because I used to write application servers for a living. A client program would connect to my server by (1) create a socket - a file that you transfer data through when communicating to the server (2) Connect to the server's socket (3) issue commands to the server; e.g., a GET command.  The socket would be of type "tcp"; the connect command required this. Here's an example of a client (from the web):

 

Please note that you have to connect to the server with the "connect" command. The "connect" command is required for tcp communication, and tcp communication is required for surfing the net. However, tcp sockets don't allow you to spoof your ip address; you have  to connect with your real ip address. To spoof your ip address you need a raw socket, but there is no connect command for raw sockets. So how do you visit somebody's webpage with a spoofed ip address?  You visit with a raw socket and perform the steps by hand that a connect command does!

If you go back to the blind-spoof.html frame above (2 frames above) you'll see the following code:

 

Packet 1: Client -> Server
          flags: SYN            ("I want to initiate a connection")
          SEQ  : clientnr
Packet 2: Server -> Client
          flags: SYN, ACK       (ACK: The request is being acknowledged)
          SEQ  : servernr
          ACK  : clientnr+1
Packet 3: Client -> Server
          flags: ACK

 

... and that is the connection. So what we need to make a connection with a raw socket is a knowledge of how the web server (or an application server) generates sequence numbers.  This isn't cut and dried. Web servers used to use rules for generating sequence numbers that were easy to predict. E.g., previous to version 3.2, AIX web servers assigned a sequence number that was calculated as an offset from the time of the packet transaction. VAX/VMS had an extremely secure file system, files 11, but used a web server sequence number generation that was easy to predict. Today's web servers use random number generators to calculate sequence number; much more secure then a time offset

It's still possible to spoof today's servers, but you need to analyze the sequence numbers they generate too formulate an algorithm for predicting their sequence numbers. Aside: take a look at eriu.c  You can find this program on the Internet; it's on packetstormsecurity.org eriu.c will show you how to use raw sockets. There are similar examples you can find on the Internet. So the next thing you need to do is create a program that prints out the sequence numbers coming out of port 80 (port 80 is used for HTTP communication - the communication protocol of e web).  You can write a program in the C programming language that can access web packets directly from the network adapter, but you need to incorporate the WinPcap library; http://winpcap.org

After going to http://winpcap.org you need to download the developer's version of WinPcap;  the version that has the includes and libraries you need to call. After installing the developer's version you need to download and install the regular version; i.e., the version that is available by clicking on the download button on the WinPcap home page; the version that contains winpcap.dll - the run time stuff (late binding routines). While your on the home page, click on the documents button; look at WinPcap manual http://www.winpcap.org/docs/docs_412/html/main.html  The "owner's guide" will show you how to use WinPcap, but if you still have problems compiling, take a look at  http://www.rhyous.com/2011/11/12/how-to-compile-winpcap-with-visual-studio-2010/

 

I compiled one of the examples supplied with the developer's version; basic_dump.c  It compiled the first time I tried it, so this is great code. It didn't produce any sequence numbers, so I made some modifications to basic_dump by adding some code I found at http://www.binarytides.com/code-a-packet-sniffer-in-c-with-winpcap/  and voila, sequence numbers! Here's the code:

 

#include <stdafx.h>
#include <pcap.h>                   //I added the WinPCap include directory to the project includes 
#include "winsock2.h"               //need this for the ntohs and ntohl functions
#pragma comment(lib, "ws2_32.lib")  //I added the wpcap.lib library in the project settings but I wasn't sure about how too add this
                                    //so I'm adding the library for winsock here, the old fashioned way
using namespace System;

/* prototype of the packet handler */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

int main()
{
	pcap_if_t *alldevs;
	pcap_if_t *d;
	int inum;
	int i=0;
	pcap_t *adhandle;
	char errbuf[PCAP_ERRBUF_SIZE];
	
	/* Retrieve the device list */
	if(pcap_findalldevs(&alldevs, errbuf) == -1)
	{
		fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
		exit(1);
	}
	
	/* Print the list */
	for(d=alldevs; d; d=d->next)
	{
		printf("%d. %s", ++i, d->name);
		if (d->description)
			printf(" (%s)\n", d->description);
		else
			printf(" (No description available)\n");
	}
	
	if(i==0)
	{
		printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
		return -1;
	}
	
	printf("Enter the interface number (1-%d):",i);
	scanf("%d", &inum);
	
	if(inum < 1 || inum > i)
	{
		printf("\nInterface number out of range.\n");
		/* Free the device list */
		pcap_freealldevs(alldevs);
		return -1;
	}
	
	/* Jump to the selected adapter */
	for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
	
	/* Open the device */
	/* Open the adapter */
	if ((adhandle= pcap_open_live(d->name,	// name of the device
							 65536,			// portion of the packet to capture. 
											// 65536 grants that the whole packet will be captured on all the MACs.
							 1,				// promiscuous mode (nonzero means promiscuous)
							 1000,			// read timeout
							 errbuf			// error buffer
							 )) == NULL)
	{
		fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
		/* Free the device list */
		pcap_freealldevs(alldevs);
		return -1;
	}
	
	printf("\nlistening on %s...\n", d->description);
	
	/* At this point, we don't need any more the device list. Free it */
	pcap_freealldevs(alldevs);
	
	/* start the capture */
	pcap_loop(adhandle, 0, packet_handler, NULL);
	
	pcap_close(adhandle);
	return 0;
}


/* Callback function invoked by libpcap for every incoming packet */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
	struct tm *ltime;
	char timestr[16];
	time_t local_tv_sec;

	typedef struct tcp_header  
 {  
     unsigned short source_port; // source port  
     unsigned short dest_port; // destination port  
     unsigned int sequence; // sequence number - 32 bits  
     unsigned int acknowledge; // acknowledgement number - 32 bits  
    

     unsigned char ns :1; //Nonce Sum Flag Added in RFC 3540.  
     unsigned char reserved_part1:3; //according to rfc  
     unsigned char data_offset:4; /*The number of 32-bit words in the TCP header.  
     This indicates where the data begins.  
     The length of the TCP header is always a multiple  
     of 32 bits.*/ 

     unsigned char fin :1; //Finish Flag  
     unsigned char syn :1; //Synchronise Flag  
     unsigned char rst :1; //Reset Flag  
     unsigned char psh :1; //Push Flag  
     unsigned char ack :1; //Acknowledgement Flag  
     unsigned char urg :1; //Urgent Flag  
   
     unsigned char ecn :1; //ECN-Echo Flag  
     unsigned char cwr :1; //Congestion Window Reduced Flag  
    
     unsigned short window; // window  
     unsigned short checksum; // checksum  
     unsigned short urgent_pointer; // urgent pointer  
 } TCP_HDR;  

/* Ip header (v4)  */
 typedef struct ip_hdr  
 {  
     unsigned char ip_header_len:4; // 4-bit header length (in 32-bit words) normally=5 (Means 20 Bytes may be 24 also)  
     unsigned char ip_version :4; // 4-bit IPv4 version  
     unsigned char ip_tos; // IP type of service  
     unsigned short ip_total_length; // Total length  
     unsigned short ip_id; // Unique identifier  
   
     unsigned char ip_frag_offset :5; // Fragment offset field  
    
     unsigned char ip_more_fragment :1;  
     unsigned char ip_dont_fragment :1;  
     unsigned char ip_reserved_zero :1;  
    
     unsigned char ip_frag_offset1; //fragment offset  
    
     unsigned char ip_ttl; // Time to live  
     unsigned char ip_protocol; // Protocol(TCP,UDP etc)  
     unsigned short ip_checksum; // IP checksum  
     unsigned int ip_srcaddr; // Source address  
     unsigned int ip_destaddr; // Source address  
 } IPV4_HDR;  
    
/* Ethernet Header  */
 typedef struct ethernet_header  
 {  
     UCHAR dest[6];  
     UCHAR source[6];  
     USHORT type;  
 }   ETHER_HDR;  
   
 ETHER_HDR *ethhdr;  
 IPV4_HDR *iphdr;  
 TCP_HDR *tcpheader;  
 unsigned char iphdrlen = 0;
 unsigned int sequence = 0;
 unsigned int ack = 0;
 unsigned short dest_port = 0;
 unsigned short source_port = 0;

	/*
	 * unused parameter
	 */
	(VOID)(param);

	/* Get the sequence number from pkt_data */
	iphdr = (IPV4_HDR *) (pkt_data + sizeof(ETHER_HDR));
	iphdrlen = iphdr->ip_header_len*4;
	tcpheader = (TCP_HDR*) (pkt_data +iphdrlen + sizeof(ETHER_HDR));
	if (tcpheader != NULL) 
	{
	   sequence = ntohl(tcpheader->sequence);
	   ack = ntohl(tcpheader->acknowledge);;
	   source_port = ntohs(tcpheader->source_port);
	   dest_port = ntohs(tcpheader->dest_port);
	}
	else
	{
		sequence = -1;
		ack = -1;
		source_port = 80;
		dest_port = 80;
	}

	/* convert the timestamp to readable format */
	local_tv_sec = header->ts.tv_sec;
	ltime=localtime(&local_tv_sec);
	strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
	
	//I just want info from web connections - filtering for port 80
	if ((dest_port == 80) || (source_port == 80))
	{
	   printf("%s,%.6d len:%d, seqnbr:%u, acknbr:%u, source_port:%u, dest_port:%u\n", timestr, header->ts.tv_usec, header->len, sequence, ack, source_port, dest_port);
	}
}
 

Getting back to the title of this article; improving your search standings. Run this program on the system where your web server runs; in my case, Serval. You need to write a spoofing client that lets you enter sequence numbers by hand during the handshake (connect) process; in my case on Caprica. Adding, say 100 web hits/day this way is quite possible, and can significantly improve the ranking of a personal home page.

Return To My Blog Page       Return To My Programming Page