全志A40i平台Android系统adb安全加固:实现可配置的Shell登录密码

发布时间:2026/7/7 16:47:21

全志A40i平台Android系统adb安全加固:实现可配置的Shell登录密码 1. 为什么需要给adb shell加密码最近有个做智能硬件的朋友找我吐槽说他们公司生产的设备被人用adb shell连上去乱改配置导致设备无法正常工作。这让我想起在全志A40i这类嵌入式Android平台上adb shell确实是个安全隐患。想象一下如果你的设备像没锁的门一样谁都能通过adb连进去捣鼓那得多危险adb shell默认不需要密码就能登录这在开发阶段确实方便但产品出厂后就是个巨大的安全漏洞。我在给某家工厂做设备管理系统时就遇到过这种情况——工人用adb连上生产线设备误删了关键配置文件导致整条生产线停工8小时。这种教训告诉我们adb shell必须加把锁。全志A40i这类嵌入式平台还有个特殊之处它们通常用在工业控制、智能终端等场景设备可能7×24小时运行。如果被人恶意连接adb执行rm -rf后果不堪设想。我经手过的一个医疗设备项目就因为adb未加密被黑客入侵差点酿成医疗事故。2. 技术原理深度解析2.1 adb shell的工作机制先给大家拆解下adb shell的底层原理。当你在电脑上输入adb shell时实际发生了这些事PC端的adb客户端通过USB或TCP连接到设备的adbd守护进程adbd收到请求后会fork一个子进程这个子进程最终执行/system/bin/sh启动shell关键点在于第三步——这里没有任何鉴权检查。就像你家大门钥匙插在锁眼里谁都能拧开。我在全志A40i的源码中找到了证据在shell_service.cpp里有这么一段static void shell_service(int fd, void *cookie) { // 直接execv执行sh execv(/system/bin/sh, new_argv); }2.2 我们的改造思路既然问题出在执行sh前没有校验那解决方案就很清晰了在/system/bin/sh前插入我们的校验脚本脚本要求输入密码密码正确才启动真正的shell这就像在门前加了个智能门锁只有输入正确密码才会打开内门。具体实现上我们需要修改三处新增密码校验脚本修改adbd源码使其调用我们的脚本添加系统属性控制开关3. 手把手实现密码校验3.1 编写校验脚本首先在vendor/aw/public/prebuild/bin/tools下创建ckp.sh#!/system/bin/sh # 获取系统配置的密码 sys_pwd$(getprop persist.zonecare.adb.pwd) # 默认密码 if [ -z $sys_pwd ];then sys_pwdadmin fi echo Enter your pwd: while : do # -r防止转义字符被处理 read -r PASSWORD if [[ $PASSWORD $sys_pwd ]];then break else echo please try again: fi done echo success!! # 关键用exec替换当前进程 exec /system/bin/sh这个脚本有几个设计亮点密码从系统属性读取支持动态修改使用exec替代当前进程避免产生多余进程循环验证直到密码正确3.2 编译配置修改要让脚本生效需要修改编译系统在Android.mk中添加LOCAL_PREBUILT_EXECUTABLES ckp.sh在tools.mk中确保脚本被复制到/system/bin在init.rc中添加权限设置chmod 0777 /system/bin/ckp.sh4. 源码级改造实战4.1 修改adbd核心代码找到shell_service.cpp关键修改点static void shell_service(int fd, void *cookie) { // 新增密码检查开关判断 char ckp_enable[PROP_VALUE_MAX]; property_get(persist.zonecare.adb.ckp, ckp_enable, 0); if (strcmp(ckp_enable, 1) 0) { // 如果开启校验执行我们的脚本 execv(/system/bin/ckp.sh, new_argv); } else { // 否则走原流程 execv(/system/bin/sh, new_argv); } }4.2 设备配置参数在a40_p1.mk中添加默认配置# adb密码校验开关 0关闭 1开启 PRODUCT_PROPERTY_OVERRIDES persist.zonecare.adb.ckp0 # 默认密码 PRODUCT_PROPERTY_OVERRIDES persist.zonecare.adb.pwdadmin5. 实际应用技巧5.1 密码动态修改产品出厂后可以通过adb修改密码adb shell setprop persist.zonecare.adb.pwd newpassword我在给某银行做ATM终端时他们就要求每月自动更换密码。这可以通过在init.rc中添加定时任务实现service change_adb_pwd /system/bin/sh /data/change_pwd.sh oneshot disabled on property:sys.boot_completed1 start change_adb_pwd5.2 安全增强建议密码复杂度检查可以在ckp.sh中加入正则校验if [[ ${#PASSWORD} -lt 8 ]];then echo 密码至少8位 continue fi尝试次数限制防止暴力破解attempt0 max_attempt3 while [ $attempt -lt $max_attempt ] do read -r PASSWORD if [[ $PASSWORD $sys_pwd ]];then break fi attempt$((attempt1)) done if [ $attempt -eq $max_attempt ];then echo 尝试次数过多 exit 1 fi日志记录所有登录尝试记入logcatlog -p i -t ADB_AUTH Login attempt from $ADB_CLIENT6. 避坑指南在给某车载设备实施这个方案时我踩过几个坑权限问题脚本必须有执行权限建议在init.rc中设置SELinux冲突需要添加新的策略规则allow adbd shell_exec:file { execute execute_no_trans };缓冲问题adb的输入输出需要特殊处理建议在脚本开头加stty raw -echo有个客户反映密码校验后终端显示异常最后发现是没处理TERM环境变量。解决方案是在exec前添加export TERMxterm7. 方案扩展思考这个方案不仅适用于全志A40i其他Android设备也通用。我在瑞芯微RK3399上测试过只需调整编译路径即可。对于更高安全要求的场景还可以集成LDAP认证增加双因素认证与设备IMEI绑定生成动态密码最近在做一个政府项目时我们就实现了密码短信验证码的双重验证。核心思路是在ckp.sh中调用curl访问验证服务verify_code$(curl -s https://api.example.com/verify?token$PASSWORD) if [[ $verify_code ! SUCCESS ]];then exit 1 fi

相关新闻