1 原理说明
这样的改动一般是为了防止客户拿到定制设备后对软件偷家,但同时我们又需要一些特殊定制,比如抓日志logcat这种。因为针对前者的限制,我们完全可以值接禁用adb即可,不需要再做特殊修改。但基于前者的需求我们又希望能有一些定制的命令或者极少常见命令可以正常使用,那么就需要对adb有一定了解的情况下定制修改了。这里的原理是主要针对adbd中关键位置进行过滤和特殊处理操作。
2 修改方案(Android S)
说明:这里的修改方案以logcat为例,但是不局限于logcat。
修改文件为:$AOSP/ackages/modules/adb/daemon/services.cpp中,修改内容为:
// Shell service string can look like:
// shell[,arg1,arg2,...]:[command]
unique_fd ShellService(std::string_view args, const atransport* transport) {
size_t delimiter_index = args.find(':');
if (delimiter_index == std::string::npos) {
LOG(ERROR) << "No ':' found in shell service arguments: " << args;
return unique_fd{};
}
// TODO: android::base::Split(const std::string_view&, ...)
std::string service_args(args.substr(0, delimiter_index));
std::string command(args.substr(delimiter_index + 1));
// Defaults:
// PTY for interactive, raw for non-interactive.
// No protocol.
// $TERM set to "dumb".
SubprocessType type(command.empty() ? SubprocessType::kPty : SubprocessType::kRaw);
SubprocessProtocol protocol = SubprocessProtocol::kNone;
std::string terminal_type = "dumb";
for (const std::string& arg : android::base::Split(service_args, ",")) {
if (arg == kShellServiceArgRaw) {
type = SubprocessType::kRaw;
+ return unique_fd{}; //modify add
} else if (arg == kShellServiceArgPty) {
type = SubprocessType::kPty;
+ return unique_fd{}; //modify add
} else if (arg == kShellServiceArgShellProtocol) {
protocol = SubprocessProtocol::kShell;
} else if (arg.starts_with("TERM=")) {
terminal_type = arg.substr(strlen("TERM="));
} else if (!arg.empty()) {
// This is not an error to allow for future expansion.
LOG(WARNING) << "Ignoring unknown shell service argument: " << arg;
}
}
return StartSubprocess(command, terminal_type.c_str(), type, protocol);
}
//...
unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
ADB_LOG(Service) << "transport " << transport->serial_name() << " opening service " << name;
+ if (name.find("logcat") == std::string::npos) { //如果找不到logcat则返回默认为空的unique_fd,这里也可以按需过滤其他命令
+ return unique_fd{};
+ }
#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);
} 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);
} else if (android::base::ConsumePrefix(&name, "exec:")) {
return StartSubprocess(std::string(name), nullptr, SubprocessType::kRaw,
SubprocessProtocol::kNone);
} else if (name.starts_with("sync:")) {
return create_service_thread("sync", file_sync_service);
} 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{};
}
修改代码简要解读如下:
- 这里首先是修改ShellService函数,这里的修改主要是针对常见的adb shell所有命令,不再执行StartSubprocess来处理,而是直接过滤掉。
- 其次是修改daemon_service_to_fd函数,这里的修改主要是过滤其他命令,如果是logcat命令则正常流程处理,如果不是logcat则全部过滤掉。