Linux编程可以给你的程序开后门

这里说的“后门”并不是教你做坏事,而是让你做好事,搭建自己的调试工具更好地进行调试开发。我们都知道,当程序发生异常错误时,我们需要定位到错误,有时我们还想,我们在不修改程序的前提下,就能通过log来定位错误呢?有人会说,我在我的程序里加多点打印就好了,程序每做一步我就加一行打印,到时一查log就知道程序在哪一步死掉的了。这个方法在小程序里也许会行得通,但是,在一个大型系统,每秒的log达到几百条,那时我们怎么能在这繁多的log里找出我们想要的那条的log的?这工作量大得夸张。工程中的解决方法就是给自己的程序开个后门专门给开发人员来调试程序。
当然我们通过后门能做的不仅仅是这些,具体来说,后门就是我们程序眼和跑着的程序交流的一道门。
搭建这么一个程序后门主要有这么几个关键点:
在进程里开一个线程用于充当debug center
该线程通过fifo接收开发人员传给它的命令
解析这些命令
用脚本搭建简单的命令行界面
一、创建debug center线程
这个就没什么好说了,我使用了上篇文章《linux编程之自定义消息队列》所搭建的消息队列框架,将其中的msg_sender1改造为debug_center线程,作为我们的程序后门,我们跟程序交互就是从这里开始的。
if(pthread_create(&debug_thread_id, null, (void*)debug_center, null)){ my_log(fatal,create debug center fail!\n); return -1;}
二、创建fifo
为什么要创建fifo(有名管道)?因为我们需要跟我们的程序进行通信,我们需要把我们的指令告诉程序,那就需要一个通信途径,fifo就是一个很好的选择。我们把我们的指令写进管道,程序将指令从管道出,然后执行该指令,这样子我们程序后门的通信模型就出来了。why解决了,是时候解决how了。
对于管道的操作,我是这么做的:
system(rm /vob/ljsdpoenew3/exercise/debug_log); //每次进入debug center我们都将原来的fifo文件删除,避免影响后面操作rc = mkfifo(/vob/ljsdpoenew3/exercise/debug_log, 0666); //创建fifoif(rc < 0){ my_log(debug, make fifo fail!\n); pthread_exit(0);} fp = fopen(/vob/ljsdpoenew3/exercise/debug_log, r); //打开fifo,读取指令if(fp == null){ my_log(debug, open debug_log fail!\n); pthread_exit(0);}
读fifo我们解决了,那怎么将我们的指令写进fifo呢?这里我打算使用shell的read指令,文章后面会解释如何实现。
三、解析指令
解析指令又可以分为两个步骤:
将从fifo取得数据进行格式解析,比如我定义了d d的意思是display debug,即显示现在的debug级别,那么我们程序就得首先对原始数据进行格式处理。
将指令进行命令解析,执行相应操作。
格式处理:
static int get_args(file *inputfile){ char tmpbuffer[100]; char *line = tmpbuffer; char separator[] = ,\n\t; char *token; int i; char eof; int num = 0; eof = !fgets(line, sizeof(tmpbuffer), inputfile); if (eof) return num; token = strtok(line, separator); while (num < max_num_args && token) { strcpy(args[num], token); num++; token = strtok(null, separator); } for (i = num; i $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 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 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 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 );121 num = get_args(fp,fd);122 if(num );129 switch(args[0][0])130 {131 case 'd': //display132 switch(args[1][0])133 {134 case 'q': //display queue135 show_mq(fd);136 break;137 case 'd': //display debug138 show_debug_level(fd);139 break;140 141 default:142 help_manual(fd);143 break;144 }145 break;146 147 case 's': //set148 switch(args[1][0])149 {150 case 'd': //set debug level151 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 }

苹果正式公布iPhone 12系列售后保修费用,来看看详细价格吧
vivo蝉联两季销量冠军 面临战略机遇点
人们是否准备好迎接下一代AI技术革命
MIMXRT1021CAG4B GPIO口复位值详解
UltraSoC宣布提供业界首款RISC-V处理器跟踪IP产品
Linux编程可以给你的程序开后门
远心镜头和普通镜头谁更有优势?
Counterpoint:联发科正加快在旗舰智能手机市场中的渗透
对于电缆生产行业,它对测径仪的需求是什么
科大讯飞再添A.I.学习利器,新品扫描词典笔正式发布
中国2019年第二季度可穿戴设备市场报告公布 小米第一华为紧随其后
Python 函数默认返回None的原因
ROHM开发出零漂移运算放大器LMR1002F-LB
利亚德:利晶月产能已到1600KK,计划明年扩产至4000KK
喜获认证!M5Stack Core2兼容Harmony
VR市场投资热度骤降 惠普披甲上阵战“寒冬”
三星Galaxy S11系列新机有望在2月份亮相
面向NFV和SDN的自动化的编排系统:智能化ONAP社区
如何提高FPGA的工作频率
拆卸扁平封装集成电路简法