本文最后更新于:9 天前
在出某php框架相关的CTF赛题的时候,意外地发现了该框架在运行状态下,phar反序列化无法利用成功
于是就想着趁此机会学习一下从C层面调试php代码
源码编译
首先从github上clone下php的源码,并切换到我们想要的版本分支
1 2 3
| git clone https://github.com/php/php-src.git cd php-src git checkout PHP-7.4.33
|
然后执行buildconf生成configure脚本
根据P神给出的的dockerfile,再结合GPT将绝大部分基础拓展都配置好
若缺少什么库请自行结合ai进行安装,这个部分主要问题可能就是库少安装了,或者是安装好的路径与默认路径不匹配
若切换版本分支编译导致出问题,请自行make clean并清除缓存重新编译
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| ./configure \ --enable-option-checking=fatal \ --prefix=/source/php7.4/ \ --enable-bcmath \ --enable-calendar \ --enable-debug \ --enable-embed \ --enable-exif \ --enable-ftp \ --enable-gd \ --enable-intl \ --enable-mbstring \ --enable-mysqlnd \ --enable-opcache \ --enable-pcntl \ --enable-phar \ --enable-shmop \ --enable-soap \ --enable-sockets \ --enable-sysvmsg \ --enable-sysvsem \ --enable-sysvshm \ --enable-xmlreader \ --enable-xmlwriter \ --with-bz2 \ --with-curl \ --with-freetype \ --with-gettext \ --with-gmp \ --with-jpeg \ --with-kerberos \ --with-libedit \ --with-mhash \ --with-mysqli \ --with-openssl \ --with-password-argon2 \ --with-pdo-dblib=/usr \ --with-libdir=/lib/x86_64-linux-gnu \ --with-pear \ --with-pdo-mysql \ --with-pdo-pgsql \ --with-pdo-sqlite=/lib \ --with-readline \ --with-sodium \ --with-tidy \ --with-xmlrpc \ --with-xsl \ --with-zip \ --with-zlib
|
最后编译
然后得到这些个重要目录

执行编译生成的可执行文件

最后就是在vscode进行配置debug了,首先安装好必要插件:

在此处新增我们的debug配置:

内容如下:
注意php可执行文件的路径program参数根据自己的实际情况修改,以及启动参数args
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| { "name": "php source debug", "type": "cppdbg", "request": "launch", "args": [ "-f", "/root/php-src/test.php" ], "stopAtEntry": true, "externalConsole": false, "cwd": "${fileDirname}", "program": "/source/php7.4/bin/php", "MIMode": "gdb", "miDebuggerPath": "gdb", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ] }
|
这时候点击debug,会自动停在php-cli的main主入口

使用以下命令能够定位我们需要的函数的所在文件的位置
1
| grep -rn "PHP_FUNCTION(file_get_contents)" /root/php-src/
|
通过源码编译的php一开始不会把php.ini移入生成目录中,可以用下面目录确定php.ini应该放在哪
1
| /source/php7.4/bin/php --ini
|
然后把二者之一cp过去成php.ini即可

关于拓展插件:
我在编译完成之后在对应的插件目录没有找到共享库,只能手动编译
在源码的ext目录下存在着基本插件的源码,可以手动编译
1 2 3 4 5 6
| cd php-src cd ext/exif phpize ./configure --with-php-config=/source/php7.4/bin/php-config make make install
|
若想调试web应用下的情况,可以修改launch.json中args参数
1 2 3 4 5 6
| "args": [ "-S", "0.0.0.0:7777", "-t", "/var/www/html" ],
|
php内核推荐文章
https://github.com/pangudashu/php7-internal