Google Driveの隠しアプリデータを見るにはどうしたらいいですか?
質問
Androidアプリで、メモを 隠しアプリのデータ . 私は私のノートをエクスポートしたいので、質問は簡単です。
特定のアプリについて、Google Drive の隠されたアプリ データにアクセスするにはどうすればよいですか?
どのように解決するのですか?
確かに、Google はこの隠された app-data フォルダに直接アクセスすることを許可していません。
しかし、Google のサーバーに対する認証に使用される、アプリのクライアント ID、クライアント シークレット、デジタル署名を入手できれば、基本的にアプリをエミュレートして、Drive API を使用して Google ドライブ内の隠しデータにアクセスすることができます。
Android での動作
通常、アンドロイドアプリケーションがGoogle APIにアクセスしたい場合(例えば
ドライブ
やゲーム、Google サインインなど、すべてがサポートされているわけではありませんが)、アンドロイドアプリケーションが Google API にアクセスしようとする場合、通常は
Google Play サービス クライアント ライブラリ
と通信し、アプリに代わって Google からアクセストークンを取得します。このアクセストークンは API へのリクエストごとに送信され、Google は誰がこの API を使用しているか、そしてあなたのアカウントで何をすることが許可されているかを把握します (
OAuth 2.0
). このアクセストークンを初めて取得するために、Google Play サービスは HTTPS POST リクエストを
android.clients.google.com/auth
に、これらのフィールド (およびその他の詳細) を含む HTTPS POST リクエストを送信します。
-
Token
- Google アカウントを識別し、基本的にフルアクセスを可能にするマスター トークンです。 -
app
- のようなアプリケーションのパッケージ名です。com.whatsapp
-
client_sig
- アプリケーションの デジタル署名 (SHA1として送信) -
device
- デバイスの Android ID -
service
- その スコープ (パーミッション)を持つことを望んでいるアプリです。
したがって、特定のアプリの名前で Drive API を使い始める前に、その署名と私たちのアカウントのマスター トークンを知る必要があります。幸いなことに、署名は
.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
次に必要なのは、マスタートークンです。この特別なトークンは通常、新しい Google アカウントが追加されたとき (たとえば、携帯電話を最初にセットアップしたとき)、同じ URL に同様のリクエストを行うことで受信し、デバイスに保存されます。違いは、現在、許可を求めているアプリが Play サービス アプリ自体であることです (
com.google.android.gms
) であり、Google にも追加の
Email
と
Passwd
パラメータを使用してログインします。リクエストが成功すると、マスター トークンが返され、それをユーザーのアプリ リクエストに追加できます。
読み取ることができるのは このブログ記事 をご覧ください。
すべてをまとめる
これで、これら 2 つの HTTP リクエストを直接使用して認証するコード、つまり Google アカウントで任意のアプリのファイルを参照できるコードを記述できるようになりました。好きなプログラミング言語を選択し クライアント ライブラリ . 私は、より簡単に 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;
}
そして最後に、その結果 -
Files:
gdrive_file_map (1d9QxgC3p4PTXRm_fkAY0OOuTGAckykmDfFls5bAyE1rp)
Databases/msgstore.db.crypt9 (1kTFG5TmgIGTPJuVynWfhkXxLPgz32QnPJCe5jxL8dTn0)
16467702039-invisible (1yHFaxfmuB5xRQHLyRfKlUCVZDkgT1zkcbNWoOuyv1WAR)
Done.
注意 これは非公式で雑な解決策なので、いくつかの問題があるかもしれません。例えば、アクセストークンは1時間だけ生きていて、その後は自動的にリフレッシュされません。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン