拯救被勒索軟體加密的 Google Drive 檔案 Part 1

FishFu
5 min readJul 2, 2020

--

最近協助管理的伺服器不幸慘遭勒索軟體(Ransomware)感染,勒索軟體一但在電腦上執行,就會對電腦中所有檔案進行 RSA 加密,並修改檔案名稱為所有檔名加上後綴(例如我遇到的是 原檔名.[4*****A3].[ruthlessencry@qq.com].makop),此時若電腦連接 Google Drive 進行同步,也會不幸導致 Google Drive 內的檔案一同被加密!

好在 Google Drive 有內建的版本管理功能,因此我們能夠利用管理版本的功能來復原原本的檔案,值得注意的是!每個檔案舊版本都會在 30 天後,或是保留 100 種版本後刪除,因此必須在受感染後的 30 天內復原才行。

雖然我們可以透過版本管理功能來復原檔案,但其缺點就是必須要一個一個點的中毒檔案來進行復原,需要對該檔案按下右鍵選擇 [管理版本],對新版本(中毒的版本)按下刪除才行,但若你的雲端硬碟中檔案過多,要復原所有中毒檔案就會變成一件十分困難的事情。

經過一番研究發現,其實我們可以透過程式語言搭配 Google Drive API 來協助我們進行自動化的版本刪除!在此我選用 Python 的 Google Drive API 進行實作,並直接使用 Google Colab 作為運行的環境。

Google Drive API

目前最新的 API 版本為 v3,在 API 的官網中有一些相關的簡介可以參考,想了解各個詳細方法(Method)操作、Request/Response 欄位可點進 API Reference 進行查看。

在不同的 Resource (如:Files,Revisions等)下,Overview 頁面可以告訴你此 Resource 有哪些 metadata 或 屬性(Property)可以查看。

值得一提的是,有些方法在 v3 中雖然沒有程式法範例,但若切換到 v2 的相同方法,可能會有能夠參考的程式碼範例可作為參考!通常使用方式都大同小異,有些參數可能有更新而已,因此還是很有參考價值的。

連接至 Google Drive

在 Google Colab 以 Python 執行以下程式碼片段後會跳出驗證頁面,複製認證 Token 進行授權後,即可完成連線的動作,變數 drive_service 即可利用 API 進行各種操作。

from google.colab import authauth.authenticate_user()from googleapiclient.discovery import builddrive_service = build('drive', 'v3')

Files.list 方法

要對檔案進行操作,首先必須要先能夠列出檔案,Files.list方法提供了這樣子的操作,雖然 v3 的頁面中沒有 list 的參考範例,但是前一個版本中卻有 v2 版本 Python範例可以參考。

以下程式碼片段可列出 list 後的 檔案名稱 與 對應之檔案 ID

files = drive_service.files().list().execute().get('files', [])for f in files:
print(f['name'],f["id"]

也許你會發現怎麼只會列出了 100 個檔案,查看 list 頁面參數可以發現 pageSize 預設為 100,可接受的調整範圍為 1~1000,代表我們進行一次 list 最多能取得 1000 個檔案資訊,因此我們需要不斷一直進行 list 操作才能接著歷遍所有檔案,這樣的需求則可透過 pageToken 參數指定 nextPageToken 來做到。

若你直接試著 print(f),可能會發現返回的檔案屬性不如 Overview 頁面多,甚至可能沒有想要的屬性,查看文件可知預設只會回傳 id, name, mimeType三個欄位,因此在 list 時必須指定參數 fields 指定想要返回的檔案屬性,關於指定回傳檔案屬性文件中有相關的介紹

因此我們可以透過以下程式碼片段歷遍雲端硬碟中所有檔案。

from google.colab import auth
auth.authenticate_user()
from googleapiclient.discovery import build
drive_service = build('drive', 'v3')
page_token = None
while True:
files = drive_service.files().list(pageSize=1000, pageToken=page_token, fields='nextPageToken, files(id, name)').execute()
for f in files.get('files', []):
print(f['name'],"/",f["id"])
page_token = files["nextPageToken"]
if page_token is None:
break

要如何刪除中毒版本,將在日後進行介紹。

--

--