seteuid0's blog
Themed by Diary.
编码版b374k实现分析

实验PHP+SELINUX的时候,使用B374k,发现PHP文件的上下文意外的发生了变化,Inode号却没有发生变化,审计日志里也找不到relabel相关信息,就想一探究竟。 看代码发现上下文变化的这个版本是代码进行了编码处理的,从google code里找到的那些没有编码处理的版本上下文不会发生变化,看来只能对解码处理。 第一层使用了简单的“.“符号把字符串进行了分割,将$b374k=@create_function('$x',‘ev’.‘al’.'(gz'.‘inf’.‘late’.'(bas'.‘e64’.'_de'.‘co’.‘de($x)));');处理后就可以看到(gzinflate(base64_decode($x)));使用这个函数把后面的解码就可以得到解密后的代码。将代码格式化处理下,可以看到前半部分还是编码后的代码,后半部分有一些功能代码。

eval(gzinflate(base64_decode($x7774cacf))); rebirth(); eval(gzinflate(base64_decode(hate($xc3a649b2,$xec8e9aa2))));

同样,去掉eval,通过gzinflate(base64_decode($x7774cacf))解码,得到上面的功能代码,将解码后的内容格式化可以得到

里面是基础的编码、解码、生成随机数功能函数,可以注意到里面的rebirth函数,该函数将该PHP文件重新编码后替换当前的PHP文件。而随后的代码便调用了rebirth()函数,实现了这个webshell的rebirth。 而eval(gzinflate(base64_decode(hate($xc3a649b2,$xec8e9aa2))));就是执行本次请求的功能。可以找一个文件将该解码后的内容拷贝进去进行验证,功能与预期一致。 目前知道了上下文改变是由于用新生成的文件替换了之前的老文件,但是为什么inode号会保持一致?对该文件进行审计,将日志处理后可以看到。

syscall=4 ppid=2563 pid=2617 syscall=2 ppid=2563 pid=13403 syscall=2 ppid=2563 pid=13403 syscall=21 ppid=2563 pid=13403 syscall=2 ppid=2563 pid=13403 syscall=87 ppid=2563 pid=13403 syscall=82 ppid=2563 pid=13403 syscall=2 ppid=2563 pid=13404 syscall=2 ppid=2563 pid=13405 syscall=2 ppid=2563 pid=13405 syscall=2 ppid=2563 pid=13404 syscall=87 ppid=2563 pid=13405 syscall=82 ppid=2563 pid=13405 syscall=87 ppid=2563 pid=13404 syscall=82 ppid=2563 pid=13404 syscall=2 ppid=2563 pid=13406 syscall=2 ppid=2563 pid=13406 syscall=87 ppid=2563 pid=13406 syscall=82 ppid=2563 pid=13406 syscall=2 ppid=2563 pid=13407 syscall=2 ppid=2563 pid=13407 syscall=87 ppid=2563 pid=13407 syscall=82 ppid=2563 pid=13407

应该是apache多次解析了这个文件,进行了多次的unlink与rename操作。会不会是inode号重用呢,看如下实验:

$ touch inode $ ls -i inode 1048641 inode $ rm inode $ touch inode $ ls -i inode 1048641 inode $

到此可以明白只有上下文和文件内容发生变化的原因。 通过php直接执行测试发现,由于只执行了一次,所以inode号也随着发生了变化。 遗留问题:目前还无法确知为什么多次解析了这个PHP文件。