ADB加密实例


通常我们的MIFI USB端口仅枚举rndis和mass端口,为了便于开发人员、工厂维护人员调试和运营商认证,会预留出可通过SCSI指令切口支持ADB端口,该机制可能会被作为切入点破解侵入系统,对于系统安全存在极大风险。因此我们需要对adb访问进行加密控制。
adb的指令在 ADB介绍也进行了列举,有应用管理、文件管理、日志管理、设备管理等,而MIFI产品常用的主要是文件管理和日志管理。因此我们按照Penetration Test要求,对于常用adb操作进行加密处理。

1. adb shell加密访问

最常使用的就是通过adb shell去访问adb设备终端,可以在终端中进行文件访问、应用管理、日志管理等操作,因此对于该指令需进行加密操作。

X12中adb源码位置在sdx12-ap/system/core/adb/,在使用adb shell命令登陆系统时,adb服务(adbd)为我们fork一个子shell作为终端,源码如下:

system\core\adb\services.cpp
#define SHELL_COMMAND "/bin/sh"static int create_subproc_thread(const char *name, const subproc_mode mode)
{switch (mode) {
    case SUBPROC_PTY:
        ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid);
        break;
    case SUBPROC_RAW:
        ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid);
        break;
    default:
        fprintf(stderr, "invalid subproc_mode %d\n", mode);
        return -1;
    }
    D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid);
    stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo)));
    if(sti == 0) fatal("cannot allocate stinfo");
    sti->func = subproc_waiter_service;
    sti->cookie = (void*) (uintptr_t) pid;
    sti->fd = ret_fd;
    if (adb_thread_create(&t, service_bootstrap_func, sti)) {
        free(sti);
        adb_close(ret_fd);
        fprintf(stderr, "cannot create service thread\n");
        return -1;
    }}

因此我们可以将shell替换成可登陆的shell应用,如/bin/login,该应用便可以实现用户名和密码登录,用户名和密码均来自于sdx12-ap/poky/meta-qti-bsp/recipes-core/base-passwd/base-passwd-3.5.29/add-hash.patch,该patch中包含了用户名、密码、密码加密方式等,最终会生成按照冒号分隔的9段密码规则的字段存储在文件/etc/shadow中,当前linux默认的用户名是root、密码是oelinux123、密码加密方式是MD5。

我们修改#define SHELL_COMMAND "/bin/sh"为#define SHELL_COMMAND “/bin/login”,即可实现adb登录访问,编译验证如下:

C:\platform-tools>adb shell
sdxnightjar login: root
Password:
Last login: Wed Aug  9 11:28:44 UTC 2023 on pts/0
No directory, logging in with HOME=/
~ #

adb shell加密访问是生效的。但每次都需要输入账号密码是比较麻烦的,由于账户名是默认不变的,因此我们将账户名在adb中固定,每次只需要输入密码即可。

system\core\adb\services.cpp
**#define SHELL_COMMAND "/bin/login"**static int create_subproc_thread(const char *name, const subproc_mode mode)
{switch (mode) {
    case SUBPROC_PTY:
        **ret_fd = create_subproc_pty(SHELL_COMMAND, "-p", "root", &pid);**
        break;
    case SUBPROC_RAW:
        **ret_fd = create_subproc_raw(SHELL_COMMAND, "-p", "root", &pid);**
break;
    default:
        fprintf(stderr, "invalid subproc_mode %d\n", mode);
        return -1;
    }
    D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid);
    stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo)));
    if(sti == 0) fatal("cannot allocate stinfo");
    sti->func = subproc_waiter_service;
    sti->cookie = (void*) (uintptr_t) pid;
    sti->fd = ret_fd;
    if (adb_thread_create(&t, service_bootstrap_func, sti)) {
        free(sti);
        adb_close(ret_fd);
        fprintf(stderr, "cannot create service thread\n");
        return -1;
    }}

编译验证:

C:\platform-tools>adb shell
Password:
Last login: Wed Aug  9 11:28:58 UTC 2023 on pts/0
No directory, logging in with HOME=/
~ #

在这里插入图片描述

2 adb文件传输命令加密访问

上述章节仅限制了adb shell功能,adb其他功能是没有受到限制的,如adb push\pull等文件传输命令。为了对常用指令进行加密控制,我们设计了如下机制:

  1. 当/etc/lock_flag 内容为 lock 时,禁用 adb shell 功能。当此文件内容为空或文件不存在时,启用adb shell。
  2. 当/etc/adb_flag文件存在时,启用adb shell。 oem_stop_service_list()函数中通过字符串判断定义了当 adb shell 禁用时具体哪些功能会被禁用。
  3. adb指令下发 ->service_to_fd() ->oem_shell_access()判断是否为adb激活,检测到maigc字符串则赋 g_access_adb = ACCESS_ADB ->oem_security_access_adb()判断lock_flag 和 adb_flag,若配置了lock则oem_stop_service_list()判断当前功能是否在禁用列表中,若配置在禁用列表中则退出。具体代码如下:
 int service_to_fd(const char *name)
{
    int ret = -1;

    D("service_to_fd:%s\n", name);

    //for debug, we send a magic string to access shell
    if(!HOST && !strncmp(name, "shell:", 6))
    {
        //backdoor for this
        **oem_shell_access(name);**
    }

    **int running_flag = oem_security_access_adb();
    if (running_flag == 0)
    {
        int stop_list = oem_stop_service_list(name);
        if (stop_list == 1)
        {
            return -1;
        }**
}}

oem_shell_access()判断是否为adb激活:

int oem_shell_access(const char *name)
{
    initkey();

    //it means "access_0x45000000000000000000000000000023"
    //for debug, we use command "adb shell access_7aa72119ca08fc7809663a4f4f8b10f64c2aaa4e" to access shell
    const char *f_magic = "f04542f6f73a355bf541f44443f5f04cf148f6fc4443424b41fdf7434148f242f6464df140f44743464af445434141f6";
    const char *magic = decrypt(f_magic);

    const char *p = strstr(name, magic);
    if (p != NULL)
    {
        g_access_adb = ACCESS_ADB;
        return 0;
    }

    return -1;
}

oem_security_access_adb()判断lock_flag 和 adb_flag,若配置了lock则oem_stop_service_list()判断当前功能是否在禁用列表中

int oem_security_access_adb(void)
{initkey();
    //we can acess adb when sending a magic string
    if (g_access_adb == ACCESS_ADB)
    {
        return 1;
    }
    //protect the strings for security, it can't get information from decompiling 
    //it is "/etc/lock_flag"
    const char *f_encname = "011c5c18071545524260111203521f18084b5a424154014d0e5c530f3e605b5656";
    const char *file_name = decrypt(f_encname);
    // adb push and adb pull service is still running.
    // we can push a file to overwrite adb_flag, so we can access the shell, this is a backdoor.
    // we need to add a file by git to add this function. 
    // I think it isn't a goog way to read the factory.db at here.
    // read etc/lock_flag
    r = oem_read_txt_file(file_name, buf, sizeof(buf));
    if (r > 0)
    {
        //if we find some info like "lock", we will disable adb shell
        const char *f_key = decrypt("11696f171a");
        const char *findstr = strstr(buf, f_key);   //f_key="lock"
        if (findstr != NULL)
        {
            D("stop adb running for security\n");
            return 0;
        }
    }
    else
    {
        //read failed or empty file, we will start adb shell
        D("adb running for security\n");
        return 1;
    }
    //we start adb by default
    D("adb running by default\n");
    return 1;
}

禁用列表中仅添加了一些常用的指令,若有其他需求,可以增删。

int oem_stop_service_list(const char *name) 
{     
	//it means "adb shell" "adb shell xxxx" "exec" "backup" "restore" was disabled     
	//thoes service will be closed     
	if(!strncmp(name, "tcp:", 4))     
	{
	         D("service tcp can't access\n");
	         return 1;     
	}     
	if(!HOST && !strncmp(name, "shell:", 6))if(!HOST && !strncmp(name, "exec:", 5))if(!strncmp(name, "backup:", 7))if(!strncmp(name, "restore:", 8))if(!strncmp("dev:", name, 4))if(!strncmp(name, "sync:", 5))if(!strncmp(name, "remount:", 8))if(!strncmp(name, "unroot:", 7))if(!strncmp(name, "root:", 5))if(!strncmp(name, "tcpip:", 6))if(!strncmp(name, "usb:", 4))if(!strncmp(name, "reverse:", 8))if(!strncmp(name, "disable-verity:", 15))if(!strncmp(name, "enable-verity:", 15))if(!strncmp(name, "push:", 5))if(!strncmp(name, "pull:", 5))return 0; 
}

全部功能代码patch如下:ADB加密实例patch

编译验证:

  1. Lock前,可以随意使用adb访问shell终端和传输文件等:
    在这里插入图片描述
    创建标志位,lock adb
    在这里插入图片描述
  2. lock后,adb shell、push、pull等在禁用列表中的指令均无法访问
    在这里插入图片描述
  3. 使用magic指令解锁,然后可以访问禁用列表中的指令如adb shell、push\pull等
    在这里插入图片描述

adb加密功能完成。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四儿家的小祖宗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值