PHP C源码调试

本文最后更新于: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脚本

1
./buildconf

根据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

最后编译

1
make & make install

然后得到这些个重要目录

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

最后就是在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