<- HOME

Proxy Tunneling Engine Class for C++

Tunneling proxy (also known as 'Proxy Chaining') servers is a kinda old technique, but effective way to make yourself hard to trace. Even if you tunnel with 5 proxies deep it would be a hell of a job to find out the attackers real IP.
I'm not going to explain how this technique works because there are enough docs about this on the Net.
One of the reason is that most proxy servers are misconfigured so they dont even log you request.
The class code below allows you to expand your private tools or other code projects to support proxy tunneling by simply setting some parameters, like the path to your proxy file.

To use the class, save the code below to a file (e.g tunnel.h), put it in the same location as your project files, and enter in your main project file '#include "tunnel.h".

After doing that, declare a variable with the class, like:
tunnelengine engine;

Now we need to initialize the engine with:
engine.SetOptions(char *ProxyFileName,bool LogToScreen);

Proxyfilename=full path to the proxy file on your harddrive (e.g C:\\proxylist.txt)
Note: Proxy list file must be in the format of host:port<enter>host:port<enter> etc..
LogToScreen =Print out log and statics info with printf()

After the engine is initialized, order the engine to parse the enteries in the proxylist:
engine.ParseProxyList(); //Returns false on failure

After the list is parsed, we can begin to built the tunnel by calling StartTunnel:
engine.StartTunnel(int levelsdeep,int beginindex)

levelsdeep=How long will the tunnel be, how many proxies??
beginindex=the proxy that will begin the tunnel, use 1 for the first proxy in the list

This function returns true if all proxies are chained together and the tunnel is ready for data transmission.

Now we can connect to our final host by calling ConnectToFinalHost:
engine.ConnectToFinalHost(char *RemHost,int RemPort);

RemHost=Pointer to the remotehost (e.g microsoft.com)
RemPort=Remote port of host (e.g 80 for HTTP)

ConnectToFinalHost returns true on success.

Alright, now the tunnel is all set up and ready to receive/send.

Sending data:

engine.SendData(char *What);

What=Pointer to buffer to send through the tunnel to the remote host

Receiving data:

engine.ReadData(char *RecvBuf,int ReceiveSize)

RecvBuf=Pointer to the buffer that receives the data.
ReceiveSize=Size of the RecvBuffer (doing sizeof(RecvBuffer) didnt work for me )


Thats it, now j00r exploits will see the light =)


**********Begin of tunnel.h*************

#include <fcntl.h>
#include <io.h>
#include <malloc.h>
#include <string.h>
#include <winsock.h>
#include <stdlib.h>

/*
Proxy Tunnel Engine Class by dataholic <pinheadONLYSHEMALESPAM@cis.tzo.com>
<Today is a good day to die>

This sourcecode is public domain, you may fuck it up however you like but dont forget to give the author a fucking credit!

Greetz to all people @ BOX Network, WoH [ [RaFa], here's your proxy support where you asked GOBBLES for, hehe, peace], GOBBLES [nice apache exploit,God bless], eEye.

This computer program may not be distributed for commercial purposes without permission from the author or from the local shemale bar.

Script kidz can exploit apache by GOBBLES, now script kidz can use http tunnels,
/me grins bastardly @ FBI

This code is made for use on Win32 , but should not be hard to port to other platforms since i didnt use 'fancy' win32 functions.

Win32 note: DONT forget to call WsaStartup first!!!
i'm doing C/C++ for 6 months, so this is not elite code , but hey! it works! so stfu!
*/

class tunnelengine
{
private: // vars are kept private, do i look like a pimp?

struct PROXY
{
char *host;
int port;

};


char ProxyFile[500];
bool PrintLog;
int proxiescount;
PROXY proxies[1000];
char FinalHost[500];
int FinalPort;
SOCKET sock; //global proxy socket

public:

void SetOptions(char *ProxyFileName,bool LogToScreen)
{
//LogToScreen, send statics to screen with printf, yes or no (true/false)
PrintLog = LogToScreen;

if ( PrintLog == true ) printf("Proxy Tunnel Engine , (c) 2002 by dataholic \n");
if ( PrintLog == true ) printf("Initializing engine. . .\n");


sprintf(ProxyFile,"%s",ProxyFileName);

if ( PrintLog == true ) printf("Initialized.\n");

}


int ParseProxyList()
{

if ( PrintLog == true ) { printf("Loading proxylist...");}


int hFile;
int pos,poscomma;
long filelen;
char *pdest1,*pdest2,*entery;
char *buffer;


SetFileAttributes(ProxyFile,FILE_ATTRIBUTE_NORMAL); /*My other "mass proxychecker" tool used to write bad attributes because of a bug, so thats why i set the file attribs to normal*/

hFile = _open(ProxyFile,_O_RDONLY);

if ( hFile == -1 )
{
if ( PrintLog == true ) printf("Error reading proxy file.\n");
return false;
}


filelen = _filelength(hFile);

if ( filelen < 10 )
{
if ( PrintLog == true ) printf("zero byte proxy file or filesize too small\n");
return false;
}


buffer = (char*) malloc(filelen+1);
_read(hFile,buffer,filelen);

buffer[filelen]=0;


//Parse list...
proxiescount=0;

while (1)
{

pdest1 = strstr(buffer,"\n");
if ( pdest1 == NULL ) { goto done;}

pos = pdest1 - buffer;


entery = (char*) malloc(pos);

strncpy(entery,buffer,pos);
entery[pos] =0;

pdest2 = strstr(entery,":");
if ( pdest2 == NULL ) { goto trynext;}
poscomma = pdest2 - entery +1;


proxiescount++;

proxies[proxiescount].host = (char*) malloc(poscomma -1);

strncpy(proxies[proxiescount].host,entery,poscomma-1);
proxies[proxiescount].host[poscomma-1]=0;


//printf("%s port %s\n",proxies[proxiescount].host,entery + poscomma );
proxies[proxiescount].port = atoi(entery+poscomma);

trynext:

buffer = buffer + (pos+1);
}


done:
if ( PrintLog == true )
{
printf("completed (%d enteries in cache)\n",proxiescount);

}

//free(buffer);
_close(hFile);


return true;

}

char *GetProxyFile()
{
return ProxyFile;
}


bool StartTunnel(int levelsdeep,int beginindex)
{
//Tunnel xxx levels deep
//returns true if tunnel is made
//Connect to the first proxy in list
char buffer[1024];
int curprox=beginindex;
int retval=0;

if ( beginindex >= proxiescount ) { return false;}

if ( proxiescount - beginindex < levelsdeep )
{
if ( PrintLog == true ) { printf("Not enough proxies left to go %d levels deep, aborted.\n",levelsdeep);}
}


//check if connected
if ( ConnectToHost(proxies[beginindex].host,proxies[beginindex].port) == FALSE )
{
if ( PrintLog == true ) { printf("Failed to connect to proxy #%d , %s:%d...tunnel failed.\n",beginindex,proxies[beginindex].host,proxies[beginindex].port);}

return false;
}

//Alright, connected, let proxy connect to first other proxy
curprox++; //beginindex +1
sprintf(buffer,"CONNECT %s:%d HTTP/1.0\r\n\r\n",proxies[curprox].host,proxies[curprox].port);
send(sock,buffer,strlen(buffer),0);
if ( PrintLog == true ) { printf(buffer); }

//Receive answer and check if connected to other proxy
retval = recv(sock,buffer,1024,0);
buffer[retval]=0;

if ( retval == SOCKET_ERROR || strstr(buffer," 200 ") == NULL ) //HTTP 200 OK expected
{
if ( PrintLog == true) { printf("Error receiving from proxy(%s:%d) or proxy could not connect to next proxy (%s:%d) \n",proxies[beginindex].host,proxies[beginindex].port,proxies[curprox].host,proxies[curprox].port);}
return false;
}


if ( PrintLog == true ) { printf("Connected,tunnelling...\n");}
printf("%s:%d->%s:%d",proxies[beginindex].host,proxies[beginindex].port,proxies[curprox].host,proxies[curprox].port);


while (1)
{

curprox++;
sprintf(buffer,"CONNECT %s:%d HTTP/1.0\r\n\r\n",proxies[curprox].host,proxies[curprox].port);
send(sock,buffer,strlen(buffer),0);

//Receive answer and check if connected to other proxy
retval = recv(sock,buffer,1024,0);
buffer[retval]=0;

if ( retval == SOCKET_ERROR || strstr(buffer," 200 ") == NULL ) //HTTP 200 OK expected
{
if ( PrintLog == true)
{
printf("->[FAILURE]Proxy(%s:%d) could not connect to next proxy (%s:%d)(or next proxy refused connection) \n",proxies[curprox-1].host,proxies[curprox -1].port,proxies[curprox].host,proxies[curprox].port);
printf("Response was: %s\n",buffer);
}
return false;
}

printf("->%s:%d->%s:%d",proxies[curprox-1].host,proxies[curprox -1].port,proxies[curprox].host,proxies[curprox].port);

//debug: printf("curproxy - beginindex==%d (levelsdeep==%d)\n",curprox - beginindex,levelsdeep);

if ( curprox - beginindex == levelsdeep )
{
if ( PrintLog == true ) { printf("\nTunnel build. (do you see the light?)\n");}
return true;
}

//eow
}

printf("\nhmmm, tunnel finished, but on another way ?, enjoy it ne way!\n");
return true;
}

BOOL ConnectToHost(char RemoteHost[],int RemotePort)
{
//win32: dont forget to initialize winsock with WSAStartup!!!!

//printf("Connecting to %s:%d\n",RemoteHost,RemotePort);
SOCKADDR_IN SockAddr;
HOSTENT *HostInfo;

if ( sock != NULL ) { closesocket(sock);}

sock = socket(AF_INET,SOCK_STREAM,0);

if (sock == INVALID_SOCKET )
{
printf("Invalid socket, did you call wsastartup first??\n");
return FALSE;
}

//printf("Resolving host...\n");
HostInfo = gethostbyname(RemoteHost);
if (HostInfo == NULL)
{
printf("Could not resolve host\n");
return FALSE;
}
else
{
SockAddr.sin_addr.S_un.S_un_b.s_b1 = (unsigned char)HostInfo->h_addr_list[0][0];
SockAddr.sin_addr.S_un.S_un_b.s_b2 = (unsigned char)HostInfo->h_addr_list[0][1];
SockAddr.sin_addr.S_un.S_un_b.s_b3 = (unsigned char)HostInfo->h_addr_list[0][2];
SockAddr.sin_addr.S_un.S_un_b.s_b4 = (unsigned char)HostInfo->h_addr_list[0][3];
}

SockAddr.sin_port = htons(RemotePort);
SockAddr.sin_family = AF_INET;


if (connect(sock , (SOCKADDR *)(&SockAddr), sizeof(SockAddr)) != 0)
{
printf("Could not connect to %s:%d\n",RemoteHost,RemotePort);
sock = NULL;
return FALSE;
}

printf("Connected to %s:%d\n",RemoteHost,RemotePort);
return TRUE;
}

int SendData(char *What)
{
return send(sock,What,strlen(What),0);
}

int ReadData(char *RecvBuf,int ReceiveSize)
{
int retval = recv(sock,RecvBuf,ReceiveSize,0);

if ( retval != SOCKET_ERROR || retval > 0 ) { RecvBuf[retval]=0;}
return retval;
}

bool ConnectToFinalHost(char *RemHost,int RemPort)
{
//Use this function after the tunnel is created.
//It instructs the last proxy of the chain/tunnel to connect to your target:port
char buffer[1024];
int retval=0;
if ( PrintLog ) {printf("Connecting to final host via last proxy (proxy->proxy->..->lastproxy->%s:%d",RemHost,RemPort);}

sprintf(buffer,"CONNECT %s:%d HTTP/1.0\r\n\r\n",RemHost,RemPort);
send(sock,buffer,strlen(buffer),0);
printf("\n%s\n",buffer);

retval = recv(sock,buffer,1024,0); //Catch proxy response

if ( retval < 1 || retval == SOCKET_ERROR ) { return false;}

buffer[retval]=0;


if ( strstr(buffer," 200 ") != NULL )
{
//connection success
return true;
}
else
{
//failure
printf("Response was: %s\n",buffer);
return false;
}


}


};

**********End of tunnel.h*************


To demonstrate how simple it is, i made a example that creates a tunnel of 4 proxies long and to connect to microsoft.com @ port 80:

**********Begin of tunnelexample.c*************


#include "classs.h"

//Tunnelexample.h by dataholic, the great cornholio

int main(int argc, char* argv[])
{
tunnelengine tunnel;

//Winsock init
WSADATA WsaDat;

if (WSAStartup(MAKEWORD(1, 1), &WsaDat) != 0)
{
printf("Could not init winsock\n");
return 0;
}


tunnel.SetOptions("C:\proxylist.txt",true);
tunnel.ParseProxyList();
printf("Creating tunnel...\n");
if ( tunnel.StartTunnel(4,1) == true ) //Tunnel size is 4 proxies, log == true
{
printf("Tunnel created.\n");
}
else
{
printf("Tunnel creation failed :(((\n");
return 0;
}

char buffer[5024];

if ( !tunnel.ConnectToFinalHost("www.microsoft.com",80) )
{
printf("Could not connect to final host\n");
return 0;
}


printf("Connected to final host, sending http query...\n");

sprintf(buffer,"GET /\r\n");
tunnel.SendData((char*)&buffer);
tunnel.ReadData((char*)&buffer,5024);
printf(buffer);

printf("Finished.\n");


return 0;

}

**********End of tunnelexample.c***************

 

 

<- HOME

Copyright (c) 2000-3000 by. Ing. Eduardo Palena - Napolifirewall.com©