AI 摘要(由 ChatGPT 总结生成):
本文详细介绍了如何在Android系统上使用NDK交叉编译Python 3的过程。文章涉及了所需工具和库的下载,包括Python、NDK、OpenSSL、LibreSSL、zlib等,并展示了具体的编译步骤。此外,还包括了设置环境变量和部署到Android设备上的方法,最后提供了一个生成Python 3二进制文件的示例,以及如何在Android设备上运行编译后的Python。

前期准备

本次使用的是基于 Android NDK 去交叉编译 Python ,使得在 Android 上也能玩 Python 。编译过程中相关工具必不可少,如下:

本文基于 Debian 系 Linux 系统进行编译操作演示,且交叉编译 Python 的时候最好保证系统上的 Python 版本和要编译的 Python 版本一致,即先编译安装 Linux 版本的,再编译 arm 版本。

为模拟 Android 的文件系统路径,故此处会将 Python 编译至 /data/local/tmp 目录下,创建目录:

mkdir -p /data/local/tmp

此处我们将上述的工具等上传到 /data/local 目录下,此处我们编译一份 Python 3.7 的版本。先将相关压缩包解压,解压命令如下:

# 解压 NDK unzip android-ndk-r25c-linux.zip # 解压 OpenSSL tar -zxvf openssl-1.1.1w.tar.gz # 解压 zlib tar -zxvf zlib-1.3.tar.gz # 解压 Python3.7 tar -xvf Python-3.7.17.tar.xz # 解压 LibreSSL tar -zxvf libressl-3.8.1.tar.gz

最终如下图:

image-20230921135837747

image-20230921135837747

下面开始对相关组件等交叉编译,下述操作建议在 root 用户下操作。

交叉编译 zlib

编译该工具是让 Python 支持使用 pip 命令等工具。

zlibconfigure 不支持设置 --host 项,因此我们先直接 configure 一下,然后手动更改生成的 Makefile 文件,相关命令如下:

# 前往 zlib 目录 root@ubuntu:/data/local# cd zlib-1.3/ # 创建 build 和 out 文件夹 root@ubuntu:/data/local/zlib-1.3# mkdir -p build out # 前往 build 目录 root@ubuntu:/data/local/zlib-1.3# cd build/ # 执行 configure 命令 root@ubuntu:/data/local/zlib-1.3/build# ../configure --prefix=/data/local/zlib-1.3/out Checking for gcc... Checking for shared library support... Building shared library libz.so.1.3 with gcc. Checking for size_t... Yes. Checking for off64_t... Yes. Checking for fseeko... Yes. Checking for strerror... Yes. Checking for unistd.h... Yes. Checking for stdarg.h... Yes. Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf(). Checking for vsnprintf() in stdio.h... Yes. Checking for return value of vsnprintf()... Yes. Checking for attribute(visibility) support... Yes. root@ubuntu:/data/local/zlib-1.3/build#

使用 vim 命令打开编辑 Makefile 文件,将其中的 CCARRANLIB 都修改为 arm-linux 交叉编译器的相关参数,也将 LDSHAREDCPP 两项中的 gcc 替换为 CC 修改后的内容,具体修改地方如下:

root@ubuntu:/data/local/zlib-1.3/build# vim Makefile …… CC=/data/local/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang …… LDSHARED=/data/local/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang -shared -Wl,-soname,libz.so.1,--version-script,../zlib.map CPP=/data/local/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang -E …… AR=/data/local/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar …… RANLIB=/data/local/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib ……

Makefile 文件修改后保存退出,接下来执行下面两条命令,完成交叉编译:

make make install

编译后的内容在 zlib 源码的 out 目录下。

交叉编译 OpenSSL

编译该工具是使得 Python 支持加密协议。

前往 OpenSSL 目录,将下述脚本保存到 OpenSSL 源码的同目录下,脚本内容如下,部分内容参数请按提示自定义更新:

#!/bin/bash COMPILE_ROOT="$(dirname $(readlink -f "$0"))" # NDK 目录,按需更换 export ANDROID_NDK_ROOT=/data/local/android-ndk-r25c export ANDROID_GCC_ROOT=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64 export ANDROID_GCC_PATH=${ANDROID_GCC_ROOT}/bin BUILD_PATH=${COMPILE_ROOT}/build OUT_PATH=${COMPILE_ROOT}/out CROSS_COMPILER=aarch64-linux-android- CROSS_COMPILER_CLANG=aarch64-linux-android33- #prepare mkdir -p ${BUILD_PATH} mkdir -p ${OUT_PATH} export PATH=${ANDROID_NDK_ROOT}:${ANDROID_GCC_PATH}:$PATH export ARCH="aarch64" export CC="${CROSS_COMPILER_CLANG}clang -pie -fPIE" export CPP="${CROSS_COMPILER_CLANG}clang -E -pie -fPIE" export CXX="${CROSS_COMPILER_CLANG}clang++ -pie -fPIE" # 下方的链接文件,新版 NDK 变成了 llvm-xx 的文件格式了,可能旧版的还存在诸如 aarch64-linux-android-xx 的格式文件,若为旧版格式文件,可将下面注释的取消注释,并将 llvm-xx 格式的命令参数反向注释掉,按需修改 #export AS="${CROSS_COMPILER}as" export LD="${CROSS_COMPILER}ld -pie -fPIE" export GDB="${CROSS_COMPILER}gdb" export STRIP="${CROSS_COMPILER}strip" #export RANLIB="${CROSS_COMPILER}ranlib" #export OBJCOPY="${CROSS_COMPILER}objcopy" #export OBJDUMP="${CROSS_COMPILER}objdump" #export AR="${CROSS_COMPILER}ar" #export NM="${CROSS_COMPILER}nm" export RANLIB="llvm-ranlib" export AR="llvm-ar" export NM="llvm-nm" export OBJCOPY="llvm-objcopy" export OBJDUMP="llvm-objdump" export AS="llvm-as" #export READELF="${CROSS_COMPILER}readelf" export READELF="llvm-readelf" export M4=m4 export TARGET_PREFIX=$CROSS_COMPILER export CXXFLAGS="-D__ANDROID_API__=33 " cd ${BUILD_PATH} config_soft(){ ../config --prefix=${OUT_PATH} -no-asm -no-shared -no-async } make_soft(){ make -j $(nproc) } make_soft_install(){ make install } make_clean(){ make clean } case "$1" in config_soft) config_soft ;; make_soft) make_soft ;; make_soft_install) make_soft_install ;; make_clean) make_clean ;; esac

先使用 config_soft 生成一些文件,命令如下:

root@ubuntu:/data/local/openssl-1.1.1w# vim make_openssl.sh root@ubuntu:/data/local/openssl-1.1.1w# bash make_openssl.sh config_soft Operating system: x86_64-whatever-linux2 Configuring OpenSSL version 1.1.1w (0x1010117fL) for linux-x86_64 Using os-specific seed configuration Creating configdata.pm Creating Makefile ********************************************************************** *** *** *** OpenSSL has been successfully configured *** *** *** *** If you encounter a problem while building, please open an *** *** issue on GitHub <https://github.com/openssl/openssl/issues> *** *** and include the output from the following command: *** *** *** *** perl configdata.pm --dump *** *** *** *** (If you are new to OpenSSL, you might want to consult the *** *** 'Troubleshooting' section in the INSTALL file first) *** *** *** ********************************************************************** root@ubuntu:/data/local/openssl-1.1.1w#

然后在 make_softmake_soft_install 完成 OpenSSL 的编译:

root@ubuntu:/data/local/openssl-1.1.1w# bash make_openssl.sh make_soft …… root@ubuntu:/data/local/openssl-1.1.1w# bash make_openssl.sh make_soft_install ……

若无报错,即完成 OpenSSL 的交叉编译,编译后的内容在 OpenSSL 源码的 out 目录下。

交叉编译 LibreSSL

编译该工具是使得 Python 支持加密协议,相当于 OpenSSL 的替代。

前往 libressl 目录,将下述脚本保存到 libressl 源码的同目录下,脚本内容如下,部分内容参数请按提示自定义更新:

#!/bin/bash COMPILE_ROOT="$(dirname $(readlink -f "$0"))" # NDK 目录,按需更换 export ANDROID_NDK_ROOT=/data/local/android-ndk-r25c export ANDROID_GCC_ROOT=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64 export ANDROID_GCC_PATH=${ANDROID_GCC_ROOT}/bin BUILD_PATH=${COMPILE_ROOT}/build OUT_PATH=${COMPILE_ROOT}/out CROSS_COMPILER=aarch64-linux-android- CROSS_COMPILER_CLANG=aarch64-linux-android33- #prepare mkdir -p ${BUILD_PATH} mkdir -p ${OUT_PATH} export PATH=${ANDROID_NDK_ROOT}:${ANDROID_GCC_PATH}:$PATH export ARCH="aarch64" export CC="${CROSS_COMPILER_CLANG}clang -pie -fPIE" export CPP="${CROSS_COMPILER_CLANG}clang -E -pie -fPIE" export CXX="${CROSS_COMPILER_CLANG}clang++ -pie -fPIE" # 下方的链接文件,新版 NDK 变成了 llvm-xx 的文件格式了,可能旧版的还存在诸如 aarch64-linux-android-xx 的格式文件,若为旧版格式文件,可将下面注释的取消注释,并将 llvm-xx 格式的命令参数反向注释掉,按需修改 #export AS="${CROSS_COMPILER}as" export LD="${CROSS_COMPILER}ld -pie -fPIE" export GDB="${CROSS_COMPILER}gdb" export STRIP="${CROSS_COMPILER}strip" #export RANLIB="${CROSS_COMPILER}ranlib" #export OBJCOPY="${CROSS_COMPILER}objcopy" #export OBJDUMP="${CROSS_COMPILER}objdump" #export AR="${CROSS_COMPILER}ar" #export NM="${CROSS_COMPILER}nm" export RANLIB="llvm-ranlib" export AR="llvm-ar" export NM="llvm-nm" export OBJCOPY="llvm-objcopy" export OBJDUMP="llvm-objdump" export AS="llvm-as" #export READELF="${CROSS_COMPILER}readelf" export READELF="llvm-readelf" export M4=m4 export TARGET_PREFIX=$CROSS_COMPILER export CXXFLAGS="-D__ANDROID_API__=33 " cd ${BUILD_PATH} config_soft(){ ../configure --host=aarch64-linux-android \ --host=aarch64-linux \ --build=x86_64-linux-gnu \ --target=aarch64-linux-android \ --prefix=${OUT_PATH} } make_soft(){ make -j $(nproc) } make_soft_install(){ make install } make_clean(){ make clean } case "$1" in config_soft) config_soft ;; make_soft) make_soft ;; make_soft_install) make_soft_install ;; make_clean) make_clean ;; esac

然后编译安装,安装的文件在 out 目录下:

root@ubuntu:/data/local/libressl-3.8.1# vim make_libressl.sh root@ubuntu:/data/local/libressl-3.8.1# bash make_libressl.sh config_soft …… root@ubuntu:/data/local/libressl-3.8.1# bash make_libressl.sh make_soft …… root@ubuntu:/data/local/libressl-3.8.1# bash make_libressl.sh make_soft_install ……

交叉编译 Python

下面就到了交叉编译 Python 的环节了。

此处需注意一下,交叉编译前,系统内需要一份同版本的 Python ,所以我们先编译安装一份当前系统下的 Python ,命令如下:

# 先安装一些库 root@ubuntu:/data/local/Python-3.7.17# apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev git libgdbm-dev libdb-dev libpcap-dev libexpat1-dev # 然后编译安装一份当前版本的 Python 。注意的是,此处不需要真正安装到系统中去,所以我将其安装在源码的 python3_bin 目录下,供下面的脚本需要 # 生成配置文件,--prefix按需修改,若修改,下面的脚本路径也需要你按需自定义 root@ubuntu:/data/local/Python-3.7.17# ./configure --prefix=/data/local/Python-3.7.17/python3_bin # 编译安装 root@ubuntu:/data/local/Python-3.7.17# make && make install # 安装操作结束后,清除一下 Python 源代码目录文件的一些编译过程文件 root@ubuntu:/data/local/Python-3.7.17# make clean

然后继续在 Python3.7 源码目录,将下述脚本保存到 Python3 源码的同目录下,脚本内容如下,部分内容参数请按提示自定义更新:

#!/bin/bash # 此为上述编译后生成的 Python 3 二进制文件所在,并设置一下别名 export PATH=/data/local/Python-3.7.17/python3_bin/bin:$PATH alias python='python3' COMPILE_ROOT="$(dirname $(readlink -f "$0"))" # NDK 路径 export ANDROID_NDK_ROOT=/data/local/android-ndk-r25c export ANDROID_GCC_ROOT=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64 export ANDROID_GCC_PATH=${ANDROID_GCC_ROOT}/bin BUILD_PATH=${COMPILE_ROOT}/build # 生成二进制文件的路径 OUT_PATH=/data/local/tmp/python3 # 若 OpenSSL 不能正常编译加密库,可换成 LibreSSL OPENSSL_PATH=/data/local/openssl-1.1.1w/out OPENSSL_LIB_PATH=/data/local/openssl-1.1.1w/out/lib #OPENSSL_PATH=/data/local/libressl-3.8.1/out #OPENSSL_LIB_PATH=/data/local/libressl-3.8.1/out/lib CROSS_COMPILER=aarch64-linux-android- CROSS_COMPILER_CLANG=aarch64-linux-android33- #prepare mkdir -p ${BUILD_PATH} mkdir -p ${OUT_PATH} export PATH=${ANDROID_NDK_ROOT}:${ANDROID_GCC_PATH}:$PATH export ARCH="aarch64" export CC="${CROSS_COMPILER_CLANG}clang -pie -fPIE" export CPP="${CROSS_COMPILER_CLANG}clang -E -pie -fPIE" export CXX="${CROSS_COMPILER_CLANG}clang++ -pie -fPIE" # 下方的链接文件,新版 NDK 变成了 llvm-xx 的文件格式了,可能旧版的还存在诸如 aarch64-linux-android-xx 的格式文件,若为旧版格式文件,可将下面注释的取消注释,并将 llvm-xx 格式的命令参数反向注释掉,按需修改 #export AS="${CROSS_COMPILER}as" export LD="${CROSS_COMPILER}ld -pie -fPIE" export GDB="${CROSS_COMPILER}gdb" export STRIP="${CROSS_COMPILER}strip" #export RANLIB="${CROSS_COMPILER}ranlib" #export OBJCOPY="${CROSS_COMPILER}objcopy" #export OBJDUMP="${CROSS_COMPILER}objdump" #export AR="${CROSS_COMPILER}ar" #export NM="${CROSS_COMPILER}nm" export RANLIB="llvm-ranlib" export AR="llvm-ar" export NM="llvm-nm" export OBJCOPY="llvm-objcopy" export OBJDUMP="llvm-objdump" export AS="llvm-as" #export READELF="${CROSS_COMPILER}readelf" export READELF="llvm-readelf" export M4=m4 export TARGET_PREFIX=$CROSS_COMPILER export CONFIG_SITE="config.site" export CXXFLAGS="-D__ANDROID_API__=33 " cd ${BUILD_PATH} config_soft(){ # 此处可在 Android 设备上查看一下是否存在 /dev/ptmx 和 /dev/ptc 设备文件,有就把参数设置成 yes ,无则设为 no 。 echo -e "ac_cv_file__dev_ptmx=yes\nac_cv_file__dev_ptc=no" > config.site ../configure --host=aarch64-linux-android \ --host=aarch64-linux \ --build=x86_64-pc-linux-gnu \ --target=aarch64-linux-android \ LDFLAGS="-Wl,--allow-shlib-undefined -D__ANDROID_API__=33 -fPIC -L${OPENSSL_LIB_PATH}" \ CFLAGS="-D__ANDROID_API__=33 " \ CPPFLAGS="-D__ANDROID_API__=33" \ --enable-ipv6 \ --with-openssl=${OPENSSL_PATH} \ --prefix=${OUT_PATH} } make_soft(){ make -j $(nproc) } make_soft_install(){ make install } make_clean(){ make clean } case "$1" in config_soft) config_soft ;; make_soft) make_soft ;; make_soft_install) make_soft_install ;; make_clean) make_clean ;; esac

先使用 config_soft 生成一些文件,命令如下:

root@ubuntu:/data/local/Python-3.7.17# vim make_python.sh root@ubuntu:/data/local/Python-3.7.17# bash make_python.sh config_soft ……

到这一步需要注意,如果其他平台编译时在 build/Modules 文件夹内生成了 Setup 文件,我们需要修改一下里面的部分参数内容,其中 SSL 参数是我们上面脚本里指定的哪个加密库,下方就改成对应的加密库。同时指定一下 zlib 库文件位置:

root@ubuntu:/data/local/Python-3.7.17# vim build/Modules/Setup …… SSL=/data/local/openssl-1.1.1w/out _ssl _ssl.c \ -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \ -L$(SSL)/lib -lssl -lcrypto …… zlib zlibmodule.c -I/data/local/zlib-1.3/out/include -L/data/local/zlib-1.3/out/lib -lz ……

然后再编译安装生成可执行二进制文件:

root@ubuntu:/data/local/Python-3.7.17# bash make_python.sh make_soft …… root@ubuntu:/data/local/Python-3.7.17# bash make_python.sh make_soft_install ……

生成成功后接下来就是将 /data/local/tmp 目录下的文件压缩并使用 adb 推到 Android 设备的 /data/local/tmp 目录下:

# 打包 Python 3 文件 root@ubuntu:/data/local/tmp# tar -zcvf python3.tar.gz python3 # adb 将文件推送至手机 adb push python3.tar.gz /data/local/tmp

然后在 Android 系统下解压,即可使用该 Python ,如图:

image-20230921162655368

image-20230921162655368

接下来为更方便的调用,可写个脚本控制相关环境变量,脚本内容如下:

#!/system/bin/env sh export HOME='/data/local/tmp/python3' PYTHON_HOME='/data/local/tmp/python3' export PATH=${PYTHON_HOME}/bin:${PATH} export LD_LIBRARY_PATH=${PYTHON_HOME}/lib:${LD_LIBRARY_PATH} export PYTHONPATH=${PYTHONPATH}:${PYTHON_HOME} python3 "$@"

效果如下:

kali@shell:/data/local/tmp/python3 $ vi python_run.sh kali@shell:/data/local/tmp/python3 $ chmod +x python_run.sh kali@shell:/data/local/tmp/python3 $ ./python_run.sh --version Python 3.7.17 kali@shell:/data/local/tmp/python3 $ ./python_run.sh Python 3.7.17 (default, Sep 20 2023, 16:55:26) [Clang 14.0.7 (https://android.googlesource.com/toolchain/llvm-project 4c603efb on linux Type "help", "copyright", "credits" or "license" for more information. >>>

至此,基于 NDK 交叉编译的 Python 3 已能够在 Android 上执行。自己在编译过程中发现 pip 模块缺失,可前往 Python 官网下载 get-pip.py 进行安装即可,如下图:

image-20230921163853621

image-20230921163853621


最后的最后,快淦饭了,就让 ChatGPT 给我生成一个标题吧:

image-20230921165230558

image-20230921165230558

个人自己编译的一份成品也将其打包分享给大家,若有兴趣的小伙伴可根据编译的成品 Python 二进制文件去制作成 Magisk 模块使得挂载到设备上使用:

提取链接:
https://pan.baidu.com/s/1Sxs7VxEVPQKSWI_AL0aszg?pwd=6666

提取码:6666

End

本文标题:在 Android 上解锁 Python 魔力:交叉编译 Python 3 的完整指南

本文链接:https://www.isisy.com/1515.html

除非另有说明,本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

声明:转载请注明文章来源。

如果觉得我的文章对你有用,请随意赞赏