1. 程式人生 > >超級輕量的遠端命令列客戶端和服務端(含檔案傳輸)

超級輕量的遠端命令列客戶端和服務端(含檔案傳輸)

功能:實現基於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、需要保證服務端的埠可以正常開啟監聽

參考: