# !/bin/python
# -*- coding: utf-8 -*-
u"""SecureTea Social Engineering
Project:
    ╔═╗┌─┐┌─┐┬ ┬┬─┐┌─┐╔╦╗┌─┐┌─┐
    ╚═╗├┤ │  │ │├┬┘├┤  ║ ├┤ ├─┤
    ╚═╝└─┘└─┘└─┘┴└─└─┘ ╩ └─┘┴ ┴
    Author: Digvijay Bhosale <digvijayb1729@gmail.com> August 15 2021
    Version: 1.0
    Module: SecureTea
"""

import os
import subprocess
from securetea.lib.malware_analysis import globals


class FileAnalyser:
    '''
    Contains functions that use the most popular command line steganography tools to extract hidden data

    start_analysis() and individual_runner()
    These functions are responsible for running other functions and as such, program flow starts here

    file_info() view_strings() and extract_steg_data()
    These functions call the functions that actually do the steganographic decoding and display the data back to user

    any function starting with command_
    This function is the heart of the program. It uses the steg tools and returns the result.
    file
    strings
    exiftool
    foremost
    binwalk
    pngcheck
    steghide
    stegosuite

    these are the tools currently being used.
    '''

    def __init__(self, filename):
        self.filename = filename
        self.file = open(filename, 'r')
        globals.initialize_colours()

    def full_stegscan(self, filename=''):
        if filename:
            self.filename = filename
        res = self.command_file()
        if res is not None:
            print(res[0])
            # print(res[1])
        else:
            print(globals.FAIL + "Error Encountered while running command.\n" + globals.END)
        res = self.command_strings()
        if res is not None:
            print(res[0])
            # print(res[1])
        else:
            print(globals.FAIL + "Error Encountered while running command.\n" + globals.END)
        res = self.command_exiftool()
        if res is not None:
            print(res[0])
            # print(res[1])
        else:
            print("No png Data detected")
        res = self.command_foremost()
        if res is not None:
            print(res[0])
            # print(res[1])
        else:
            print(globals.FAIL + "Error Encountered while running command.\n" + globals.END)
        res = self.command_binwalk()
        if res is not None:
            print(res[0])
            # print(res[1])
        else:
            print(globals.FAIL + "Error Encountered while running command.\n" + globals.END)
        res = self.command_pngcheck()
        if res is not None:
            print(res[0])
            # print(res[1])
        else:
            print("No png Data detected\n")
        res = self.command_steghide()
        if res is not None:
            print(res[0])
            print(res[1])
        else:
            print(
                globals.FAIL + "Steghide is incompatible with given files. Use image formats like JPG or JPEG\n" + globals.END)
        res = self.command_stegosuite()
        if res is not None:
            print(res[0])
            # print(res[1])
            if 'Wrong' in res[1]:
                print(globals.FAIL + 'Stegosuite: could not extract any data with that passphrase!' + globals.END)
        else:
            print(globals.FAIL + "Stegosuite is incompatible with given files. Use image formats like PNG, MNG, JPG or JPEG\n" + globals.END)

    def start_analysis(self):
        while True:
            action = ''
            try:
                action = input("\nEnter action to take on file\n"
                               "f/F File Information\n"
                               "s/S View Strings\n"
                               "e/E Extract Embedded Data\n"
                               "i/I Run Steganography Tools Individually\n"
                               "a/A Run all Steganography tools\n"
                               "q/Q Quit\n"
                               "\t: ")
            except KeyboardInterrupt:
                print(globals.WARNING + 'KeyboardInterrupt. Quitting' + globals.END)
                exit()

            if action.lower() == 'f':
                self.file_info()
            elif action.lower() == 's':
                self.view_strings()
            elif action.lower() == 'e':
                self.extract_steg_data()
            elif action.lower() == 'i':
                self.individual_runner()
                break
            elif action.lower() == 'a':
                self.full_stegscan()
                break
            elif action.lower() == 'q':
                break
            else:
                print(globals.WARNING + 'Incorrect choice entered. ' + globals.END)
                continue

    def individual_runner(self):
        while True:
            action = ''
            try:
                action = input("\nEnter tool to use on file\n"
                               "f/F or file\n"
                               "s/S or strings\n"
                               "e/E or exiftool\n"
                               "o/O or foremost\n"
                               "b/B or binwalk\n"
                               "p/P or pngcheck\n"
                               "t/T or steghide\n"
                               "u/U or stegosuite\n"
                               "q/quit/exit for exiting\n")
            except KeyboardInterrupt:
                print(globals.WARNING + 'KeyboardInterrupt. Quitting' + globals.END)
                exit()
            action = action.lower()
            if action == 'file' or action == 'f':
                res = self.command_file()
                if res is not None:
                    print(res[0])
                    # print(res[1])
                else:
                    print(globals.FAIL + "Error Encountered while running command.\n" + globals.END)
            elif action == 'strings' or action == 's':
                res = self.command_strings()
                if res is not None:
                    print(res[0])
                    # print(res[1])
                else:
                    print(globals.FAIL + "Error Encountered while running command.\n" + globals.END)
            elif action == 'exiftool' or action == 'e':
                res = self.command_exiftool()
                if res is not None:
                    print(res[0])
                    # print(res[1])
                else:
                    print("No png Data detected")
            elif action == 'foremost' or action == 'o':
                res = self.command_foremost()
                if res is not None:
                    print(res[0])
                    # print(res[1])
                else:
                    print(globals.FAIL + "Error Encountered while running command.\n" + globals.END)
            elif action == 'binwalk' or action == 'b':
                res = self.command_binwalk()
                if res is not None:
                    print(res[0])
                    # print(res[1])
                else:
                    print(globals.FAIL + "Error Encountered while running command.\n" + globals.END)
            elif action == 'pngcheck' or action == 'p':
                res = self.command_pngcheck()
                if res is not None:
                    print(res[0])
                    # print(res[1])
                else:
                    print("No png Data detected\n")
            elif action == 'steghide' or action == 't':
                res = self.command_steghide()
                if res is not None:
                    print(res[0])
                    print(res[1])
                else:
                    print(
                        globals.FAIL + "Steghide is incompatible with given files. Use image formats like JPG or JPEG\n" + globals.END)
            elif action == 'stegosuite' or action == 'u':
                res = self.command_stegosuite()
                if res is not None:
                    print(res[0])
                    # print(res[1])
                    if 'Wrong' in res[1]:
                        print(globals.FAIL + 'Stegosuite: could not extract any data with that passphrase!' + globals.END)
                else:
                    print(globals.FAIL + "Stegosuite is incompatible with given files. Use image formats like PNG, MNG, JPG or JPEG\n" + globals.END)
            elif action == 'q' or action == 'exit' or action == 'quit':
                break
            else:
                print(globals.WARNING + "Incorrect choice entered" + globals.END)

    def file_info(self):
        print('File Info')
        res = self.command_file()
        print(res[0])
        # print(res[1])
        print('Exif Data')
        res = self.command_exiftool()
        print(res[0])
        # print(res[1])
        print('Png data')
        res = self.command_pngcheck()
        if res is not None:
            print(res[0])
            # print(res[1])
        else:
            print("No png Data detected")

    def view_strings(self):
        res = self.command_strings()
        print(res[0])

    def extract_steg_data(self):
        res = self.command_foremost()
        if res is not None:
            print(res[0])
            # print(res[1])
        else:
            print(globals.FAIL + "Error Encountered while running command.\n" + globals.END)
        res = self.command_binwalk()
        if res is not None:
            print(res[0])
            # print(res[1])
        else:
            print(globals.FAIL + "Error Encountered while running command.\n" + globals.END)
        res = self.command_steghide()
        if res is not None:
            print(res[0])
            print(res[1])
        else:
            print(
                globals.FAIL + "Steghide is incompatible with given files. Use image formats like JPG or JPEG\n" + globals.END)
        res = self.command_stegosuite()
        if res is not None:
            print(res[0])
            if 'Wrong' in res[1]:
                print(globals.FAIL + 'Stegosuite: could not extract any data with that passphrase!' + globals.END)
        else:
            print(
                globals.FAIL + "Stegosuite is incompatible with given files. Use image formats like PNG, MNG, JPG or JPEG\n" + globals.END)

    def command_file(self):
        process = subprocess.Popen(['file', self.filename],
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        stdout = stdout.decode('utf-8')
        stderr = stderr.decode('utf-8')
        return stdout, stderr

    def command_strings(self):
        number = input('Min String Length (default 10) : ') or '10'
        print(number)
        process = subprocess.Popen(['strings', '-n', number, self.filename],
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        stdout = stdout.decode('utf-8')
        stderr = stderr.decode('utf-8')
        return stdout, stderr

    def command_exiftool(self):
        process = subprocess.Popen(['exiftool', self.filename],
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        stdout = stdout.decode('utf-8')
        stderr = stderr.decode('utf-8')
        return stdout, stderr

    def command_foremost(self):
        process = subprocess.Popen(['foremost', '-o', 'files_extracted_from_foremost', '-T', self.filename],
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        stdout = stdout.decode('utf-8') + '\nFiles extracted by Foremost have been stored in Folder ' \
                                          'files_extracted_from_foremost_<Day>_<Month>_<Date>_' \
                                          '<Hours>_<Minutes>_<Seconds>_<Year>\n'
        stderr = stderr.decode('utf-8')
        return stdout, stderr

    def command_binwalk(self):
        process = subprocess.Popen(['binwalk', '-e', self.filename],
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        stdout = stdout.decode('utf-8')
        stderr = stderr.decode('utf-8')
        return stdout, stderr

    def command_pngcheck(self):
        filetype = self.command_file()[0]
        if 'png' in filetype or 'jng' in filetype or 'mng' in filetype:
            process = subprocess.Popen(['pngcheck', self.filename],
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE)
            stdout, stderr = process.communicate()
            stdout = stdout.decode('utf-8')
            stderr = stderr.decode('utf-8')
            return stdout, stderr
        else:
            return None

    def command_steghide(self):
        filetype = self.command_file()[0]
        if 'jpg' in filetype or 'jpeg' in filetype:
            key = input('Enter passphrase to be used for StegHide (Default None) : ') or ''
            if key == '':
                process = subprocess.Popen(['steghide', 'extract', '-sf', self.filename, '-xf', 'extracted_file',
                                            '-f', '-p', ''],
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.PIPE)
                stdout, stderr = process.communicate()

            else:
                process = subprocess.Popen(['steghide', 'extract', '-sf', self.filename, '-xf', 'extracted_file',
                                            '-f', '-p', key],
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.PIPE)
                stdout, stderr = process.communicate()

            stdout = stdout.decode('utf-8')
            stderr = stderr.decode('utf-8')
            return stderr, stdout
        else:
            return None

    def command_stegosuite(self):
        filetype = self.command_file()[0]
        if 'image' in filetype or 'png' in filetype or 'jpg' in filetype or 'jpeg' in filetype:
            key = input('Enter passphrase to be used for StegoSuite (default : password) : ') or 'password'
            print(globals.OKCYAN + 'This might take some time ....' + globals.END)
            process = subprocess.Popen(['stegosuite', '-x', '-k', key, self.filename],
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE)
            try:
                stdout, stderr = process.communicate()
            except KeyboardInterrupt:
                print(globals.WARNING + '\nKeyboardInterrupt' + globals.END)
                return None
            stdout = stdout.decode('utf-8')
            stderr = stderr.decode('utf-8')
            return stdout, stderr
        else:
            return None
