Simple utility that allows a user to switch applications while keeping a TCP connection established.
a0c182bcd496f827d938424a3fac78ce510a38178ebc89fa5b9559c6a4ef10a9
//Code written by Eric des Courtis
//eric.des.courtis @ gmail.com
//Threeway allows you to connect to a server via TCP/IP and switch the stream
//to another application without the need to reconnect to the host it can be
//very useful in some rare situations.
//As an example between an exploit and a telnet client ;)
//There are obviously other uses but that is left to the user how he uses it.
//Please try to use this with a minimum level of ethics
//To make an executable under linux you can simply run the following
//gcc -o threeway threeway.c
//Under Windows you'll need to install cygwin + gcc first...
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <wait.h>
#include <signal.h>
//int checkvalidip(char *);
int checkvalidport(char *);
void CWR( int *, int *, int);
void CRW( int *, int *, int);
void L1RW(int *, int *, int);
void L1WR(int *, int *, int);
void L2RW(int *, int *, int);
void L2WR(int *, int *, int);
int main(int argc, char *argv[]){
struct sockaddr_in listensocket1;
struct sockaddr_in listensocket2;
struct sockaddr_in connectsocket;
struct hostent *host;
int listensock1;
int listensock2;
int connectsock;
int lsock1;
int lsock2;
int processid1;
int processid2;
int processid3;
int processid4;
int processid5;
int processid6;
int datapipe1[2];
int datapipe2[2];
int addrlen;
addrlen = sizeof(struct sockaddr);
listensocket1.sin_family = AF_INET;
listensocket2.sin_family = AF_INET;
connectsocket.sin_family = AF_INET;
listensocket1.sin_addr.s_addr = htonl(INADDR_ANY);
listensocket2.sin_addr.s_addr = htonl(INADDR_ANY);
listensocket1.sin_port = htons(atoi(argv[3]));
listensocket2.sin_port = htons(atoi(argv[4]));
connectsocket.sin_port = htons(atoi(argv[2]));
if(argc < 5){
printf("Not enough arguments!\n");
printf("ex: threeway [ipdest] [portdest] %s\n",
"[portsrc1] [portsrc2]");
fflush(stdout);
}else{
//Start program
host = (struct hostent*)gethostbyname(argv[1]);
if(!host){
fprintf(stderr,"Host could not be resolved.\n");
exit(EXIT_FAILURE);
}
connectsocket.sin_addr = *((struct in_addr *)host->h_addr);
if(!checkvalidport(argv[2])){
fprintf(stderr,"Port %s is invalid.\n",
argv[2]);
exit(EXIT_FAILURE);
}
if(!checkvalidport(argv[3])){
fprintf(stderr,"Port %s is invalid.\n",
argv[3]);
exit(EXIT_FAILURE);
}
if(!checkvalidport(argv[4])){
fprintf(stderr,"Port %s is invalid.\n",
argv[4]);
exit(EXIT_FAILURE);
}
if(atoi(argv[3]) == atoi(argv[4])){
fprintf(stderr,"Listen ports cannot %s\n",
"be the same.");
exit(EXIT_FAILURE);
}
if((connectsock = socket(PF_INET, SOCK_STREAM, 0)) == -1){
fprintf(stderr,"Socket creation failed.\n");
exit(EXIT_FAILURE);
}
if((listensock1 = socket(PF_INET, SOCK_STREAM, 0)) == -1){
fprintf(stderr,"Listen socket 1 creation failed.\n");
exit(EXIT_FAILURE);
}
if((listensock2 = socket(PF_INET, SOCK_STREAM, 0)) == -1){
fprintf(stderr,"Listen socket 2 creation failed.\n");
exit(EXIT_FAILURE);
}
if(bind(listensock1,
(struct sockaddr*) &listensocket1,
sizeof(listensocket1))){
fprintf(stderr,"Bind to socket 1 failed.\n");
exit(EXIT_FAILURE);
}
if(bind(listensock2,
(struct sockaddr*) &listensocket2,
sizeof(listensocket2))){
fprintf(stderr,"Bind to socket 2 failed.\n");
exit(EXIT_FAILURE);
}
if(listen(listensock1, 0) == -1){
fprintf(stderr,"Listen failed for sock 1.\n");
exit(EXIT_FAILURE);
}
if(listen(listensock2, 0) == -1){
fprintf(stderr,"Listen failed for sock 2.\n");
exit(EXIT_FAILURE);
}
if(connect(connectsock, (struct sockaddr *)&connectsocket,
sizeof(connectsocket)) == -1){
fprintf(stderr,"Connection failed to host.\n");
exit(EXIT_FAILURE);
}
//Accept connection
lsock1 = accept(listensock1,
(struct sockaddr*)&listensocket1, &addrlen);
pipe(datapipe1);
pipe(datapipe2);
switch(processid3 = fork()){
case 0:
//Start CWR Process
CWR(datapipe1, datapipe2, connectsock);
break;
case -1:
exit(EXIT_FAILURE);
default:
break;
}
switch(processid4 = fork()){
case 0:
//Start CRW Process
CRW(datapipe1, datapipe2, connectsock);
break;
case -1:
exit(EXIT_FAILURE);
default:
break;
}
switch(processid1 = fork()){
case 0:
//Start L1RW Process
L1RW(datapipe1, datapipe2, lsock1);
break;
case -1:
exit(EXIT_FAILURE);
default:
break;
}
switch(processid2 = fork()){
case 0:
//Start L1WR Process
L1WR(datapipe1, datapipe2, lsock1);
break;
case -1:
exit(EXIT_FAILURE);
default:
break;
}
lsock2 = accept(listensock2, (struct sockaddr*)&listensocket2,
&addrlen);
printf("Press any key to switch the stream.\n");
getchar();
kill(processid1, SIGKILL);
kill(processid2, SIGKILL);
close(listensock1);
close(lsock1);
switch(processid5 = fork()){
case 0:
//Start L2RW
L2RW(datapipe1, datapipe2, lsock2);
break;
case -1:
exit(EXIT_FAILURE);
default:
break;
}
switch(processid6 = fork()){
case 0:
//Start L2WR
L2WR(datapipe1, datapipe2, lsock2);
case -1:
exit(EXIT_FAILURE);
default:
break;
}
printf("Press any key to terminate Connection.");
getchar();
close(datapipe1[0]);
close(datapipe1[1]);
close(datapipe2[0]);
close(datapipe2[1]);
close(listensock2);
close(lsock2);
close(connectsock);
kill(processid3, SIGKILL);
kill(processid4, SIGKILL);
kill(processid5, SIGKILL);
kill(processid6, SIGKILL);
}
exit(EXIT_SUCCESS);
}
int checkvalidport(char *port){
if(!port) exit(EXIT_FAILURE);
if(port[0] == '\0') return 0;
if(atoi(port) > 0 && atoi(port) < 65536) return 1;
return 0;
}
void CWR(int *pipe1,int *pipe2, int connectsock){
char buf;
int len;
close(pipe1[0]);
close(pipe1[1]);
close(pipe2[1]);
for(;;){
len = read(pipe2[0], &buf, sizeof(buf));
write(connectsock, &buf, len);
}
}
void CRW(int *pipe1,int *pipe2, int connectsock){
char buf;
int len;
close(pipe1[0]);
close(pipe2[0]);
close(pipe2[1]);
for(;;){
len = read(connectsock, &buf, sizeof(buf));
write(pipe1[1], &buf, len);
}
}
void L1RW(int *pipe1, int *pipe2, int lsock1){
char buf;
int len;
close(pipe1[0]);
close(pipe1[1]);
close(pipe2[0]);
for(;;){
len = read(lsock1, &buf, sizeof(buf));
write(pipe2[1], &buf, len);
}
}
void L1WR(int *pipe1, int *pipe2, int lsock1){
char buf;
int len;
close(pipe1[1]);
close(pipe2[0]);
close(pipe2[1]);
for(;;){
len = read(pipe1[0], &buf, sizeof(buf));
write(lsock1, &buf, len);
}
}
void L2RW(int *pipe1, int *pipe2, int lsock2){
char buf;
int len;
close(pipe1[0]);
close(pipe1[1]);
close(pipe2[0]);
for(;;){
len = read(lsock2, &buf, sizeof(buf));
write(pipe2[1], &buf, len);
}
}
void L2WR(int *pipe1, int *pipe2, int lsock2){
char buf;
int len;
close(pipe1[1]);
close(pipe2[0]);
close(pipe2[1]);
for(;;){
len = read(pipe1[0], &buf, sizeof(buf));
write(lsock2, &buf, len);
}
}