PHP_SCREW解密PM9SCREW

前言

要对公司内部的某堡垒机系统做测试审计,但是碰到了加密的PHP文件,因为是采购的第三方整套设备所以只能自己做解密啦,加密形式如下图:
image

收集信息

收集了一下PM9SCREW的信息,该使用的加密拓展名字叫PHP_Screw,这是一款免费的针对PHP源码进行加密的PHP的扩展,可以自定义加密的key,加密后的文件效率还不会下降。其原理是通过压缩取反然后跟加密的key做异或加密的方式,在使用的时候通过.so文件的拓展文件进行解密然后再运行。并且找到了两个前人写好的工具,参考文章及工具链接如下。
https://www.skactor.tk/2018/03/26/php-screw%E7%9A%84%E5%8A%A0%E5%AF%86%E5%92%8C%E8%A7%A3%E5%AF%86%E6%8E%A2%E7%A9%B6%EF%BC%88%E4%BA%8C%EF%BC%89%E8%A7%A3%E5%AF%86%E7%AE%97%E6%B3%95%E4%B8%8Epython%E5%AE%9E%E7%8E%B0/
https://github.com/firebroo/screw_decode

解密过程

通过前文得知有加密密钥存储的.so拓展文件很关键,所以先寻找文件image
找到了之后发现也是二进制文件
image
于是IDA搞起,先找到pm9screw相关函数
image
然后追踪相关变量
image
找到加密的密钥口令
image
hex转为十进制
image
然后另一个函数中找到头部变量(这里为默认值)
image

然后将找到的密钥和头部放入前文的工具中使用即可

脚本

前文中的工具只会对php文件解密后复制成.php.decode的同名文件,所以写了个脚本来把除了原本的php文件之外的文件按目录结构复制出来,在这里也放出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
import shutil

def copy_tree_ext(exts,src,dest):
fp={}
extss=exts.lower().split()
for dn,dns,fns in os.walk(src):
for fl in fns:
if os.path.splitext(fl.lower())[1][1:] not in extss:
if dn not in fp.keys():
fp[dn]=[]
fp[dn].append(fl)
for k,v in fp.items():
relativepath=k[len(src)+1:]
newpath=os.path.join(dest,relativepath)
for f in v:
oldfile=os.path.join(k,f)
print("复制 ["+oldfile+"] 到 ["+newpath+"]")
if not os.path.exists(newpath):
os.makedirs(newpath)
shutil.copy(oldfile,newpath)

copy_tree_ext('php','/srcdir','/destdir')

然后稍微改一改再把.php.decode后缀改成.php就大功告成了,因为忘记保存所以偷个懒就不再放代码了。

总的来说感谢前人的研究,以及如果使用该拓展加密,千万记得改掉或者隐去头部的几个字符不要留下线索,以及把.so文件隐藏好。

PS:遇到一个hexo的小坑

1
YAMLException: can not read a block mapping entry; a multiline key may not be an implicit key at line 4, column 1:

记得要在所有:后面加空格,以及中英文字符一定得注意。