针对Linux平台下,PHP命令执行函数的底层原理分析。
本文《 命令执行底层原理探究-PHP (二) 》主要讲述的是第二部分:以PHP语言为对象,针对不同平台,进行环境准备、PHP内核源码的编译、运行、调试等。
PHP for Windows
针对Windows平台下:环境准备、PHP内核源码的编译、运行、调试等。
环境准备
环境部署情况:
Windows (Win10 Pro)
Visual Studio (Visual Studio Professional 2019)
Visual Studio Code (VSCode-win32-x64-1.51.1)
PHP Source Code (PHP 7.2.9)
PHP Windows SDK (php-sdk-binary-tools-php-sdk-2.2.0)
Source Insight (Source Insight 4.0)
php官方wiki对不同php版本编译的需求如下:
Visual C++ 14.0 (Visual Studio 2015) for PHP 7.0 or PHP 7.1.
Visual C++ 15.0 (Visual Studio 2017) for PHP 7.2, PHP 7.3 or PHP 7.4.
Visual C++ 16.0 (Visual Studio 2019) for master.
虽然官方wiki指出不同VS编译不同PHP版本,但是这里使用VS2019去编译PHP 7.2.9是没有问题的(兼容性)。
Visual Studio
Visual Studio 面向任何开发者的同类最佳工具,功能完备的 IDE,可用于编码、调试、测试和部署到任何平台。
Visual Studio 官网:介绍、下载
# 下载官网最新版 VS2019 http://visualstudio.microsoft.com/zh-hans/
Visual Studio 历史版本下载(这里无论是下载的社区版或企业版等,下载器都是一样的,在社区版下载器里面也可选择安装专业版、企业版)
http://visualstudio.microsoft.com/zh-hans/vs/older-downloads/ or http://my.visualstudio.com/Downloads?q=Visual%20Studio
这里下载Visual Studio Professional 2019主要的作用为:提供开发环境,编译PHP内核。
Visual Studio Professional 2019 安装情况:仅安装在 Visual Studio 中进行开发所需的工具和组件捆绑包。
[attach]56255[/attach]
Visual Studio Code
Visual Studio Code 常用于不同语言的项目开发、源代码编辑调试等工作。
官网:介绍、下载
添加相应扩展:c/c++扩展、代码辅助运行扩展
C/C++ Code Runner
PHP Source Code
PHP官方各个版本源代码下载
http://www.php.net/releases/ or http://github.com/php/php-src/releases
这里下载的版本为:PHP 7.2.9
PHP Windows SDK
PHP SDK is a tool kit for Windows PHP builds.
PHP SDK 依赖关系
The PHP SDK 2.2+ is compatible with PHP 7.2 and above. The PHP SDK 2.1 is required to build PHP 7.1 or 7.0.
新版SDK下载地址:构建PHP7
旧版SDK下载地址:构建PHP5
http://windows.php.net/downloads/php-sdk/ or http://github.com/Microsoft/php-sdk-binary-tools/tree/legacy
这里下载的PHP-SDK版本为2.2.0,下载解压并添加相应环境变量
xxx\php-sdk-binary-tools-php-sdk-2.2.0\bin xxx\php-sdk-binary-tools-php-sdk-2.2.0\msys2\usr\bin
Source Insight
环境准备部分,安装Visual Studio 2019后,运行在开始菜单里的Visual Studio 2019文件夹下的x86 Native Tools Command Prompt for VS 2019终端。
终端运行后,进入到PHP 7.2.9源代码目录中进行编译配置工作:
生成configure配置文件
执行源代码下buildconf.bat生成windows下的configure文件(configure.js)
xxx\php-7.2.9-windows-debug>buildconf.bat Rebuilding configure.js Now run 'configure --help' xxx\php-7.2.9-windows-debug>
查看configure支持的编译参数
xxx\php-7.2.9-windows-debug>configure.bat --help PHP Version: 7.2.9 Options that enable extensions and SAPI will accept 'yes' or 'no' as a parameter. They also accept 'shared' as a synonym for 'yes' and request a shared build of that module. Not all modules can be built as shared modules; configure will display [shared] after the module name if can be built that way. --enable-snapshot-build Build a snapshot; turns on everything it can and ignores build errors --with-toolset Toolset to use for the compilation, give: vs, clang, icc. The only recommended and supported toolset for production use is Visual Studio. Use others at your own risk. --with-cygwin Path to cygwin utilities on your system --enable-object-out-dir Alternate location for binary objects during build --enable-debug Compile with debugging symbols --enable-debug-pack Release binaries with external debug symbols (--enable-debug must not be specified) --enable-pgi Generate PGO instrumented binaries --with-pgo Compile optimized binaries using training data from folder --disable-zts Thread safety --with-prefix where PHP will be installed --with-mp Tell Visual Studio use up to [n,auto,disable] processes for compilation --with-php-build Path to where you extracted the development libraries (http://wiki.php.net/internals/windows/libs). Assumes that it is a sibling of this source dir (..\deps) if not specified --with-extra-includes Extra include path to use when building everything --with-extra-libs Extra library path to use when linking everything --with-analyzer Enable static analyzer. Pass vs for Visual Studio, clang for clang, cppcheck for Cppcheck, pvs for PVS-Studio --disable-ipv6 Disable IPv6 support (default is turn it on if available) --enable-fd-setsize Set maximum number of sockets for select(2) --with-snapshot-template Path to snapshot builder template dir --disable-security-flags Disable the compiler security flags --without-uncritical-warn-choke Disable some uncritical warnings --enable-sanitizer Enable address sanitizer extension --with-codegen-arch Architecture for code generation: ia32, sse, sse2, avx, avx2 --with-all-shared Force all the non obligatory extensions to be shared --with-config-profile Name of the configuration profile to save this to in php-src/config.name.bat --disable-test-ini Enable automatic php.ini generation. The test.ini will be put into the build dir and used to automatically load the shared extensions. --with-test-ini-ext-exclude Comma separated list of shared extensions to be excluded from the test.ini --enable-apache2handler Build Apache 2.x handler --enable-apache2-2handler Build Apache 2.2.x handler --enable-apache2-4handler Build Apache 2.4.x handler --disable-cgi Build CGI version of PHP --disable-cli Build CLI version of PHP --enable-crt-debug Enable CRT memory dumps for debugging sent to STDERR --enable-cli-win32 Build console-less CLI version of PHP --enable-embed Embedded SAPI library --enable-phpdbg Build phpdbg --enable-phpdbgs Build phpdbg shared --disable-phpdbg-webhelper Build phpdbg webhelper --disable-bcmath bc style precision math functions --with-bz2 BZip2 --disable-calendar calendar conversion support --disable-com-dotnet COM and .Net support --disable-ctype ctype --with-curl cURL support --with-dba DBA support --with-qdbm DBA: QDBM support --with-db DBA: Berkeley DB support --with-lmdb DBA: Lightning memory-mapped database support --with-enchant Enchant Support --enable-fileinfo fileinfo support --disable-filter Filter Support --enable-ftp ftp support --without-gd Bundled GD support --without-libwebp webp support --with-gettext gettext support --with-gmp Include GNU MP support. --disable-hash enable hash support --with-mhash mhash support --without-iconv iconv support --with-imap IMAP Support --with-interbase InterBase support --enable-intl Enable internationalization support --disable-json JavaScript Object Serialization support --with-ldap LDAP support --with-libmbfl use external libmbfl --enable-mbstring multibyte string functions --enable-mbregex multibyte regex support --disable-mbregex-backtrack check multibyte regex backtrack --without-mysqlnd Mysql Native Client Driver --with-oci8 OCI8 support --with-oci8-11g OCI8 support using Oracle 11g Instant Client --with-oci8-12c OCI8 support using Oracle Database 12c Instant Client --enable-odbc ODBC support --with-odbcver Force support for the passed ODBC version. A hex number is expected, default 0x0350. Use the special value of 0 to prevent an explicit ODBCVER to be defined. --disable-opcache whether to enable Zend OPcache support --disable-opcache-file whether to enable file based caching --with-openssl OpenSSL support --without-pcre-jit Enable PCRE JIT support --with-pgsql PostgreSQL support --with-pspell pspell/aspell (whatever it's called this month) support --without-readline Readline support --disable-session session support --enable-shmop shmop support --with-snmp SNMP support --enable-sockets SOCKETS support --with-sodium for libsodium support --with-sqlite3 SQLite 3 support --with-password-argon2 Argon2 support --with-config-file-scan-dir Dir to check for additional php ini files --enable-sysvshm SysV Shared Memory support --with-tidy TIDY support --disable-tokenizer tokenizer support --enable-zend-test enable zend-test extension --disable-zip ZIP support --disable-zlib ZLIB support --without-libxml LibXML support --without-dom DOM support --enable-exif Exchangeable image information (EXIF) Support --with-mysqli MySQLi support --enable-pdo Enable PHP Data Objects support --with-pdo-dblib freetds dblib (Sybase, MS-SQL) support for PDO --with-pdo-mssql Native MS-SQL support for PDO --with-pdo-firebird Firebird support for PDO --with-pdo-mysql MySQL support for PDO --with-pdo-oci Oracle OCI support for PDO --with-pdo-odbc ODBC support for PDO --with-pdo-pgsql PostgreSQL support for PDO --with-pdo-sqlite for pdo_sqlite support --with-pdo-sqlite-external for pdo_sqlite support from an external dll --disable-phar disable phar support --enable-phar-native-ssl enable phar with native OpenSSL support --without-simplexml Simple XML support --enable-soap SOAP support --without-xml XML support --without-wddx WDDX support --disable-xmlreader XMLReader support --with-xmlrpc XMLRPC-EPI support --disable-xmlwriter XMLWriter support --with-xsl xsl support xxx\php-7.2.9-windows-debug>
配置编译参数
这里的编译参数为:以Debug模式编译PHP内核源码
xxx\php-7.2.9-windows-debug>configure.bat --disable-all --enable-cli --enable-debug PHP Version: 7.2.9 Saving configure options to config.nice.bat Checking for cl.exe ... WARNING: Using unknown MSVC version 19.28.29335 Detected compiler MSVC 19.28.29335, untested Detected 32-bit compiler Checking for link.exe ... D:\QSoftware\VS2019Professional\Professional\VC\Tools\MSVC\14.28.29333\bin\HostX86\x86 Checking for nmake.exe ... Checking for lib.exe ... Checking for bison.exe ... Checking for sed.exe ... Checking for re2c.exe ... Detected re2c version 1.1.1 Checking for zip.exe ... Checking for lemon.exe ... Checking for mc.exe ... C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x86 Checking for mt.exe ... C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x86 WARNING: Debug builds cannot be built using multi processing Build dir: D:\QSec\Code-Audit\PHP\PHP-Source-Code\php-7.2.9-windows-debug\Debug_TS PHP Core: php7ts_debug.dll and php7ts_debug.lib Checking for wspiapi.h ... Enabling IPv6 support Enabling SAPI sapi\cli Checking for library edit_a.lib;edit.lib ... Enabling extension ext\date Enabling extension ext\pcre Enabling extension ext\reflection Enabling extension ext\spl Checking for timelib_config.h ... ext/date/lib Enabling extension ext\standard Creating build dirs... Generating files... Generating Makefile Generating main/internal_functions.c Generating main/config.w32.h Generating phpize Done. Enabled extensions: | Extension | Mode | | date | static | | pcre | static | | reflection | static | | spl | static | | standard | static | Enabled SAPI: | Sapi Name | | cli | | | | | Build type | Debug | | Thread Safety | Yes | | Compiler | MSVC 19.28.29335, untested | | Architecture | x86 | | Optimization | disabled | | Static analyzer | disabled | Type 'nmake' to build PHP xxx\php-7.2.9-windows-debug>
next(简写 n) : C语言级的断点定位。相当于其它调试器中的“Step Over (单步跟踪)”。单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。
step (简写 s):C语言级的断点定位。相当于其它调试器中的“Step Into (单步跟踪进入)”。单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数体。【前提: s会进入C函数内部,但是不会进入没有定位信息的函数(比如没有加-g编译的代码,因为其没有C代码的行数标记,没办法定位)。(比如:调试编译PHP内核源码,然后调试php代码底层实现,跟踪到了libc函数后,由于libc没有标记信息,导致s或n之后直接打印输出完成程序的调试)】
nexti(简写 ni):Next one instruction exactly。汇编级别的断点定位。作用和next指令相同,只是单步跟踪汇编代码,碰到call调用,不会进入汇编函数体。
stepi(简写 si):Step one instruction exactly。汇编级别的断点定位。作用和step指令相同,只是单步跟踪汇编代码,碰到call调用,会进入汇编函数体。【前提:当要进入没有调试信息的库函数调试的时候,用si是唯一的方法。当进入有调试信息的函数,用si和s都可以进入函数体,但是他们不同,si是定位到汇编级别的第一个语句,但是s是进入到C级别的第一个语句。】
进入编译好的PHP可执行文件目录下
$ cd Debug/bin
加载待调式的PHP文件
# gdb --args ./php -f test1.php GNU gdb (Debian 10.1-1+b1) 10.1 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word"... pwndbg: loaded 188 commands. Type pwndbg [filter] for a list. pwndbg: created $rebase, $ida gdb functions (can be used with print/break) Reading symbols from ./php... pwndbg>
对程序入口函数下断点,并查看断点信息
pwndbg> b main Breakpoint 1 at 0x46430e: file /mnt/hgfs/QSec/Code-Audit/PHP/PHP-Source-Code/php-7.2.9-linux-debug/sapi/cli/php_cli.c, line 1216. pwndbg> i b Num Type Disp Enb Address What 1 breakpoint keep y 0x000000000046430e in main at /mnt/hgfs/QSec/Code-Audit/PHP/PHP-Source-Code/php-7.2.9-linux-debug/sapi/cli/php_cli.c:1216 pwndbg>
运行至断点处
pwndbg> r
单步调式:n、ni、s、si
pwndbg> n
源码执行