Jak Mogę zobaczyć ukryte dane aplikacji na Dysku Google?

Mam aplikację na Androida, która przechowuje moje notatki w ukrytych danych aplikacji . Chcę wyeksportować swoje notatki, więc pytanie jest proste:

Jak uzyskać dostęp do ukrytych danych aplikacji na Dysku Google dla konkretnej aplikacji?

Author: Simón, 2014-04-03

2 answers

Rzeczywiście, Google nie pozwala uzyskać dostępu do tego ukrytego folderu danych aplikacji bezpośrednio.

Ale jeśli możesz zdobyć identyfikator klienta aplikacji / tajny klient / podpis cyfrowy, który jest używany do uwierzytelniania na serwerach Google - to tak, możesz zasadniczo emulować aplikację i uzyskać dostęp do ukrytych danych na Dysku Google za pomocą interfejsu API dysku.

Jak to działa w Androidzie

Zazwyczaj, gdy aplikacja na Androida chce uzyskać dostęp do Google API (takich jak [[21]} Drive , Games lub Google Sign-In-nie wszystkie są obsługiwane) komunikuje się z Google services client library , która z kolei uzyskuje token dostępu od Google w imieniu aplikacji. Ten token dostępu jest następnie wysyłany wraz z każdym żądaniem do API, dzięki czemu Google wie, kto go używa i co może zrobić z Twoim kontem (OAuth 2.0 ). Aby uzyskać ten token dostępu po raz pierwszy, usługa Google Play wysyła żądanie https POST do android.clients.google.com/auth z tymi polami (wraz z innymi szczegółami):

  • Google nie ma dostępu do konta Google i nie ma dostępu do konta Google.]}
  • app - Nazwa pakietu aplikacji, np. com.whatsapp
  • client_sig - podpis cyfrowy aplikacji (wysłany jako SHA1)
  • device - identyfikator urządzenia Android ID
  • Jeśli aplikacja nie chce mieć dostępu do aplikacji, może to być konieczne.]}

Więc zanim będziemy mogli zacznij używać Drive API w nazwie konkretnej aplikacji, musimy znać jej podpis i główny token naszego konta. Na szczęście podpis można łatwo wyodrębnić z pliku .apk:

shell> unzip whatsapp.apk META-INF/*
       Archive:  whatsapp.apk
          inflating: META-INF/MANIFEST.MF    
          inflating: META-INF/WHATSAPP.SF    
          inflating: META-INF/WHATSAPP.DSA
shell> cd META-INF
shell> keytool -printcert -file WHATSAPP.DSA   # can be CERT.RSA or similar
       .....
       Certificate fingerprints:
       SHA1: 38:A0:F7:D5:05:FE:18:FE:C6:4F:BF:34:3E:CA:AA:F3:10:DB:D7:99
       Signature algorithm name: SHA1withDSA
       Version: 3

Następną rzeczą, jakiej potrzebujemy, jest główny token. Ten specjalny token jest zwykle odbierany i przechowywany na urządzeniu po dodaniu nowego konta google (na przykład podczas pierwszej konfiguracji telefonu), poprzez złożenie podobnego żądania do tego samego adresu URL. Różnica polega na tym, że teraz aplikacja, która pyta dla uprawnień jest sama aplikacja Play services (com.google.android.gms), a Google otrzymuje również dodatkowe parametry Email i Passwd do logowania. Jeśli żądanie się powiedzie, odzyskamy nasz główny token, który może zostać dodany do żądania aplikacji użytkownika.

Możesz przeczytać ten post na blogu , aby uzyskać bardziej szczegółowe informacje na temat procesu uwierzytelniania.

Składanie wszystkiego razem

Teraz możemy napisać kod do uwierzytelniania za pomocą tych dwóch żądań HTTP bezpośrednio-kod, który może przeglądać pliki dowolnej aplikacji za pomocą dowolnego konta Google. Po prostu wybierz swój ulubiony język programowania i client library. Znalazłem to łatwiejsze z PHP :

require __DIR__ . '/vendor/autoload.php'; // Google Drive API

// HTTPS Authentication
$masterToken = getMasterTokenForAccount("[email protected]", "your_password");
$appSignature = '38a0f7d505fe18fec64fbf343ecaaaf310dbd799';
$appID = 'com.whatsapp';
$accessToken = getGoogleDriveAccessToken($masterToken, $appID, $appSignature);

if ($accessToken === false) return;

// Initializing the Google Drive Client
$client = new Google_Client();
$client->setAccessToken($accessToken);
$client->addScope(Google_Service_Drive::DRIVE_APPDATA);
$client->addScope(Google_Service_Drive::DRIVE_FILE);
$client->setClientId("");    // client id and client secret can be left blank
$client->setClientSecret(""); // because we're faking an android client
$service = new Google_Service_Drive($client);

// Print the names and IDs for up to 10 files.
$optParams = array(
    'spaces' => 'appDataFolder',
    'fields' => 'nextPageToken, files(id, name)',
    'pageSize' => 10
);
$results = $service->files->listFiles($optParams);

if (count($results->getFiles()) == 0) 
{
    print "No files found.\n";
} 
else 
{
    print "Files:\n";
    foreach ($results->getFiles() as $file) 
    {
        print $file->getName() . " (" . $file->getId() . ")\n";
    }
}

/*
$fileId = '1kTFG5TmgIGTPJuVynWfhkXxLPgz32QnPJCe5jxL8dTn0';
$content = $service->files->get($fileId, array('alt' => 'media' ));
echo var_dump($content);
*/

function getGoogleDriveAccessToken($masterToken, $appIdentifier, $appSignature)
{
    if ($masterToken === false) return false;

    $url = 'https://android.clients.google.com/auth';
    $deviceID = '0000000000000000';
    $requestedService = 'oauth2:https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.file';
    $data = array('Token' => $masterToken, 'app' => $appIdentifier, 'client_sig' => $appSignature, 'device' => $deviceID, 'google_play_services_version' => '8703000', 'service' => $requestedService, 'has_permission' => '1');

    $options = array(
        'http' => array(
            'header' => "Content-type: application/x-www-form-urlencoded\r\nConnection: close",
            'method' => 'POST',
            'content' => http_build_query($data),
            'ignore_errors' => TRUE,
            'protocol_version'=>'1.1',
             //'proxy' => 'tcp://127.0.0.1:8080', // optional proxy for debugging
             //'request_fulluri' => true
        )
    );
    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);
    if (strpos($http_response_header[0], '200 OK') === false) 
    { 
        /* Handle error */
        print 'An error occured while requesting an access token: ' . $result . "\r\n";
        return false;
    }

    $startsAt = strpos($result, "Auth=") + strlen("Auth=");
    $endsAt = strpos($result, "\n", $startsAt);
    $accessToken = substr($result, $startsAt, $endsAt - $startsAt);

    return "{\"access_token\":\"" . $accessToken . "\", \"refresh_token\":\"TOKEN\", \"token_type\":\"Bearer\", \"expires_in\":360000, \"id_token\":\"TOKEN\", \"created\":" . time() . "}";
}

function getMasterTokenForAccount($email, $password) 
{
    $url = 'https://android.clients.google.com/auth';
    $deviceID = '0000000000000000';
    $data = array('Email' => $email, 'Passwd' => $password, 'app' => 'com.google.android.gms', 'client_sig' => '38918a453d07199354f8b19af05ec6562ced5788', 'parentAndroidId' => $deviceID);

    $options = array(
        'http' => array(
            'header' => "Content-type: application/x-www-form-urlencoded\r\nConnection: close",
            'method' => 'POST',
            'content' => http_build_query($data),
            'ignore_errors' => TRUE,
            'protocol_version'=>'1.1',
             //'proxy' => 'tcp://127.0.0.1:8080', // optional proxy for debugging
             //'request_fulluri' => true
        )
    );
    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);
    if (strpos($http_response_header[0], '200 OK') === false) 
    { 
        /* Handle error */
        print 'An error occured while trying to log in: ' . $result . "\r\n";
        return false;
    }

    $startsAt = strpos($result, "Token=") + strlen("Token=");
    $endsAt = strpos($result, "\n", $startsAt);
    $token = substr($result, $startsAt, $endsAt - $startsAt);

    return $token;
}

I na koniec Wyniki -

Files:
gdrive_file_map (1d9QxgC3p4PTXRm_fkAY0OOuTGAckykmDfFls5bAyE1rp)
Databases/msgstore.db.crypt9    (1kTFG5TmgIGTPJuVynWfhkXxLPgz32QnPJCe5jxL8dTn0)
16467702039-invisible (1yHFaxfmuB5xRQHLyRfKlUCVZDkgT1zkcbNWoOuyv1WAR)
Done.

Uwaga: jest to nieoficjalne, hakerskie rozwiązanie, więc może mieć kilka problemów. Na przykład token dostępu jest aktywny tylko przez godzinę, po czym nie zostanie odświeżony automatycznie.

 39
Author: Tomer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-04 11:30:00

Użytkownik nie może bezpośrednio uzyskać dostępu do danych w ukrytych folderach aplikacji, tylko aplikacja może uzyskać do nich dostęp. Jest to przeznaczone do konfiguracji lub innych ukrytych danych, których Użytkownik nie powinien bezpośrednio manipulować. (Użytkownik może usunąć dane, aby zwolnić miejsce, z którego korzysta.)

Jedyny sposób, w jaki użytkownik może uzyskać do niego dostęp, to Korzystanie z niektórych funkcji ujawnionych przez konkretną aplikację.

 8
Author: Cheryl Simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-03 17:32:21