Code A Dead Man's Switch in Python 3 To Encrypt & Delete Files Whenever You Don't Check in Null Byte WonderHowTo
Code A Dead Man's Switch in Python 3 To Encrypt & Delete Files Whenever You Don't Check in Null Byte WonderHowTo
By Retia
A dead man's switch is a fairly simple concept. If you don't perform a specific task before a set amount of time,
it'll perform a specific action you set. They can be handy not just for hackers but for everyone who wants to
protect themselves, someone else, or something tangible or intangible from harm. While there are more
nefarious uses for a dead man's switch, white hats can put one to good use.
These switches have appeared in pop culture in many different forms, and examples can be seen in films such as
"Point Break," "Speed," and "Crimson Tide." For a more recent example, in the film "Tenet," Sator (the
antagonist) had implemented a dead man's switch to go off whenever his heart stopped, which would activate
the algorithm that would end the entire world.
Notorious whistleblower Edward Snowden even used one in real life when he leaked all of those sensitive NSA
documents to journalists. He sent encrypted versions to people he could trust who would receive the decryption
key if he were to die under mysterious or violent circumstances.
From a white hat's perspective, or just someone wanting to protect themselves from data theft by black hats or
law enforcement, a dead man's switch is most useful for locking things down. Let's say you're in a protest with
the possibility of getting arrested. You could set a kill switch for your laptop in case you don't check in via
Twitter every so often. That way, it's harder for anyone to access your data.
Another scenario involves just wanting to keep some sensitive files locked down before anyone has a chance to
access them. If you don't perform a specific action that you set for yourself, either once or in intervals, then the
files you selected would be encrypted so that nobody could read them.
In this guide, we'll be using Python 3 to write a simple dead man's switch that does just that — encrypts a file if
we don't check in when specified. Now we could make one that sends a password out for an already encrypted
file if we don't check in when specified, but then you have to deal with Twitter APIs, and that's a little bit more
complicated. We just want to get you started so you can branch out to more advanced dead man's switches
afterward.
Python 3 and a Python 3 integrated development environment (IDE) is all you really need to build one. We'll be
using PyCharm as our IDE. To follow along, here's the full Python code that we've made, but skip below to find
out how it works.
GetTargets()
While the full Python code is visible in the code box above, you can check it out on GitHub or download it to
your computer with the following command.
Our Python code has the time and datetime libraries, which are standard libraries that should already be on
your system. With these, the code can deal with timing matters and the parsing of date/time formats. But there
are a few other libraries that you'll need as well. Specifically, Twint and PyAEScrypt.
Twint is a Twitter scraping tool that helps you grab a user's recent tweets, locate specific tweets for historical
data, export evidence and metadata, collect real-time data, and more. In our project today, we'll use Twint as the
mechanism for our dead man's switch.
PyAEScrypt is a tool that lets you encrypt and decrypt a file quickly. In our case, that's our payload, where we'll
be encrypting a file with a password in the event that we don't check-in. Use pip3 install twint pyAesCrypt to
install both dependencies.
~$ cd /home/kali/DeadManSwitch
~/DeadManSwitch$ pip3 install twint pyAesCrypt
If you're using PyCharm, cd to the folder where you downloaded and extracted the PyCharm program, go into
that bin folder, and use ./pycharm.sh to open up the PyCharm IDE. Then, create a new project, labeled
something like "DeadManSwitch."
~/DeadManSwitch$ cd /home/kali/pycharm-community-2020.2.3/bin
~/pycharm-community-2020.2.3/bin$ ./pycharm.sh
You could also add Twint and pyAesCrypt manually in the PyCharm IDE if you don't want to deal with pip or
when you want to be sure that you have everything you need. If you want to do that, select "File," then
"Settings," and choose your dead man's switch project. Next, select "Python Interpreter," and click the plus (+)
sign to search for and add "twint" and "pyAesCrypt" packages.
Step 3Build the Code
Now we're ready to start writing the code. We want to make sure that we can, over a certain period of time,
either check-in or not check-in. And based on that exchange, the file we choose will be encrypted. There are
three main functions of this project. Let's first focus on the targeting function.
This is the section of the code that gets all of the information to make our project run. The last GetTargets() is a
single function that calls all of the other functions.
For the targeting aspect, we start with def GetTargets():, and then we create a Twint object using c =
twint.Config(). This is where you would start to include all of the configuration items you want to run a search
on, such as a username, the date and time that you want to start the search, etc.
# Gets the information to run the loop, such as the keyword, file to
encrypt, and how long to run
def GetTargets():
c = twint.Config()
For the startTime, we want to add in the current date, or the date we want Twint to exclude everything that
came before it so that we're not getting any false positives from code phrases that appear in the timeline
elsewhere. The input part will appear on the screen when the program runs, and the user of the program will
need to enter the date in the correct format specified.
Since the date format is particular, we have some code to let us know if the user is using the wrong date format
since Twint is picky. If it is wrong, it'll print the message "That's not a date, try again." Then, it'll bounce back to
the start to ask for the date again.
# Gets the information to run the loop, such as the keyword, file to
encrypt, and how long to run
def GetTargets():
c = twint.Config()
startTime = input("Date to start searching (format: %Y-%m-%d)\n>")
try: datetime.datetime.strptime(startTime, '%Y-%m-%d')
except ValueError:
print("That's not a date, try again (format: %Y-%m-%d)")
GetTargets() ##Making sure the format is correct for the data
Next, we recall the startTime we just went over with c.Since, which is the first moving piece of c, the Twint
configuration. Then we need to ask the user for the search term with c.Search, which could be a word or phrase
the user wants to look out for. It will ask, "Keyphrase to disarm switch?"
After that, we use c.Username to ask the user which Twitter account it should be watching. Specifically, it will
ask the user, "Twitter account to watch?"
Next, with delayTime, we say how often the program should check the Twitter user's timeline for that keyword
or phrase; it's in seconds, but you could make it as long or short as you want. What the user will see in the
program is "Time in seconds to wait between checking the account?"
# Gets the information to run the loop, such as the keyword, file to
encrypt, and how long to run
def GetTargets():
c = twint.Config()
startTime = input("Date to start searching (format: %Y-%m-%d)\n>")
try: datetime.datetime.strptime(startTime, '%Y-%m-%d')
except ValueError:
print("That's not a date, try again (format: %Y-%m-%d)")
GetTargets() ##Making sure the format is correct for the data
c.Since = startTime
c.Search = input("Keyphrase to disarm switch?\n>")
c.Username = input("Twitter account to watch?\n>")
delayTime = int(input("Time in seconds to wait between checking the
account?\n>"))
For the filePath line, we ask the user running our program, "File to encrypt if switch fires?" That's where the
file path goes for the file that will be encrypted should the keyword or phrase not be detected over the set target
time.
The encryptPass line, asking "Password to encrypt file?" will encrypt the file with the password the user
chooses. Then, the line that starts with targetTime asks "How many minutes to run before firing?" This is the
target time between when the time elapsed without the safety word/phrase and when the encryption should
happen.
# Gets the information to run the loop, such as the keyword, file to
encrypt, and how long to run
def GetTargets():
c = twint.Config()
startTime = input("Date to start searching (format: %Y-%m-%d)\n>")
try: datetime.datetime.strptime(startTime, '%Y-%m-%d')
except ValueError:
print("That's not a date, try again (format: %Y-%m-%d)")
GetTargets() ##Making sure the format is correct for the data
c.Since = startTime
c.Search = input("Keyphrase to disarm switch?\n>")
c.Username = input("Twitter account to watch?\n>")
delayTime = int(input("Time in seconds to wait between checking the
account?\n>"))
filePath = input("File to encrypt if switch fires?\n>")
encryptPass = input("Password to encrypt file?\n>")
targetTime = (time.time() + (int(input("How many minutes to run before
firing?\n>"))*60))
Now we need to tell Twint how we want to store the file. The c.Hide_output line says that we want to hide the
output so that it only shows up in the list we designate later, and c.Store_object says we want to store the info,
which correlates with tweets = twint.output.tweets_list in the checking function.
In the last line, we call all of the key details over to the checking function called CheckKey, which will
continuously check for our targeting information, including everything in c, the Twint configuration, as well as
delayTime, filePath, encryptPass, and targetTime.
# Gets the information to run the loop, such as the keyword, file to
encrypt, and how long to run
def GetTargets():
c = twint.Config()
startTime = input("Date to start searching (format: %Y-%m-%d)\n>")
try: datetime.datetime.strptime(startTime, '%Y-%m-%d')
except ValueError:
print("That's not a date, try again (format: %Y-%m-%d)")
GetTargets() ##Making sure the format is correct for the data
c.Since = startTime
c.Search = input("Keyphrase to disarm switch?\n>")
c.Username = input("Twitter account to watch?\n>")
delayTime = int(input("Time in seconds to wait between checking the
account?\n>"))
filePath = input("File to encrypt if switch fires?\n>")
encryptPass = input("Password to encrypt file?\n>")
targetTime = (time.time() + (int(input("How many minutes to run before
firing?\n>"))*60))
c.Hide_output = True
c.Store_object = True
CheckKey(c, delayTime, filePath, encryptPass, targetTime)
GetTargets()
The checking function is the part that actually performs the search on Twint. The first def line tasks the
information from the targeting function that we specified, including c, delayTime, filePath, encryptPass, and
targetTime.
Then, if something goes wrong, like the date is wrong, we can print an error message for ValueError so that we
know something happened, and then it will return to GetTargets() in the targeting function to start again.
Next, we create a list called "tweets" with twint.output.tweets_list so that all of the tweets found that match the
target word or phrase can be dumped in it. The whole program will be watching this list, so it's a pretty big part
of the code.
The next line will check to see if there is anything in the tweets list. If there is something in there, we know that
the person who ran this program checked in, and everything is fine.
If it detects no tweets in the list, we compare the current time using time.time(), noting if it's greater than or
equal to (>=) the targetTime. If it is, then it will fire the payload function, pointing to the file path and
encryption password.
The else statement for the delayTime is for how often it should check the user's Twitter timeline. This will be
the delayTime from the targeting function, and it will then start back at the beginning of the checking function
to try again.
If there is something in the list, we have an else statement to print a message saying that the dead man's switch
has been deactivated and is in safe mode. If that's the case, the program will then complete, and the file is in no
need of being encrypted.
Now for the last remaining part of the puzzle: the payload. If the keyword or phrase had not been detected in the
checking function after a set amount of time, it would call the payload here. And this is where pyAesCrypt
comes into action. We print a message saying that it's activated, then encrypt the file using AES with the
specified buffer size.
Now, the next two lines are commented out, but they're there in case you want to decrypt the file
(pyAesCrypt.decryptFile) or delete the file (secure_delete). So if you wanted to decrypt a file instead, you
could use that line instead of the pyAesCrypt.encryptFile one. But if you wanted to encrypt the file and delete
it afterward, you can use the secure_delete module, which you will have to install as we did Twint and
pyAesCrypt.
/home/kali/PycharmProjects/DeadManSwitch/venv/bin/python /home/kali
/PycharmProjects/DeadManSwitch/main.py
Date to start searching (format: %Y-%m-%d)
>
After you input the date to start searching, it'll ask you for the key phrase to disarm the dead man's switch.
>2020-10-28
Keyphrase to disarm switch?
>
After adding the search term, specify the Twitter account to search.
>kali
Twitter account to watch?
>
Now, when you give it a username, it'll ask you the time in seconds to wait between checking the account.
Remember, it's in seconds only.
>NullByte
Time in seconds to wait between checking the account?
>
Then, it will ask which file you want to encrypt should it not detect the search term in the time specified.
>10
File to encrypt if switch fires?
>
>/home/kali/Documents/importantstuff.txt
Password to encrypt file?
>
And then choose how many minutes you want the program to run before firing.
>chooseagoodpassword
How many minutes to run before firing?
>
In our example, if it didn't detect the key search term after 10 seconds, it'll try again until either the term has
been identified or time runs out. In the latter case, the file will be encrypted.
>1
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
No results, trying again after delay
No results, trying again after delay
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
No results, trying again after delay
No results, trying again after delay
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
PAYLOAD ACTIVATED!!!!!
SWITCH ACTIVATED - LOCKDOWN MODE ENTERED
In our example, we only encrypted a file, so there will be a new encrypted version of the file in the same folder
as the regular file. If we wanted to delete the original file while only keeping the encrypted one, that's when we
would un-comment the secure_delete linen in the payload function.
If it were to detect the keyword or phrase in the allotted timeframe, you would see something like this instead:
>1
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
No results, trying again after delay
No results, trying again after delay
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
No results, trying again after delay
No results, trying again after delay
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
CRITICAL:root:twint.run:Twint:Feed:noDataExpecting value: line 1 column 1
(char 0)
Deadswitch De-Activated, Entered Safe Mode
If you get an error code, there could be a chance that Twitter changed something on its end, and Twint hasn't
been updated yet to reflect those changes. In that case, you could submit a request on the project's GitHub
repository. It could also be that you used the wrong Twitter username or that the user has a private account.
Want to start making money as a white hat hacker? Jump-start your hacking career with our 2020 Premium
Ethical Hacking Certification Training Bundle from the new Null Byte Shop and get over 60 hours of training
from cybersecurity professionals.
97% off The Ultimate 2021 White Hat Hacker Certification Bundle