1
votes

Long story short, I got infected by the CryptoLocker Virus. My “normal” local files are not the problem because these files I backup. But I was using the Google Drive Sync client and all my Drive files got encrypted. I didn’t back them up because I thought Google Drive is save and my data is stored all over the world (my fault I know).

Now I can see that Google Drive provides versioning. This means my old uploads are still on the server. I can restore the previous version file by file but by several thousand files, good luck. I contacted the Google G Suite support team (I’m using Google G Suite for my business) and asked them if they can restore the latest version in one bulk action. The answer was “no you have to do it file by file”. Therefore I was checking the internet for scripts, tools etc.

I found a Python script “bitbucket.org/snippets/cyclick/EBbEG” which should allow me to restore the preview working version.

  1. Install python "python.org/ftp/python/2.7.12/python-2.7.12.msi".

  2. Run "CMD".

  3. Download the pip modul "bootstrap.pypa.io/get-pip.py".

  4. Copy it to the "Scripts" folder.

  5. Run the script via CMD "python get-pip.py".

  6. Turn on the Drive API and generate a OAuth client ID: developers.google.com/drive/v3/web/quickstart/python

  7. Downloaded the json file, placed it in the “.credentials” folder and renamed it to “client_secret.json”. (like mentioned in line 28)

  8. Install Google library under CMD "pip install --upgrade google-api-python-client".

  9. Afterwards I copied the script and saved it as “cleanup.py”.

# This script removes the file revision created by the Zepto Ransomware and 
# renames the file back to what it was before infection.
# This file CHANGES the drive. USE IT AT YOUR OWN RISK. I'M NOT RESPONSIBLE FOR ANY LOSE.
# 
# Requirements : 
#  * Avoid encoding problem by setting the python encoding before running the script
#   $ export PYTHONIOENCODING=utf8
#  * Turn on the Drive API and generate a OAuth client ID : https://developers.google.com/drive/v3/web/quickstart/python

from __future__ import print_function
import httplib2
import os
import json

from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools

try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

# If modifying these scopes, delete your previously saved credentials at ~/.credentials/drive-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/drive'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Drive API Python Quickstart'

def get_credentials():
    """
    Gets valid user credentials from storage.

    If nothing has been stored, or if the stored credentials are invalid,
    the OAuth2 flow is completed to obtain the new credentials.

    Returns:
        Credentials, the obtained credential.
    """
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
      os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir, 'drive-python-quickstart.json')

    store = oauth2client.file.Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
      flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
      flow.user_agent = APPLICATION_NAME
      if flags:
        credentials = tools.run_flow(flow, store, flags)
      else: 
        # Needed only for compatibility with Python 2.6
        credentials = tools.run(flow, store)
      print('Storing credentials to ' + credential_path)
    return credentials

def deleteFilesWithSuffix(suffix, service):
  results = service.files().list(
      corpus="domain",
      spaces="drive",
      pageSize=1000,
      orderBy="folder,modifiedTime desc,name",
      q="name contains '" + suffix + "'",
      fields="nextPageToken, files(id, name)"   
        ).execute()
  items = results.get('files', [])
  if not items:
    print('No files found.')
  else:
    for item in items:
      if item['name'].endswith(suffix):
        try:
          deleteFile = service.files().delete(fileId=item['id']).execute()
          print("Deleted file : " + item['name'])
        except Exception as e:
          print("Could not delete file : " + item['name'] + ". Details : " + str(e))

def renameFile(fileId, originalFilename, service):
  try:
    print("Renaming file " + fileId + " to " + originalFilename)
    service.files().update(fileId=fileId, body={'name': originalFilename}, fields='name').execute()
  except Exception as e:
    print("Could not rename file " + fileId + " / Details : " + str(e))

def revertFiles(suffix, service):
  results = service.files().list(
      corpus="domain",
      spaces="drive",
      pageSize=1000,
      orderBy="folder,modifiedTime desc,name",
      #q="modifiedTime > '2016-09-04T12:00:00'",
      q= "name contains '" + suffix + "'",
      fields="nextPageToken, files(id, name)"   
      ).execute()
  items = results.get('files', [])
  if not items:
    print('No files found.')
  else:
      for item in items:
        details = service.files().get(fileId=item['id'], fields="lastModifyingUser,name").execute()
        if details['name'].endswith(suffix):
            print("About to handle file " + details['name'] + " having id " + item['id'])
            revs = service.revisions().list(fileId=item['id'], fields="kind,revisions").execute()
            allrev = revs['revisions']
            lastRev = allrev[-1]
            if not lastRev['originalFilename'].endswith(suffix):
              # there was a rename problem during previous run -> fix it 
              originalFilename = lastRev['originalFilename']
              renameFile(item['id'], originalFilename, service)
            elif len(allrev) > 1:
                origRev = allrev[-2]
                if lastRev['originalFilename'].endswith(suffix):
                  try:
                    print("Removing last revision of file " + details['name']) 
                    revDel = service.revisions().delete(fileId=item['id'], revisionId=lastRev['id']).execute()
                    originalFilename = origRev['originalFilename']
                    renameFile(item['id'], originalFilename, service)
                  except Exception as e:
                    print("Could not process file : " + details['name'] + " / Details : " + str(e))

def main():
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('drive', 'v3', http=http)

    deleteFilesWithSuffix('_HELP_instructions.html', service)
    revertFiles('zepto', service)

if __name__ == '__main__':
    main()
  1. I ran the script via CMD “python cleanup.py”.

I receive an error message:

C:\Python27\Scripts>python cleanup.py
Traceback (most recent call last):
  File "cleanup.py", line 133, in <module>
    main()
  File "cleanup.py", line 125, in main
    credentials = get_credentials()
  File "cleanup.py", line 48, in get_credentials
    credentials = store.get()
  File "C:\Python27\lib\site-packages\oauth2client\client.py", line 407, in get
    return self.locked_get()
  File "C:\Python27\lib\site-packages\oauth2client\file.py", line 54, in locked_get
    credentials = client.Credentials.new_from_json(content)
  File "C:\Python27\lib\site-packages\oauth2client\client.py", line 302, in new_from_json
    module_name = data['_module']
KeyError: '_module'

What did I do wrong? Is it possible that there is something wrong with the credentials/jason file?

Now I’m here guys and asking you for help. Maybe we can get this script running so that I can restore the latest working version of my files.

I really appreciate any help you can provide.

1

1 Answers

0
votes

Take a look at this page? https://github.com/hut6/google-drive-restore

Did you check out step 1.?

You must add the Google Admin SDK and Google Drive APIs to a client in the Google Developers Console. Download the JSON credentials file, and add it to the root directory as credentials.json.