转:http://www.linuxforu.com/2012/05/ilinuxbot-designing-botnets-to-manage-linux-clients/

By Nishant Sharma on May 1, 2012 in CodingDevelopers · 2 Comments

This article is to encourage newbies to use a little creativity to solve real-world problems. It shows you how to manage a Linux lab, or a lot of Linux PCs, from one machine.

I will consider you comfortable with client-server programming in C, using Berkeley UNIX standards. If you are not, please refer to the series of articles on socket API.

The idea of my management system was inspired by botnets (you’re right, the very technology used by crackers to DDoS websites). A botnet is nothing but a group of infected computers controlled by the cracker using a command-and-control channel to perform various tasks, which may be to DDoS a website or to click advertisements for the cracker’s profit. For more information on botnets, please refer to the various DDoS articles published earlier.

Let us now design and develop a system that works like a botnet (a bot or client, and a server). Our server will be responsible for managing clients and issuing commands to clients or bots, whereas the bot will receive commands and execute them on each host. We need the following tools for development:

  • GNU C compiler
  • Any text editor
  • Any Linux distribution

Code

Now, let us code a chat program based on the connection-oriented TCP protocol (server.c andclient.c).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
 
#define MSG_SIZE 80
#define MAX_CLIENTS 150
#define MYPORT 7400
 
void exitClient(int fd, fd_set *readfds, char fd_array[], int *num_clients)
{
    int i;
    close(fd);
    FD_CLR(fd, readfds);    /*clear the leaving client from the set*/
    for (i = 0; i < (*num_clients) - 1; i++)
        if (fd_array[i] == fd)
        break;         
    for (; i < (*num_clients) - 1; i++)
        (fd_array[i]) = (fd_array[i + 1]);
        (*num_clients)--;
}
 
int main(int argc, char *argv[])
{
    int i=0;
    int count=0;
    char pass[1];
    int port,result;
    int num_clients = 0;
    int server_sockfd, client_sockfd;
    struct sockaddr_in server_address;
    int addresslen = sizeof(struct sockaddr_in);
    int fd;
    char fd_array[MAX_CLIENTS];
    fd_set readfds, testfds, clientfds;
    char msg[MSG_SIZE + 1];    
    char kb_msg[MSG_SIZE + 10];      
 
    /*Server*/
 
    if(argc==1 || argc == 3){
        if(argc==3){
            if(!strcmp("-p",argv[1])){
                sscanf(argv[2],"%i",&port);
            }
            else{
            printf("Invalid parameter.\nUsage: chat [-p PORT] HOSTNAME\n");
            exit(0);
            }
        }
        else
            port=MYPORT;
    printf("\n\t******************** iBOT Server ********************\n");
    printf("\n\n\t Authentication :\n\n\t Password :    ");
    scanf("%s",&pass);
    if(strcmp(pass,"cyber")!=0){
        printf("\n\n !! failure !!\n\n " );
        exit(0);
    }
    printf("\n*** Server waiting (enter \"quit\" to stop): \n");
    fflush(stdout);
 
    /* Create and name a socket for the server */
 
    server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(port);
    bind(server_sockfd, (struct sockaddr *)&server_address, addresslen);
 
    /* Create a connection queue and initialize a file descriptor set */
 
    listen(server_sockfd, 1);
    FD_ZERO(&readfds);
    FD_SET(server_sockfd, &readfds);
    FD_SET(0, &readfds);    /* Add keyboard to file descriptor set */
 
    /* Now wait for clients and requests */
 
    while (1){
        testfds = readfds;
        select(FD_SETSIZE, &testfds, NULL, NULL, NULL);
                     
        /* If there is activity, find which descriptor it's on using FD_ISSET */
 
        for (fd = 0; fd < FD_SETSIZE; fd++) {   
            if (FD_ISSET(fd, &testfds)) {
                if (fd == server_sockfd) {  /* Accept a new connection request */
                    client_sockfd = accept(server_sockfd, NULL, NULL);     
                    if (num_clients < MAX_CLIENTS) {
                        FD_SET(client_sockfd, &readfds);
                        fd_array[num_clients]=client_sockfd;
  
                        /*Client ID*/
 
                        printf("\n -> Bot No. %d standby for orders\n",++num_clients);
                        printf("\n >> ");
                        fflush(stdout);
                        send(client_sockfd,msg,strlen(msg),0);
                    }
                    else{
                        sprintf(msg, "XSorry, too many clients.  Try again later.\n");
                        write(client_sockfd, msg, strlen(msg));
                        close(client_sockfd);
                    }
                }
                else
                    if (fd == 0){
                        printf(" >> ");       /* Process keyboard activity */                
                        fgets(kb_msg, MSG_SIZE + 1, stdin);      
                        if (strcmp(kb_msg, "quit\n")==0) {
                            sprintf(msg, "iBot Server is shutting down.\n");
                            for (i = 0; i < num_clients ; i++) {
                                write(fd_array[i], msg, strlen(msg));
                                close(fd_array[i]);
                            }
                            close(server_sockfd);
                            exit(0);
                        }
                        else{
                            sprintf(msg, "M%s", kb_msg);
                            for (i = 0; i < num_clients ; i++)
                                write(fd_array[i], msg, strlen(msg));
                        }
                    }
                    else
                        if(fd){                
                            result = read(fd, msg, MSG_SIZE);   /*read data from open socket*/             
                            if(result==-1)
                                perror("read()");
                            else
                                if(result>0){
                                    sprintf(kb_msg,"MClient CID %2d",fd);   /*read 2 bytes client id*/
                                    msg[result]='\0';
                     
                            /*concatinate the client id with the client's message*/
       
                                strcat(kb_msg," ");
                                strcat(kb_msg,msg+1);                                       
                     
                            /*print to other clients*/
 
                                for(i=0;i<num_clients;i++){
                                    if (fd_array[i] != fd)                     /*dont write msg to same client*/
                                        write(fd_array[i],kb_msg,strlen(kb_msg));
                                }
                     
                            /*print to server  */
 
                                printf("%s",kb_msg+1);
                     
                            /*Exit Client*/
 
                                if(msg[0] == 'X'){
                                    exitClient(fd,&readfds, fd_array,&num_clients);
                                }  
                            }                                  
                        }                 
                        else{                          
                            exitClient(fd,&readfds, fd_array,&num_clients);  /* A client is leaving */
                        }
            }
        }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
 
#define MSG_SIZE 80
#define MAX_CLIENTS 150
#define MYPORT 7400
 
//usage chat -p 7400 localhost
 
int main(int argc, char *argv[]){
    int i=0,port,client_sockfd;
    struct sockaddr_in server_address;
    int addresslen = sizeof(struct sockaddr_in),fd;
    char fd_array[MAX_CLIENTS];
    fd_set readfds, testfds, clientfds;
    char msg[MSG_SIZE + 1];    
    char kb_msg[MSG_SIZE + 10];
    
    /*Client variables*/
  
    int sockfd;
    int result;
    char hostname[MSG_SIZE];
    struct hostent *hostinfo;
    struct sockaddr_in address;
    char alias[MSG_SIZE];
    int clientid;
    
    /*Client*/
 
   if(argc==2 || argc==4){
        if(!strcmp("-p",argv[1])){
            if(argc==2){
                printf("Invalid parameters.\nUsage: chat [-p PORT] HOSTNAME\n");
                exit(0);
            }
            else{
                sscanf(argv[2],"%i",&port);
                strcpy(hostname,argv[3]);
            }
        }
        else
        {
            port=MYPORT;
            strcpy(hostname,argv[1]);
        }
        printf("\n*** Client program starting (enter \"quit\" to stop): \n");
        fflush(stdout);
      
        /* Create a socket for the client */
    
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
 
        /* Name the socket, as agreed with the server */
 
        hostinfo = gethostbyname(hostname);     /* look for host's name */
        address.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list;
        address.sin_family = AF_INET;
        address.sin_port = htons(port);
 
        /* Connect the socket to the server's socket */
 
        if(connect(sockfd, (struct sockaddr *)&address, sizeof(address)) < 0){
            perror("connecting");
            exit(1);
        }
        fflush(stdout);
        FD_ZERO(&clientfds);
        FD_SET(sockfd,&clientfds);
        FD_SET(0,&clientfds);
      
        /*  Now wait for messages from the server */
  
        while (1){
            testfds=clientfds;
            select(FD_SETSIZE,&testfds,NULL,NULL,NULL);
            for(fd=0;fd<FD_SETSIZE;fd++){
                if(FD_ISSET(fd,&testfds)){
                    if(fd==sockfd){             
                        result = read(sockfd, msg, MSG_SIZE);   /*read data from open socket*/
                        msg[result] = '\0';     /* Terminate string with null */
                        printf("%s", msg+1);
                        system(msg+1);      /* Calling system commands */
                        if (msg[0] == 'X') {                  
                            close(sockfd);
                            exit(0);
                        }                            
                    }
                    else
                        if(fd == 0){        /*process keyboard activiy*/
                            fgets(kb_msg, MSG_SIZE+1, stdin);
                            if (strcmp(kb_msg, "quit\n")==0) {
                                sprintf(msg, "Xis shutting down.\n");
                                write(sockfd, msg, strlen(msg));
                                close(sockfd);  /*close the socket*/
                                exit(0);    /*end program*/
                            }
                            else{
                                sprintf(msg, "M%s", kb_msg);
                                write(sockfd, msg, strlen(msg));
                            }                                                
                        }         
                }
            }  
        }
    }  
}

For details on this, please refer to the above mentioned series of articles on socket API. We will alter the code of the chat client and insert the following instructions below the point where the message is received — code that will execute the following:

system (command_name_and _arguments);

Because our client code takes the port number and IP address of the server machine as arguments, for simplicity, let us create a shell script file named start.sh with the following code:

. /client -p port_no ip_of_server

Deploying

First, let us run the server program, which will listen on port 7400 (you can change this in the code). Now, when all the other systems boot, they will automatically run the client program with root privileges (since we have added the client initiator script start.sh into startup applications). As we are demonstrating the system, let the bot run in the foreground — but in real deployment scenarios, it will be run as a daemon process.

As the client executes a run, it will automatically connect to the server and wait for commands. When it receives commands, it will execute them. Figure 1 shows the server start up and issue commands (here, I named it iLinuxBot).

Figure 1: Server screenshot

Figure 2 shows the client receiving and executing commands.

Figure 2: Client screenshot

Potential

This program can cut down on manpower and time by installing or changing settings, by changing configuration files, or by rebooting all systems at the same time. In this version, the ability to interact with a specific single computer is not implemented, but it can be overcome by installing and running the SSH daemon on all machines.

All commands that don’t need iterative user interaction, such as yum or reboot, can be executed successfully from this system. We will extend support to other commands and also create a GUI interface in the next article.

As this is my first article, I would also like to hear your views on it. Do leave me comments in case of any queries or suggestions. (Here, I would like to express my gratitude to Ankit Sharma for his contribution to this article.)

Keep thinking in open and odd ways — that’s what a techno-freak is meant to do. Long live FOSS…!

iLinuxBot: Designing Botnets to Manage Linux Clients的更多相关文章

  1. Coping with the TCP TIME-WAIT state on busy Linux servers

    Coping with the TCP TIME-WAIT state on busy Linux servers 文章源自于:https://vincent.bernat.im/en/blog/20 ...

  2. Linux 驱动开发

    linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...

  3. [译]使用chage来管理Linux密码过期时间的七个例子

    本文译自 7 Examples to Manage Linux Password Expiration and Aging Using chage 本文主要介绍命令chage的使用,译文会对原文内容会 ...

  4. Open Source VOIP applications, both clients and servers (开源sip server & sip client 和开发库)

    SIP Proxies SBO SIP Proxy Bypass All types of Internet Firewall JAIN-SIP Proxy Mini-SIP-Proxy A very ...

  5. Manjaro Linux安装singularity-container

    技术背景 容器化技术在各种生产领域已经得到了广泛的应用,这得益于容器的轻量化(相比于虚拟机而言),安全性(隔离弱于虚拟机,但是权限控制得当的情况下也可以认为是安全隔离的)以及系统级虚拟化带来的高可用性 ...

  6. ovirt user guide

    Contents [hide]  1 ⁠Accessing the User Portal 1.1 Logging in to the User Portal 1.2 Logging out of t ...

  7. time_wait状态如何处理和建议

    TL;DR: do not enable net.ipv4.tcp_tw_recycle. UPDATED (2017.09): net.ipv4.tcp_tw_recycle has been re ...

  8.  Go is more about software engineering than programming language research.

    https://talks.golang.org/2012/splash.article Go at Google: Language Design in the Service of Softwar ...

  9. 使用Windows Azure的VM安装和配置CDH搭建Hadoop集群

    本文主要内容是使用Windows Azure的VIRTUAL MACHINES和NETWORKS服务安装CDH (Cloudera Distribution Including Apache Hado ...

随机推荐

  1. 基于MapReduce的矩阵乘法运算

    1.采用两个MapReduce运算串联来实现 Pik= Mij*Njk 第一步: Map函数:将每个矩阵运算mij传给键值对(j,(M,i,mij)),将每个矩阵元素njk传给键值对(j,(N,k,n ...

  2. Hadoop开发环境简介(转)

    1.Hadoop开发环境简介 1.1 Hadoop集群简介 Java版本:jdk-6u31-linux-i586.bin Linux系统:CentOS6.0 Hadoop版本:hadoop-1.0.0 ...

  3. 转】用Maven构建Mahout项目

    原博文出自于: http://blog.fens.me/hadoop-mahout-maven-eclipse/ 感谢! 用Maven构建Mahout项目 Hadoop家族系列文章,主要介绍Hadoo ...

  4. 游戏模块分析总结(2)之UI、操作篇

    转自:http://www.gameres.com/309812.html 游戏模块分析总结(2)之UI.操作篇 发布者: wuye | 发布时间: 2014-12-12 15:03| 评论数: 0 ...

  5. cocos2d-x 3.2 DrawNode 绘图API

    关于Cocos2d-x 3.x 版本的绘图方法有两种: 1.使用DrawNode类绘制自定义图形. 2.继承Layer类重写draw()方法. 以上两种方法都可以绘制自定义图形,根据自己的需要选择合适 ...

  6. Objective C静态代码扫描和代码质量管理 OClint + SonarQube

    OClint是针对C, C++及Objective C代码的静态扫描分析工具,而SonarQube是一个开源的代码质量管理平台.本文将实现将OClint的扫描结果导入到SonarQube中,已实现对O ...

  7. Lotus 迁移到Exchange POC 之安装Exchange 2010!

    我们登录到Exchange 2010服务器,双击setup 安装Exchange 2010,双击setup.exe完成安装:

  8. 结构类模式(五):外观(Facade)

    定义 为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用. UML 优点 对客户屏蔽了其子系统组件,因而减少了客户处理对象的数目,并使得子系统实用起来更方便. ...

  9. 一个python

    #!/usr/bin/env python #coding=utf-8 import os # 遍历文件 r=input("type a directory name:") for ...

  10. jquery 应用小结

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...