adb 服务端 源码修改说明

adb 服务端 源码修改说明

adb 命令 服务端流程

adbd 主函数

int main(int argc, char** argv) {
#if defined(__BIONIC__)
    // Set M_DECAY_TIME so that our allocations aren't immediately purged on free.
    mallopt(M_DECAY_TIME, 1);
#endif

    while (true) {
        static struct option opts[] = {
                {"root_seclabel", required_argument, nullptr, 's'},
                {"device_banner", required_argument, nullptr, 'b'},
                {"version", no_argument, nullptr, 'v'},
                {"logpostfsdata", no_argument, nullptr, 'l'},
        };

        int option_index = 0;
        int c = getopt_long(argc, argv, "", opts, &option_index);
        if (c == -1) {
            break;
        }

        switch (c) {
#if defined(__ANDROID__)
            case 's':
                root_seclabel = optarg;
                break;
#endif
            case 'b':
                adb_device_banner = optarg;
                break;
            case 'v':
                printf("Android Debug Bridge Daemon version %d.%d.%d\n", ADB_VERSION_MAJOR,
                       ADB_VERSION_MINOR, ADB_SERVER_VERSION);
                return 0;
            case 'l':
                LOG(ERROR) << "post-fs-data triggered";
                return 0;
            default:
                // getopt already prints "adbd: invalid option -- %c" for us.
                return 1;
        }
    }

    close_stdin();

    adb_trace_init(argv);

    D("Handling main()");
    return adbd_main(DEFAULT_ADB_PORT);
}

在 main 函数 中主要调用了 adbd_main(DEFAULT_ADB_PORT)

在 adbd_main 方法中我们主要看一下 init_transport_registration 方法

void init_transport_registration(void) {
    int s[2];

    if (adb_socketpair(s)) {
        PLOG(FATAL) << "cannot open transport registration socketpair";
    }
    D("socketpair: (%d,%d)", s[0], s[1]);

    transport_registration_send = s[0];
    transport_registration_recv = s[1];

    transport_registration_fde =
        fdevent_create(transport_registration_recv, transport_registration_func, nullptr);
    fdevent_set(transport_registration_fde, FDE_READ);
}

调用了socketpair,一端有数据后会调用transport_registration_func函数

static void transport_registration_func(int _fd, unsigned ev, void*) {
    tmsg m;
    atransport* t;

    if (!(ev & FDE_READ)) {
        return;
    }

    if (transport_read_action(_fd, &m)) {
        PLOG(FATAL) << "cannot read transport registration socket";
    }

    t = m.transport;

    if (m.action == 0) {
        D("transport: %s deleting", t->serial.c_str());

        {
            std::lock_guard<std::recursive_mutex> lock(transport_lock);
            transport_list.remove(t);
        }

        delete t;

        update_transports();
        return;
    }

    /* don't create transport threads for inaccessible devices */
    if (t->GetConnectionState() != kCsNoPerm) {
        // The connection gets a reference to the atransport. It will release it
        // upon a read/write error.
        t->connection()->SetTransportName(t->serial_name());
        t->connection()->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
            if (!check_header(p.get(), t)) {
                D("%s: remote read: bad header", t->serial.c_str());
                return false;
            }

            VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "from remote", p.get());
            apacket* packet = p.release();

            // TODO: Does this need to run on the main thread?
            fdevent_run_on_main_thread([packet, t]() { handle_packet(packet, t); });
            return true;
        });
        t->connection()->SetErrorCallback([t](Connection*, const std::string& error) {
            LOG(INFO) << t->serial_name() << ": connection terminated: " << error;
            fdevent_run_on_main_thread([t]() {
                handle_offline(t);
                transport_destroy(t);
            });
        });

        t->connection()->Start();
#if ADB_HOST
        send_connect(t);
#endif
    }

    {
        std::lock_guard<std::recursive_mutex> lock(transport_lock);
        auto it = std::find(pending_list.begin(), pending_list.end(), t);
        if (it != pending_list.end()) {
            pending_list.remove(t);
            transport_list.push_front(t);
        }
    }

    update_transports();
}

它先调用了transport_read_action来读取transport_registration_recv的数据,也就是之前transport_registration_send发来的adb驱动节点的数据。然后把它保存在t这个变量中。

通过 connection() 连接获得对传输的引用,并通过SetReadCallback 回调 对读写数据进行处理,

在主线程上排队(fdevent_run_on_main_thread)执行 handle_packet(packet, t) 对从驱动器读取到的命令处理 看 到在 OPEN 指令中(传输数据) 调用create_local_service_socket方法

asocket* create_local_service_socket(std::string_view name, atransport* transport) {
#if !ADB_HOST
    if (asocket* s = daemon_service_to_socket(name); s) {
        return s;
    }
#endif
    unique_fd fd = service_to_fd(name, transport);
    if (fd < 0) {
        return nullptr;
    }

    int fd_value = fd.get();
    asocket* s = create_local_socket(std::move(fd));
    LOG(VERBOSE) << "LS(" << s->id << "): bound to '" << name << "' via " << fd_value;

#if !ADB_HOST
    /*if ((name.starts_with("root:") && getuid() != 0 && __android_log_is_debuggable()) ||
        (name.starts_with("unroot:") && getuid() == 0) || name.starts_with("usb:") ||
        name.starts_with("tcpip:")) {
        D("LS(%d): enabling exit_on_close", s->id);
        s->exit_on_close = 1;
    }*/
    //add by dakun
    if ((name.starts_with("root") && getuid() != 0 && __android_log_is_debuggable()) ||
        (name.starts_with("unroot:") && getuid() == 0) || name.starts_with("usb:") ||
        name.starts_with("tcpip:")) {
        D("LS(%d): enabling exit_on_close", s->id);
        s->exit_on_close = 1;
    }
    //add end
#endif

    return s;
}

可以看到service_to_fd(name, transport) 对命令进行处理后返回

unique_fd service_to_fd(std::string_view name, atransport* transport) {
    unique_fd ret;
    // LOG(INFO) << " *** [DaKun]service_to_fd *** " << name;
    if (is_socket_spec(name)) {
        std::string error;
        if (!socket_spec_connect(&ret, name, nullptr, nullptr, &error)) {
            LOG(ERROR) << "failed to connect to socket '" << name << "': " << error;
        }
    } else {
#if !ADB_HOST
       
        ret = daemon_service_to_fd(name, transport);
#endif
    }
    // LOG(INFO) << " *** [DaKun]service_to_fd ret*** " << ret.get();
    if (ret >= 0) {
        close_on_exec(ret.get());
    }
    return ret;
}

可以看到真正的命令执行逻辑是在daemon_service_to_fd()中

unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
    ADB_LOG(Service) << "transport " << transport->serial_name() << " opening service " << name;
	// LOG(INFO) << " *** [DaKun]daemon_service_to_fd *** " << name;
#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
    if (name.starts_with("abb:") || name.starts_with("abb_exec:")) {
        return execute_abb_command(name);
    }
#endif

#if defined(__ANDROID__)
    if (name.starts_with("framebuffer:")) {
        return create_service_thread("fb", framebuffer_service);
    } else if (android::base::ConsumePrefix(&name, "remount:")) {
        std::string cmd = "/system/bin/remount ";
        cmd += name;
        return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
    } else if (android::base::ConsumePrefix(&name, "reboot:")) {
        return reboot_device(std::string(name));
    } 
    
    /*else if (name.starts_with("root:")) {
        return create_service_thread("root", restart_root_service);
    }*/
    //add by dakun 
    else if (name.starts_with("root-")) {
		std::string::size_type first_pos = name.find_first_of("-");
		std::string::size_type last_pos = name.find_first_of(":");
		std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
		if (check_password(std::string(password).c_str()) != 0) {
                	LOG(ERROR) << "[DaKun]check password failed!"<< password;
                	return unique_fd{};
            	}
        return create_service_thread("root", restart_root_service);
    }
    //add end 
    else if (name.starts_with("unroot:")) {
        return create_service_thread("unroot", restart_unroot_service);
    } else if (android::base::ConsumePrefix(&name, "backup:")) {
        std::string cmd = "/system/bin/bu backup ";
        cmd += name;
        return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
    } else if (name.starts_with("restore:")) {
        return StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
                               SubprocessProtocol::kNone);
    } else if (name.starts_with("disable-verity:")) {
        return StartSubprocess("/system/bin/disable-verity", nullptr, SubprocessType::kRaw,
                               SubprocessProtocol::kNone);
    } else if (name.starts_with("enable-verity:")) {
        return StartSubprocess("/system/bin/enable-verity", nullptr, SubprocessType::kRaw,
                               SubprocessProtocol::kNone);
    } else if (android::base::ConsumePrefix(&name, "tcpip:")) {
        std::string str(name);

        int port;
        if (sscanf(str.c_str(), "%d", &port) != 1) {
            return unique_fd{};
        }
        return create_service_thread("tcp",
                                     std::bind(restart_tcp_service, std::placeholders::_1, port));
    } else if (name.starts_with("usb:")) {
        return create_service_thread("usb", restart_usb_service);
    }
#endif

    if (android::base::ConsumePrefix(&name, "dev:")) {
        return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)};
    } else if (android::base::ConsumePrefix(&name, "jdwp:")) {
        pid_t pid;
        if (!ParseUint(&pid, name)) {
            return unique_fd{};
        }
        return create_jdwp_connection_fd(pid);
    }
    /*else if (android::base::ConsumePrefix(&name, "shell")) {
        return ShellService(name, transport);
    }  */

    //add by dakun
    else if (android::base::ConsumePrefix(&name, "shell-")) {
		std::string::size_type last_pos = name.find_first_of(",");
		std::string_view password = name.substr(0, last_pos);
		if (check_password(std::string(password).c_str()) != 0) {
                	LOG(ERROR) << "[DaKun]check password failed!"<< password;
                	return unique_fd{};
            	}
		name=name.substr(last_pos);
        return ShellService(name, transport);
    }
    //add end
    
     else if (android::base::ConsumePrefix(&name, "exec:")) {
        return StartSubprocess(std::string(name), nullptr, SubprocessType::kRaw,
                               SubprocessProtocol::kNone);
    }
	//add by dakun
	else if (name.starts_with("push-")) {
		std::string::size_type first_pos = name.find_first_of("-");
		std::string::size_type last_pos = name.find_first_of(":");
		std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
		if (check_password(std::string(password).c_str()) != 0) {
                	LOG(ERROR) << " [DaKun] check password failed! "<< password;
                	return unique_fd{};
            	}
        return create_service_thread("sync", file_sync_service);
    }else if (name.starts_with("pull-")) {
		std::string::size_type first_pos = name.find_first_of("-");
		std::string::size_type last_pos = name.find_first_of(":");
		std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
		if (check_password(std::string(password).c_str()) != 0) {
                	LOG(ERROR) << "[DaKun]check password failed!"<< password;
                	return unique_fd{};
            	}
        return create_service_thread("sync", file_sync_service);
    }
	//add end
	/*else if (name.starts_with("sync:")) {
        return create_service_thread("sync", file_sync_service);
    }*/
    //add by dakun
    else if (name.starts_with("sync-")) {
        return create_service_thread("sync", file_sync_service);
    }
    //add end
    else if (android::base::ConsumePrefix(&name, "reverse:")) {
        return reverse_service(name, transport);
    } else if (name == "reconnect") {
        return create_service_thread(
                "reconnect", std::bind(reconnect_service, std::placeholders::_1, transport));
    } else if (name == "spin") {
        return create_service_thread("spin", spin_service);
    }

    return unique_fd{};
}

在这个方法中对客户端传入的命令 进行匹配执行

因此我们对修改后带密码的命令也在这里拦截匹配处理

源码修改

新建密码校验方法check_password

具体代码 参考 shell_verify.cpp 和md5.cpp

对root命令的修改

 /*else if (name.starts_with("root:")) {
        return create_service_thread("root", restart_root_service);
    }*/
    //add by dakun 
    else if (name.starts_with("root-")) {
		std::string::size_type first_pos = name.find_first_of("-");
		std::string::size_type last_pos = name.find_first_of(":");
		std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
		if (check_password(std::string(password).c_str()) != 0) {
                	LOG(ERROR) << "[DaKun]check password failed!"<< password;
                	return unique_fd{};
            	}
        return create_service_thread("root", restart_root_service);
    }

由于 在adb root执行后 adb会重启 在 create_local_service_socket 方法中 也有对root 的判断

所以也需要在create_local_service_socket 中做修改

 /*if ((name.starts_with("root:") && getuid() != 0 && __android_log_is_debuggable()) ||
        (name.starts_with("unroot:") && getuid() == 0) || name.starts_with("usb:") ||
        name.starts_with("tcpip:")) {
        D("LS(%d): enabling exit_on_close", s->id);
        s->exit_on_close = 1;
    }*/
    //add by dakun
    if ((name.starts_with("root") && getuid() != 0 && __android_log_is_debuggable()) ||
        (name.starts_with("unroot:") && getuid() == 0) || name.starts_with("usb:") ||
        name.starts_with("tcpip:")) {
        D("LS(%d): enabling exit_on_close", s->id);
        s->exit_on_close = 1;
    }
    //add end

对shell命令的修改

   /*else if (android::base::ConsumePrefix(&name, "shell")) {
        return ShellService(name, transport);
    }  */

    //add by dakun
    else if (android::base::ConsumePrefix(&name, "shell-")) {
		std::string::size_type last_pos = name.find_first_of(",");
		std::string_view password = name.substr(0, last_pos);
		if (check_password(std::string(password).c_str()) != 0) {
                	LOG(ERROR) << "[DaKun]check password failed!"<< password;
                	return unique_fd{};
            	}
		name=name.substr(last_pos);
        return ShellService(name, transport);
    }
    //add end

对push 和 pull 命令的修改

push 和 pull 和其他一些文件操作类的命令 走的都是sync 命令,所以我们不去修改 而是新增push 和 pull 命令拦截判断 使它同样执行 sync 的功能

//add by dakun
	else if (name.starts_with("push-")) {
		std::string::size_type first_pos = name.find_first_of("-");
		std::string::size_type last_pos = name.find_first_of(":");
		std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
		if (check_password(std::string(password).c_str()) != 0) {
                	LOG(ERROR) << " [DaKun] check password failed! "<< password;
                	return unique_fd{};
            	}
        return create_service_thread("sync", file_sync_service);
    }else if (name.starts_with("pull-")) {
		std::string::size_type first_pos = name.find_first_of("-");
		std::string::size_type last_pos = name.find_first_of(":");
		std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
		if (check_password(std::string(password).c_str()) != 0) {
                	LOG(ERROR) << "[DaKun]check password failed!"<< password;
                	return unique_fd{};
            	}
        return create_service_thread("sync", file_sync_service);
    }
	//add end
	/*else if (name.starts_with("sync:")) {
        return create_service_thread("sync", file_sync_service);
    }*/
    //add by dakun
    else if (name.starts_with("sync-")) {
        return create_service_thread("sync", file_sync_service);
    }
    //add end
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值