发新话题
打印

[转载]Bouncer 网络数据包"跳跃"器

[转载]Bouncer 网络数据包"跳跃"器

  信息来源:邪恶八进制信息安全团队

Bouncer是一种可以动态绑定到Linux操作系统(其它UNIX系统可能也行)的工具,它允许系统管理员使用第三方的代理服务器(如WinGate等支持SOCK4的产品)作为与互联网连接的匿名网关。  
  
例如,通过它,你可以匿名地收取电子邮件,透明地"跳跃"访问IRC、HTTP、甚至远程攻击连接。事实上,它针对的是任何使用SOCK_STREAM的AF_INET类型。  
  
此工具在后台截获connect()调用,然后使用一个或多个"跳跃"代理服务器进行连接,从而隐藏了连接的来源地址。本工具在LINUX下测试通过,在其它平台应该也可以(但需要有所修改)。本工具不需要以root权限运行。  
  
  
工具源程序:
复制内容到剪贴板
代码:
/*  
  
bouncer v1.1  
connect() client dynamic wrapper to bounce tcp connections  
by mirage (ptlink/ptnet)  
  
.\\idgard Security Services [March/April/May 1999]  
Some portability fixes added in September  
  
MANY thanks to LiquidK @ptnet/promiscnet/efnet  
  
compilation:  
linux: gcc bouncer.c -o bouncer.so -ldl -shared -O2 -s  
bsd: gcc bouncer.c -c -fPIC -O2 -s && ld bouncer.o -o bouncer.so -shared  
you may need to use -DSOCKLEN, depending on the OS and libs.  
  
to use, in bash:  
export BOUNCER="type:host:port@type:host:port(@...)"  
export LD_PRELOAD=/path/to/bouncer.so  
./your_connect_program  
where is:  
''w'' for Wingate  
''s'' for SOCKS4  
''c'' for CSM Proxy  
  
to unload:  
unset BOUNCER LD_PRELOAD  
  
注1:如果需要调试信息,可设置BOUNCER_DEBUG = 1  
注2:不能通过wingate作二进制传输连接  
  
*/  
  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
  
#ifdef SOCKLEN  
typedef int socklen_t;  
#endif  
  
#define SOCKS4_USER "billgates"  
  
#define BOUNCE_NORMAL 0  
#define BOUNCE_WINGATE 1  
#define BOUNCE_SOCKS4 2  
#define BOUNCE_CSM 3  
#define YES 1  
#define NO 0  
#define ERROR -1  
  
char *bounce_env;  
static void *lib_handle = NULL;  
/* place to put the old connect() call */  
static int (*old_connect) (int sockfd, const struct sockaddr *serv_addr,  
int addrlen);  
/* this is not reentrant :) */  
int in_use=0;  
/* whether to print or not some debugging output */  
int debug=0;  
  
/* get original connect() address and BOUNCER from the environment */  
static void  
init (void)  
{  
char *debug_env = getenv ("BOUNCER_DEBUG");  
  
if (debug_env != NULL)  
if (debug_env[0] == ''1'')  
{  
debug = YES;  
printf ("bouncer debugging started\r\n");  
}  
  
bounce_env = getenv ("BOUNCER");  
  
if (!(lib_handle = dlopen ("libc.so", RTLD_LAZY)))  
if (!(lib_handle = dlopen ("libc.so.6", RTLD_LAZY)))  
if (!(lib_handle = dlopen ("libc.so.5", RTLD_LAZY)))  
{  
printf ("error loading libc!\n");  
exit (1);  
}  
  
if (!(old_connect = dlsym (lib_handle, "connect")))  
{  
printf ("connect() not found in libc!\n");  
exit (1);  
}  
  
}  
  
/* return the number of chars needed represent */  
int  
int_chars (int num)  
{  
int i = 1, size = 0;  
while ((num / i) != 0)  
{  
i *= 10;  
size++;  
}  
return size;  
}  
  
/* connect to , using the given */  
int  
connect_to (int sock, char *host, int port)  
{  
struct hostent *he = NULL;  
struct sockaddr_in sa;  
  
if ((he=gethostbyname(host)) == NULL)  
return ERROR;  
memcpy (&sa.sin_addr, he->h_addr, he->h_length);  
sa.sin_port = htons (port);  
sa.sin_family = AF_INET;  
return old_connect (sock, (struct sockaddr *)&sa, sizeof sa);  
}  
  
/* read chars from to */  
int  
read_sock (int sock, char *dest, int num)  
{  
int i;  
for (i = 0; i < num; i++)  
if (read (sock, dest+i, 1) == ERROR)  
return ERROR;  
dest[i] = 0;  
return !ERROR;  
}  
  
/* read from until a is received */  
int  
read_until (int sock, char c)  
{  
char buf = 255;  
while (buf != c)  
if (read (sock, &buf, 1) == ERROR)  
return ERROR;  
return !ERROR;  
}  
  
/* bounce through a Wingate */  
int  
bounce_wingate (int sock, char *host, int port)  
{  
char buf[80];  
  
if (debug)  
printf ("wingate in %s:%d\r\n", host, port);  
  
snprintf (buf, 80, "%s %d\n", host, port);  
write (sock, buf, strlen (buf));  
  
if (debug)  
printf ("request sent\r\n");  
  
if ( (read_until (sock, &#39;&#39;\n&#39;&#39;) == ERROR)  
|| (read_until (sock, &#39;&#39;\n&#39;&#39;) == ERROR) )  
return ERROR;  
  
if (debug)  
printf ("done\r\n");  
  
return !ERROR;  
}  
  
/* bounce through a SOCKS4 firewall */  
int  
bounce_socks4 (int sock, char *host, int port)  
{  
struct hostent *he = NULL;  
unsigned char buf[4];  
char buf2[100];  
  
if (debug)  
printf ("socks4 in %s:%d\r\n", host, port);  
if ((he = gethostbyname (host)) == NULL)  
return ERROR;  
memcpy (&buf, he->h_addr, he->h_length);  
  
/* taken from eggdrop&#39;&#39;s net.c:proxy_connect() */  
sprintf (buf2, "\004\001%c%c%c%c%c%c%s", (port >> 8) % 256, (port % 256),  
buf[0], buf[1], buf[2], buf[3], SOCKS4_USER);  
write (sock, buf2, 8 + strlen (SOCKS4_USER) + 1);  
  
if (debug)  
printf ("request sent\r\n");  
if (read_sock (sock, buf2, 8) == ERROR)  
return ERROR;  
if (debug)  
printf ("done\r\n");  
  
return !ERROR;  
}  
  
/* bounce through a CSM Proxy */  
int  
bounce_csm (int sock, char *host, int port)  
{  
char buf[100];  
  
if (debug)  
printf ("csm in %s:%d\r\n", host, port);  
if (read_until (sock, &#39;&#39;>&#39;&#39;) == ERROR)  
return ERROR;  
sprintf (buf, "%s:%d\n", host, port);  
write (sock, buf, strlen (buf));  
if (debug)  
printf ("request sent\r\n");  
if (read_until (sock, &#39;&#39;\n&#39;&#39;) == ERROR)  
return ERROR;  
if (debug)  
printf ("done\r\n");  
  
return !ERROR;  
}  
  
/* decide how to connect */  
int  
bounce_to (int type, int sock, char *host, int port)  
{  
switch (type)  
{  
case BOUNCE_NORMAL:  
return connect_to (sock, host, port);  
case BOUNCE_WINGATE:  
return bounce_wingate (sock, host, port);  
case BOUNCE_SOCKS4:  
return bounce_socks4 (sock, host, port);  
case BOUNCE_CSM:  
return bounce_csm (sock, host, port);  
default:  
return ERROR; /* should never be reached */  
}  
}  
  
/* main bouncer */  
int  
bounce (int sock, struct sockaddr_in *sa)  
{  
int last_bounce = BOUNCE_NORMAL; /* last bounce type made */  
char *type, *host, *port, *env = bounce_env;  
  
/* BOUNCER variable parser */  
if ((type = strtok (env, ":")) != NULL)  
do  
{  
if ((host=strtok(NULL, ":")) == NULL)  
return ERROR;  
if ((port=strtok(NULL, "@")) == NULL)  
return ERROR;  
if (bounce_to(last_bounce, sock, host, atoi(port)) == ERROR)  
return ERROR;  
switch (type[0])  
{  
case &#39;&#39;w&#39;&#39;:  
last_bounce=BOUNCE_WINGATE;  
break;  
case &#39;&#39;s&#39;&#39;:  
last_bounce=BOUNCE_SOCKS4;  
break;  
case &#39;&#39;c&#39;&#39;:  
last_bounce=BOUNCE_CSM;  
break;  
default:  
return ERROR;  
}  
}  
while ((type=strtok(NULL, ":")) != NULL);  
else  
return ERROR;  
  
host = (char *) inet_ntoa (sa->sin_addr);  
/* connect to the real destination */  
last_bounce = bounce_to (last_bounce, sock, host, ntohs (sa->sin_port));  
in_use = NO;  
return (last_bounce);  
}  
  
/* the all mighty wrapper */  
int  
connect (int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)  
{  
int optval = 0, optlen = sizeof (optval), tmp, flags;  
  
if (!lib_handle) /* If not loaded, load it now */  
init ();  
  
/* if it&#39;&#39;s not connecting to localhost, and socket is AF_INET */  
if ( (((struct sockaddr_in *)serv_addr)->sin_addr.s_addr != 16777343) &&  
(((struct sockaddr_in *)serv_addr)->sin_family == AF_INET) )  
/* if we&#39;&#39;re not already being used */  
if (!in_use)  
/* if BOUNCER is defined */  
if (bounce_env != NULL)  
/* if getsockopt() succeds */  
if (getsockopt (sockfd, SOL_SOCKET, SO_TYPE, &optval, &optlen) != -1)  
/* and socket is SOCK_STREAM */  
if (optval == SOCK_STREAM)  
{  
/* bounce&#39;&#39;em baby */  
in_use = YES;  
flags = fcntl (sockfd, F_GETFL);  
if (flags & O_NONBLOCK) /* if O_NONBLOCK is set */  
fcntl (sockfd, F_SETFL, flags-O_NONBLOCK); /* unset it */  
tmp = bounce (sockfd, (struct sockaddr_in *) serv_addr);  
if (flags & O_NONBLOCK)  
fcntl (sockfd, F_SETFL, flags); /* put O_NONBLOCK back in */  
return tmp;  
}  
  
/* otherwise, use normal connect */  
return old_connect (sockfd, serv_addr, addrlen);

TOP

发新话题