首页 > 代码库 > 超级轻量的远程命令行客户端和服务端(含文件传输)

超级轻量的远程命令行客户端和服务端(含文件传输)

功能:实现基于TCPIP的命令行操作远程计算机,并且支持远程文件传输

平台:windows   (linux同理)

原理:客户端连接上服务端之后,先监听键盘输入,将键盘输入的cmd指令保存并发送给服务端;服务端保存并通过调用命令行执行,获取命令行执行结果发送给客户端。如果是   获取文件命令,则读取文件,并将文件发送给客户端

代码:源码下载链接

// 核心代码
int getfile(const char *path,SOCKET ClientSocket,const char *file)
{
	int rtn = 0;
	char buffer[DEFAULT_BUFLEN];//
	string finalfile = string(path)+"\\"+string(file);
	printf("finalfile:%s",finalfile.c_str());
	FILE *fp = fopen(finalfile.c_str(),"rb");
	
	while(1)
	{
		int size = fread(buffer,1,sizeof(buffer),fp);
		if(size == 0)
		{
			if(feof(fp))
			{
#if 0
				if(-1 ==sendData(ClientSocket,buffer,size,size))
				{
					rtn = -1;
					IF_ERROR_GOTO_END;
				}
#endif
				break;
			}
			else if(ferror(fp))
			{
				rtn = ferror(fp);
				IF_ERROR_GOTO_END;
			}
		}
		else
		{
			if(-1 ==sendData(ClientSocket,buffer,size,size))
			{
				rtn = -1;
				IF_ERROR_GOTO_END;
			}
		}
	}
END:
	fclose(fp);
	return rtn;
}

//http://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-output-of-command-within-c
int exec(char *lastpath,int pathsize,char* cmd,SOCKET ClientSocket,string out) 
{
	//命令结果字符串的最后一行即是当前路径;不能放在最前面,要获取的是执行完cmd之后的路径
	char finalcmd[0x300] = "";
    char buffer[0x300];//
	int rtn = 0;
    string result = "";

	strcpy(finalcmd,(string("cd /d ") + string(lastpath) + string(" && ") +
		string(cmd) + string(" && cd ")).c_str()); // 2>&1 ) && cd 方式添加了错误信息和显示当前路劲,但是报错时只显示最后那个错,不会报告路径,所以不获取错误信息好了
	
	FILE* pipe = _popen(finalcmd, "r");
	static int i=0;
	printf("\n>>>====第%d条指令======\ncmd:%s\n====第%d条指令======<<<\n",i,finalcmd,i++);
    if (!pipe) return -1;
    while(!feof(pipe)) 
	{
		if(fgets(buffer, sizeof(buffer), pipe) != NULL)
		{
			result += buffer;
			//printf("%s",buffer);
			int sendLen = 0;
			if(-1 ==sendData(ClientSocket,buffer,strlen(buffer),sendLen))
			{
				rtn = -1;
				IF_ERROR_GOTO_END;
			}
			if(strlen(buffer))
			{
				ZeroMemory(lastpath,pathsize);
				strcpy(lastpath,buffer);
			}
			ZeroMemory(buffer,sizeof(buffer));
		}
    }
    _pclose(pipe);
	pipe = NULL;
	out = result;
	
END:
	if(pipe != NULL)
	{
		_pclose(pipe);
		pipe = NULL;
	}

	if(lastpath[strlen(lastpath)-1] == '\n')
		lastpath[strlen(lastpath)-1]='\0';//去掉最后的回车
	printf("lastpath:%s",lastpath);
    return rtn;
}

int sendData(SOCKET ClientSocket,char *buf,int bufLen,int &sendLen)
{
	// Echo the buffer back to the sender
	int rtn = 0;
	rtn = send( ClientSocket, buf, bufLen, 0 );
	sendLen = rtn;
	if (rtn == SOCKET_ERROR) {
		printf("send failed with error: %d\n", WSAGetLastError());
	}
    //printf("Bytes sent: %d\n", iSendResult);
	return rtn;
}


测试:

1、开启服务端进程

2、从命令行打开用户端进程 HackClient.exe 127.0.0.1

3、使用dir命令浏览服务端程序的目录

4、从服务端程序获取某文件,从下面的截图可见,最终HackServer.exe拷贝过来了

截图:

注意:

1、如果编译报错没有定义addrinfo结构体,可能是因为用vc6编译的,而vc6自带的ws2tcpip.h文件里是没有定义这个结构体的,可以用vs2008编译

2、使用时,先打开Server的执行文件Server.exe,再打开Client.exe。注意Client.exe的参数是服务端的IP地址

3、需要保证服务端的端口可以正常打开监听


参考:

http://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-output-of-command-within-c

超级轻量的远程命令行客户端和服务端(含文件传输)