lcx.exe算是端口转发工具中普及率特别高的吧。当然,最近也出了好些Web端口转发工具,这个待后续再分析一下。我从网上下载了一个lcx的源码片段,结合源码谈谈自己的认识。
lcx工作原理是使不同端口之间形成一个回路,这样就可以进行端口转发。常用于外网连接内网3389端口。具体使用方法网上一堆。
这个程序主要采用Socket来实现,有几个比较重要的函数:bind2bind、bind2conn、conn2conn及transmitdata。transmitdata函数是核心,这个函数作用是使得不同端口之间的数据形成一个回路。
注意源代码中的setsocket函数,其中设置了SO_REUSEADDR。设置SO_REUSEADDR之后,可以应用的一种场景就是同一个端口可以绑定多个socket。查看相关资料可以得知,其实设置SO_REUSEADDR之后,还有其他几种应用场景。我试了一下,你把setsocket函数注释掉,在运行这个端口转发程序时,本地listen的时候设置的两个端口不一样程序还是可以正常运行的。启用setsocket函数之后,本地listen的时候,可以设置两个端口为同一个值,但是这样设置的时候,我在虚拟机中无法远程连接,一直就是尝试连接也不报错。原因不因,未深入分析。
网上很多的源码其实是有问题的,下面我分享一个稍作修改的源代码,能够在windows xp +vc6.0下编译通过,理论上是可以在windows系列所有32位版本下运行的。对于64位系统,我也修改了一个版本,在windows 7 x64+vs2013编译通过,主要用于64位windows下运行。可执行文件我就不放出来了,自己编译运行差不多就OK了。
Windows XP +VC6.0下编译通过的源码:
/*
************************************************************************************** HTran.cpp - HUC Packet Transmit Tool.** Copyright (C) 2000-2004 HUC All Rights Reserved.** Author : lion* : lion#cnhonker.net* : <a href="http://www.cnhonker.com" target="_blank">http://www.cnhonker.com</a>* :* Notice : Thx to bkbll (bkbll#cnhonker.net)* :* Date : 2003-10-20* :* Complie : cl HTran.cpp* :* Usage : E:\>HTran* : ======================== HUC Packet Transmit Tool V1.00 =======================* : =========== Code by lion & bkbll, Welcome to <a href="http://www.cnhonker.com" target="_blank">http://www.cnhonker.com</a> ==========* :* : [Usage of Packet Transmit:]* : HTran - [-log logfile]* :* : [option:]* : -listen* : -tran* : -slave**************************************************************************************/#include <stdio.h>#include <stdlib.h>#include <winsock2.h>#include <signal.h>#include <errno.h>#include <io.h>#pragma comment(lib, "ws2_32.lib")
#define VERSION "1.00"
#define TIMEOUT 300#define MAXSIZE 20480#define HOSTLEN 40#define CONNECTNUM 5// define 2 socket struct
struct transocket
{SOCKET fd1;SOCKET fd2;};// define function
void ver();
void usage(char *prog);void transmitdata(LPVOID data);
void getctrlc(int j);void closeallfd();
void makelog(char *buffer, int length);void proxy(int port);void bind2bind(int port1, int port2);void bind2conn(int port1, char *host, int port2);void conn2conn(char *host1, int port1, char *host2, int port2);int testifisvalue(char *str);int create_socket();
int create_server(int sockfd, int port);int client_connect(int sockfd, char* server, int port);// define GLOBAL variable here
extern int errno;FILE *fp;int method=0;
//int connectnum=0;
//************************************************************************************
//
// function main 主要是处理用户参数输入的问题
//
//************************************************************************************
VOID main(int argc, char* argv[]){char **p;
char sConnectHost[HOSTLEN], sTransmitHost[HOSTLEN];
int iConnectPort=0, iTransmitPort=0;
char *logfile=NULL;
ver();memset(sConnectHost, 0, HOSTLEN);memset(sTransmitHost, 0, HOSTLEN);p=argv;while(*p)
{if(stricmp(*p, "-log") == 0){if(testifisvalue(*(p+1)))
{logfile = *(++p);}else
{printf("[-] ERROR: Must supply logfile name.\r\n");
return;
}p++;continue;
}p++;}if(logfile !=NULL)
{fp=fopen(logfile,"a");
if(fp == NULL )
{printf("[-] ERROR: open logfile");
return;
}makelog("====== Start ======\r\n", 22);
}// Win Start Winsock.
WSADATA wsadata;WSAStartup(MAKEWORD(2, 2), &wsadata);signal(SIGINT, &getctrlc);if(argc > 2)
{if(stricmp(argv[1], "-listen") == 0 && argc >= 4){iConnectPort = atoi(argv[2]);iTransmitPort = atoi(argv[3]);method = 1;}else
if(stricmp(argv[1], "-tran") == 0 && argc >= 5){iConnectPort = atoi(argv[2]);strncpy(sTransmitHost, argv[3], HOSTLEN);iTransmitPort = atoi(argv[4]);method = 2;}else
if(stricmp(argv[1], "-slave") == 0 && argc >= 6){strncpy(sConnectHost, argv[2], HOSTLEN);iConnectPort = atoi(argv[3]);strncpy(sTransmitHost, argv[4], HOSTLEN);iTransmitPort = atoi(argv[5]);method = 3;}}switch(method)
{case 1:
bind2bind(iConnectPort, iTransmitPort);break;
case 2:
bind2conn(iConnectPort, sTransmitHost, iTransmitPort);break;
case 3:
conn2conn(sConnectHost, iConnectPort, sTransmitHost, iTransmitPort);break;
default:
usage(argv[0]);break;
}if(method)
{closeallfd();}WSACleanup();return;
}//************************************************************************************
//
// print version message
//
//************************************************************************************
VOID ver(){printf("======================== HUC Packet Transmit Tool V%s =======================\r\n", VERSION);
printf("=========== Code by lion & bkbll, Welcome to http://www.cnhonker.com==========\r\n\n");
}//************************************************************************************
//
// print usage message
//
//************************************************************************************
VOID usage(char* prog)
{printf("[Usage of Packet Transmit:]\r\n");
printf(" %s - [-log logfile]\n\n", prog);
printf("[option:]\n");
printf(" -listen \n");
printf(" -tran \n");
printf(" -slave \n\n");
return;
}//************************************************************************************
//
// test if is value
//
//************************************************************************************
int testifisvalue(char *str){if(str == NULL ) return(0);if(str[0]=='-') return(0);return(1);
}//************************************************************************************
//
// LocalHost:ConnectPort transmit to LocalHost:TransmitPort
//
//************************************************************************************
void bind2bind(int port1, int port2){SOCKET fd1,fd2, sockfd1, sockfd2;struct sockaddr_in client1,client2;
int size1,size2;
HANDLE hThread=NULL;transocket sock;DWORD dwThreadID;if((fd1=create_socket())==0) return;if((fd2=create_socket())==0) return;printf("[+] Listening port %d ......\r\n",port1);
fflush(stdout);if(create_server(fd1, port1)==0)
{closesocket(fd1);return;
}printf("[+] Listen OK!\r\n");
printf("[+] Listening port %d ......\r\n",port2);
fflush(stdout);if(create_server(fd2, port2)==0)
{closesocket(fd2);return;
}printf("[+] Listen OK!\r\n");
size1=size2=sizeof(struct sockaddr);while(1)
{printf("[+] Waiting for Client on port:%d ......\r\n",port1);
if((sockfd1 = accept(fd1,(struct sockaddr *)&client1,&size1))<0){printf("[-] Accept1 error.\r\n");
continue;
}printf("[+] Accept a Client on port %d from %s ......\r\n", port1, inet_ntoa(client1.sin_addr));
printf("[+] Waiting another Client on port:%d....\r\n", port2);
if((sockfd2 = accept(fd2, (struct sockaddr *)&client2, &size2))<0){printf("[-] Accept2 error.\r\n");
closesocket(sockfd1);continue;
}printf("[+] Accept a Client on port %d from %s\r\n",port2, inet_ntoa(client2.sin_addr));
printf("[+] Accept Connect OK!\r\n");
sock.fd1 = sockfd1;sock.fd2 = sockfd2;hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)transmitdata, (LPVOID)&sock, 0, &dwThreadID);if(hThread == NULL)
{TerminateThread(hThread, 0);return;
}Sleep(1000);printf("[+] CreateThread OK!\r\n\n");
}}//************************************************************************************
//
// LocalHost:ConnectPort transmit to TransmitHost:TransmitPort
//
//************************************************************************************
void bind2conn(int port1, char *host, int port2){SOCKET sockfd,sockfd1,sockfd2;struct sockaddr_in remote;
int size;
char buffer[1024];