From d1f55a49223c1ce0f89cdc02789fb2177086c839 Mon Sep 17 00:00:00 2001 From: tonyqui Date: Sat, 19 Jan 2019 22:58:27 -0500 Subject: [PATCH] Introducing an example to restore files encrypred by a ransomware --- .../restore-after-ransom-infection/README.md | 22 +++++++ .../restore-after-ransom-infection.py | 63 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 example/restore-after-ransom-infection/README.md create mode 100755 example/restore-after-ransom-infection/restore-after-ransom-infection.py diff --git a/example/restore-after-ransom-infection/README.md b/example/restore-after-ransom-infection/README.md new file mode 100644 index 00000000..686a25b3 --- /dev/null +++ b/example/restore-after-ransom-infection/README.md @@ -0,0 +1,22 @@ +# Restore after ransom infection +## A Dropbox API sample app to show Python SDK and get rid of ransom in your dropbox + +# How to run +Make sure you've installed the Dropbox Python SDK by following the installation instructions ( https://www.dropbox.com/developers/documentation/python#install ). + +Then, find this line in restore-after-ransom-infection.py and modify it to include your own access token. +```TOKEN = ''``` + +From the example/backup-and-restore directory, run the script. +```python3 restore-after-ransom-infection.py``` + +# Description +## Functionality +1. Gather files encrypted by a ransomwhere. +Once encrypted a new encrypted copy of your files is saved into your dropbox; whereas the original copy is flagged as to be deleted. Your only task here is to identify the new extension (*.rap in my case) and to change the code accordingly. + +2. For each file matching the regular expression the script gathers the latest revision of the original file and restores it if still flagged as deleted. + +# API usage +## New v2 endpoints +This app uses the Dropbox API v2 endpoints files_list_folder, files_list_folder_continue, files_list_revisions, files_restore and files_delete. \ No newline at end of file diff --git a/example/restore-after-ransom-infection/restore-after-ransom-infection.py b/example/restore-after-ransom-infection/restore-after-ransom-infection.py new file mode 100755 index 00000000..c476bbae --- /dev/null +++ b/example/restore-after-ransom-infection/restore-after-ransom-infection.py @@ -0,0 +1,63 @@ +''' +This example shows how to interact with Dropbox API to restore files encrypted by a ransom. +Even if a ransom deletes original files from the file-system, dropbox still keeps old copies. +We restore the last available revision of a file. +Optionally encrypted files can be deleted with no harm (they're unrecoverable anyway). +''' + +import dropbox +import sys +import re + +files = [] +has_more = True + +def gather_elements(folderList): + for entry in folderList.entries: + # rap here is the extension of ransom' encrypted file + if re.search('.rap$', entry.name): + files.append(entry.path_lower) + +# Here goes the token generated by your dropbox app +TOKEN = '' +dbx = dropbox.Dropbox(TOKEN) +dbx.users_get_current_account() +folderList = dbx.files_list_folder('', recursive=True) + +while has_more: + gather_elements(folderList) + if folderList.has_more: + folderList = dbx.files_list_folder_continue(folderList.cursor) + else: + has_more = False + +# Examine all the files encrypted by the ransom +for f in files: + try: + # Check that it is still marked as deleted + fileName = f.replace('.rap', '') + # Take the version of the file before being encrypted + last_revision = dbx.files_list_revisions(fileName, + mode=dropbox.files.ListRevisionsMode('path', None), limit=1) + # If not there yet, let's restore it + if last_revision.is_deleted is True: + print('Restoring {} with revision {} ...'.format(fileName, + last_revision.entries[0].rev)) + dbx.files_restore(fileName, last_revision.entries[0].rev) + else: + # If it was already restored somehow, keep it untouched + print('File {} was already in place, no action performed'.format(fileName)) + continue + except Exception as ex: + print(ex) + continue +sys.exit(0) + +# To delete files, comment previous call to sys.exit(0) +for f in files: + try: + print("Finally deleting {}".format(f)) + dbx.files_delete(f) + except Exception as ex: + print(ex) +sys.exit(0)