Implementing ADB Shell Password Authentication in Android 11

Modifying Transport State Management

To enforce security, a global authentication flag must be introduced to track the session status. This flag ensures that any change in the transport state (connection or disconnection) invalidates the current session, requiring the user to re-authenticate.

In system/core/adb/adb.cpp, add a global variable and reset it within the transport handlers.

// system/core/adb/adb.cpp

#if !ADB_HOST
// Global flag to track if the current client is authorized
bool g_is_session_valid = false;
#endif

void handle_online(atransport* t) {
    D("adb: online");
    t->online = 1;
    t->SetConnectionEstablished(true);

#if !ADB_HOST
    // Reset authentication state when the device comes online
    g_is_session_valid = false;
#endif
}

void handle_offline(atransport* t) {
    D("adb: offline");
    const atransport* hangup_transport = t;
    // ... existing logic ...
    t->online = 0;

#if !ADB_HOST
    // Invalidate session when transport goes offline
    g_is_session_valid = false;
#endif
    // ... existing logic ...
    close_all_sockets(t);
}

Implementing Credential Verification

The service layer must intercept incoming shell requests to verify credentials. If the session is not marked as valid, the system checks for a password in the command string. This password is compared against a system property, defaulting to "admin" if the property is not set.

In system/core/adb/services.cpp, implement the verification logic within the service dispatcher.

// system/core/adb/services.cpp

#include <android-base/properties.h>
#include <android-base/stringprintf.h>

#if !ADB_HOST
extern bool g_is_session_valid;

static void RespondWithStatus(unique_fd fd, bool success) {
    const char* status = success ? "Login Success\n" : "Login Failed\n";
    WriteFdExactly(fd, status);
}
#endif

unique_fd service_to_fd(std::string_view name, atransport* transport) {
    unique_fd fd_result;

#if !ADB_HOST
    if (!g_is_session_valid) {
        // Look for the 'raw' prefix in the service name to identify auth attempts
        const char* cmd_ptr = name.data();
        const char* raw_keyword = strstr(cmd_ptr, "raw");

        if (raw_keyword != nullptr) {
            // Retrieve the stored password from system properties
            std::string stored_secret = android::base::GetProperty("persist.otg.passwd", "admin");
            std::string_view input_secret(raw_keyword + 4); // Pointer arithmetic to skip 'raw'

            if (input_secret == stored_secret) {
                g_is_session_valid = true;
                fd_result = create_service_thread("auth_success", [](unique_fd fd) {
                    RespondWithStatus(std::move(fd), true);
                });
            } else {
                // Ensure auth remains false
                g_is_session_valid = false;
                fd_result = create_service_thread("auth_fail", [](unique_fd fd) {
                    RespondWithStatus(std::move(fd), false);
                });
            }

            if (fd_result >= 0) {
                close_on_exec(fd_result);
            }
            return fd_result;
        }
        // If not authenticated and not an auth attempt, block access
        return fd_result;
    }
#endif
    // ... existing socket and service logic follows ...
}

Tags: Android ADB Security C++ system-modification

Posted on Fri, 05 Jun 2026 18:51:15 +0000 by Trium918