首页 > 代码库 > Linux编程之给你的程序开后门

Linux编程之给你的程序开后门

技术分享
        switch(args[0][0])  //解析指令,看每个指令对应哪些意思
        {
            case ‘d‘:    //display
                switch(args[1][0])
                {
                    case ‘q‘:   //display queue
                    show_MQ(fd);
                    break;
                    case ‘d‘:   //display debug
                    show_debug_level(fd);
                    break;
 
                    default:
                        help_manual(fd);
                        break;
                }
                break;
 
            case ‘s‘:    //set
                switch(args[1][0])
                {
                    case ‘d‘: //set debug level
                    n = atoi(args[2]);  //将字符串转化为整数
                    fprintf(fd," debug level change from %d to %d",global.debug_level,n);
                    global.debug_level = n;  //更改log级别
                    break;
 
                    default:
                        help_manual(fd);
                        break;
                }
                break;
 
            default:
                help_manual(fd);
                break;
        }
 
技术分享

 

四、搭建debug界面
先上界面图:

技术分享

我们敲的每个命令都是通过该界面传递到程序那头的,比如“d d”就表示展示出现在系统运行时的log级别,而“s d”就是设置我们想要看的log级别,这样我们就可以实现通过程序后门动态修改程序走向了。
那该如何实现这个看似简单的交互界面呢?实现该交互界面,有几个关键点:
  • 我们需将程序的打印输出重定向到一个文件里
  • 使用shell脚本读出文件的内容
  • 我们输入的命令需写入到fifo中
以上三点就是做成界面的最重要的技术问题。
  1. 重定向输出
  一开始我是打算将标准输出、标准错误都重定向到文件里的额,但是想了想,还是想直接把打印内容直接输出到文件就好了。比如这样:
技术分享
     fd = fopen("/vob/ljsdpoenew3/exercise/debug_log2", "w+");
    if(fd == NULL)
    {
        MY_LOG(DEBUG, "open debug_log2 fail!\n");
        pthread_exit(0);
    }

fprintf(fd," debug level change from %d to %d",global.debug_level,n);
技术分享
  这样我们在debug center产生的打印都输出到文件debug_log2上了。

  2.利用脚本读出内容且将内容写入fifo

  要做到这点需要shell编程的简单知识,我们怎么将我们的输入放到fifo呢?我们怎么把log文件的内容读出来显示在显示屏呢?我想到首先是再写个client,进行进程间通信嘛,将命令写到fifo,同时也读出log文件的内容。但是,我发现利用shell就可以做到以上的事了,而且只需花费几行代码。
 
技术分享
#!/bin/bash
 
my_inp_fifo=/vob/ljsdpoenew3/exercise/debug_log    # 指定fifo文件
stty erase ^H    
 
while [ true ];
do
 
        read inp    #循环读入用户输入
        if [ "$inp" == "quit" ];then   #quit代表结束该界面
                exit 0
        fi
        echo $inp > $my_inp_fifo   #写入fifo
        cat debug_log2.txt         #显示log的内容
done
技术分享

 

那看看这个命令行界面跑起来是怎么的吧!
首先我们运行server进程
技术分享
 
sever进程不断产生消息并处理消息。
我们打开另一个窗口,并执行脚本./test.sh,进入界面
 技术分享
 
我们使用了d d命令看到了程序此时的debug级别,用d q看出了程序消息队列的情况。
 技术分享
 
我们使用了s d指令将debug level设置为0,此时屏幕没有任何打印输出,当我们在使用s d指令将level设置为-1(即将所有位置一),此时所有打印级别都打开了,屏幕又开始疯狂打印了。也就说,我们通过后门操控了程序,这里我们只是仅仅修改了程序的log级别,当然我们还可以做更多的事,只要依照这个框架往里面加指令,以及对应的处理操作,就可以实现了。
五、总结
所谓后门,就是一个可以操控程序的接口,这个接口仅仅用于开发者调试开发,不会开放给客户。所以这个后门的作用非常巨大,所以是开发者调试程序的一大利器。有人会想,我想用socket来代替fifo进行进程通信可以不,这样就可以做到远程主机操控程序了。我觉得是可以的,但是感觉利用telnet到目的主机再运行脚本操作比较安全。
最后给出源代码框架
技术分享
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <math.h>
  5 #include <sys/types.h>
  6 #include <sys/stat.h>
  7 #include <sys/prctl.h>
  8 #include "msg_def.h"
  9 #include "global.h"
 10  
 11 extern Queue_t MsgQueue;
 12 extern dashboard_t global;
 13  
 14  
 15 #define  MAX_NUM_ARGS  20
 16 #define  MAX_ARGS_SIZE  56
 17  
 18 static char args[MAX_NUM_ARGS][MAX_ARGS_SIZE];
 19  
 20 static int get_args(FILE *inputFile,FILE *fd)
 21 {
 22     char tmpBuffer[100];
 23     char tmpBuffer2[100];
 24     char *line = tmpBuffer;
 25     char separator[] = " ,\n\t";
 26     char *token;
 27     int  i;
 28     char eof;
 29  
 30     int num = 0;
 31  
 32     eof = !fgets(line, sizeof(tmpBuffer), inputFile);
 33     if (eof)
 34         return num;
 35  
 36     memcpy(tmpBuffer2,tmpBuffer,100);
 37  
 38  
 39     token = strtok(line, separator);
 40     while (num < MAX_NUM_ARGS && token)
 41     {
 42         strcpy(args[num], token);
 43         num++;
 44         token = strtok(NULL, separator);
 45     }
 46  
 47     for (i = num; i < MAX_NUM_ARGS; i++)
 48         args[i][0] = 0;
 49  
 50     if(num > 0)
 51     {
 52         fprintf(fd, "%s", tmpBuffer2);
 53     }
 54  
 55     return num;
 56 }
 57  
 58  
 59 static void help_manual(FILE* fd)
 60 {
 61     fprintf(fd,"\nd d         :           display current debug level\n");
 62     fprintf(fd,"d q         :           display msg queue length, head and tail\n");
 63     fprintf(fd,"s d [level] :           set debug [level] \n");
 64 }
 65  
 66 static void show_MQ(FILE* fd)
 67 {
 68     fprintf(fd," msg queue length:%d  head:%d  tail:%d \n",abs(MsgQueue.head-MsgQueue.rear),MsgQueue.head,MsgQueue.rear);
 69 }
 70  
 71 static void show_debug_level(FILE* fd)
 72 {
 73     fprintf(fd," current debug level: %d\n", global.debug_level);
 74 }
 75  
 76  
 77  
 78 void debug_center()
 79 {
 80     int rc,num,n;
 81     FILE* fp;
 82     FILE* fd;
 83  
 84     MY_LOG(DEBUG,"Hi,debug!\n");
 85  
 86  
 87     system("rm /vob/ljsdpoenew3/exercise/debug_log");
 88     system("rm /vob/ljsdpoenew3/exercise/debug_log2");
 89     rc = mkfifo("/vob/ljsdpoenew3/exercise/debug_log", 0666);
 90     if(rc < 0)
 91     {
 92        MY_LOG(DEBUG, "make fifo fail!\n");
 93        pthread_exit(0);
 94     }
 95  
 96     fp = fopen("/vob/ljsdpoenew3/exercise/debug_log", "r");
 97     if(fp == NULL)
 98     {
 99         MY_LOG(DEBUG, "open debug_log fail!\n");
100         pthread_exit(0);
101     }
102  
103     fd = fopen("/vob/ljsdpoenew3/exercise/debug_log2", "w+");
104     if(fd == NULL)
105     {
106         MY_LOG(DEBUG, "open debug_log2 fail!\n");
107         pthread_exit(0);
108     }
109     //freopen("/vob/ljsdpoenew3/exercise/debug_log2.txt", "w+", fd);
110  
111     fprintf(fd,"  \n==================================================\n");
112     fprintf(fd,"             Welcme to Debug Center!");
113     fprintf(fd,"  \n==================================================\n\n");
114     help_manual(fd);
115     //fflush(fd);
116  
117     while(1)
118     {
119         fflush(fd);
120         fprintf(fd,"\n\nmy_diag>");
121         num = get_args(fp,fd);
122         if(num < 1)
123         {
124             freopen("/vob/ljsdpoenew3/exercise/debug_log", "r", fp);
125             fflush(fd);
126             continue;
127         }
128         fprintf(fd,"\n\nmy_diag>");
129         switch(args[0][0])
130         {
131             case ‘d‘:    //display
132                 switch(args[1][0])
133                 {
134                     case ‘q‘:   //display queue
135                     show_MQ(fd);
136                     break;
137                     case ‘d‘:   //display debug
138                     show_debug_level(fd);
139                     break;
140  
141                     default:
142                         help_manual(fd);
143                         break;
144                 }
145                 break;
146  
147             case ‘s‘:    //set
148                 switch(args[1][0])
149                 {
150                     case ‘d‘: //set debug level
151                     n = atoi(args[2]);
152                     fprintf(fd," debug level change from %d to %d",global.debug_level,n);
153                     global.debug_level = n;
154                     break;
155  
156                     default:
157                         help_manual(fd);
158                         break;
159                 }
160                 break;
161  
162             default:
163                 help_manual(fd);
164                 break;
165         }
166  
167     }
168 }
技术分享

 

Linux编程之给你的程序开后门