[转载]Bouncer 网络数据包"跳跃"器
信息来源:邪恶八进制信息安全团队Bouncer是一种可以动态绑定到Linux操作系统(其它UNIX系统可能也行)的工具,它允许系统管理员使用第三方的代理服务器(如WinGate等支持SOCK4的产品)作为与互联网连接的匿名网关。
例如,通过它,你可以匿名地收取电子邮件,透明地"跳跃"访问IRC、HTTP、甚至远程攻击连接。事实上,它针对的是任何使用SOCK_STREAM的AF_INET类型。
此工具在后台截获connect()调用,然后使用一个或多个"跳跃"代理服务器进行连接,从而隐藏了连接的来源地址。本工具在LINUX下测试通过,在其它平台应该也可以(但需要有所修改)。本工具不需要以root权限运行。
工具源程序:
[code]/*
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, ''\n'') == ERROR)
|| (read_until (sock, ''\n'') == 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''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, ''>'') == 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, ''\n'') == 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 ''w'':
last_bounce=BOUNCE_WINGATE;
break;
case ''s'':
last_bounce=BOUNCE_SOCKS4;
break;
case ''c'':
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''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''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''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);[/code]
页:
[1]