你们信不信一句Console.WriteLine就能让你的控制台程序失去响应
好久没更新博客了,今天是扒衣见君节,难得闲下来就来说说一个最近有趣的发现吧.
首先废话不多说,直接上代码吧
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var bytes = new byte[4096]; 6 for (int i = 0; i < bytes.Length; i++) 7 { 8 bytes[i] = 7; 9 } 10 11 Console.WriteLine(Encoding.ASCII.GetString(bytes)); 12 string line = Console.ReadLine();//你已经死了 这部分是没有机会跑到了............ 13 while (line != "ok") 14 { 15 Console.WriteLine(line); 16 line = Console.ReadLine(); 17 } 18 } 19 }
有兴趣的童鞋可以建个控制台程序跑一下,看看会不会程序失去响应.看回复中的信息,貌似WIN8.1和WIN10都没这个问题.我这边是在WIN7SP1下测试会失去响应的.如果还有用老掉牙XP的可以测试一下结果发上来看看.
为什么会挂掉呢?
关键就在于这个ASCII代码7,请看下图的ASCII码表.
ASCII的7代表BELL,也就是让主板上的蜂鸣器叫一声,就和你电脑刚刚开机时候的滴一声一样.所以输出ASCII的7就会让主板蜂鸣器叫一声,不过现在都是WINDOWS接管了,不是当年DOS年代了,蜂鸣器这部分由beep.sys这个驱动文件接管了,WIN7下的beep.sys会从声卡发声,XP下的beep.sys还是老样子走主板蜂鸣器的.题外话,当初机器狗病毒也会修改这个beep.sys,毕竟权限是ring0的,拿最高权限和杀毒软件干才是硬道理……
所以我们用Console.WriteLine输出ASCII代码7的时候,等于是调用了系统函数去发声,而不仅仅是在控制台上打印文本.当我们输出大量的ASCII代码7的时候,就会不断的去调用这个系统函数,你会发现进程中有个负责DComLaunch的svchost进程基本上进入死循环状态,而你的控制台程序,在系统函数调用结束之前是不会再有响应了……
这玩意能干什么呢?
说了这么多,那么这个问题有什么利用价值呢?其实利用价值还是挺大的,很多做服务类程序的人很喜欢直接上手开一个控制台程序,还喜欢把异常信息之类的打印在控制台上,如果你直接显示了用户的输入,那么我只要发一堆ASCII代码7过来,你的服务基本上就挂了……
虽然我只是在C#里面做了测试,但是不表示其他的语言就没有影响了,毕竟都是做成WINDOWS控制台程序的,有对应其他语言环境的可以试试看.