python2的socks5代理 文件上传

前言

在对linux机器进行打点时候,机器不出网,但是我们能链接到linux机器,在webshell无法传输文件,或者无法传输大文件时,可以使用python来作为服务端,因为大部分linux机器中内置python 不需要下载

socks5+文件上传

服务端

# coding=utf-8
import logging
import select
import socket
import struct
from SocketServer import ThreadingMixIn, TCPServer, StreamRequestHandler

logging.basicConfig(level=logging.DEBUG)
SOCKS_VERSION = 5


class ThreadingTCPServer(ThreadingMixIn, TCPServer):
    pass


class SocksProxy(StreamRequestHandler):
    username = 'username'
    password = 'password'

    def handle(self):
        logging.info('Accepting connection from %s:%s' % self.client_address)

        # greeting header
        # read and unpack 2 bytes from a client
        header = self.connection.recv(2)
        version, nmethods = struct.unpack("!BB", header)

        # socks 5
        if version == 2:
            self.recvfile()
            self.server.close_request(self.request)
            return
        assert version == SOCKS_VERSION
        assert nmethods > 0

        # get available methods
        methods = self.get_available_methods(nmethods)

        # accept only USERNAME/PASSWORD auth
        if 2 not in set(methods):
            # close connection
            self.server.close_request(self.request)
            return

        # send welcome message
        self.connection.sendall(struct.pack("!BB", SOCKS_VERSION, 2))

        if not self.verify_credentials():
            return

        # request
        version, cmd, _, address_type = struct.unpack("!BBBB", self.connection.recv(4))
        assert version == SOCKS_VERSION

        if address_type == 1:  # IPv4
            address = socket.inet_ntoa(self.connection.recv(4))
        elif address_type == 3:  # Domain name
            domain_length = int(str(self.connection.recv(1)[0]).encode('hex'),16)
            address = self.connection.recv(domain_length)
            address = socket.gethostbyname(address)
        else:
            self.server.close_request(self.request)
        port = struct.unpack('!H', self.connection.recv(2))[0]
        # reply
        try:
            if cmd == 1:  # CONNECT
                remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                remote.connect((address, port))
                bind_address = remote.getsockname()
                logging.info('Connected to %s %s' % (address, port))
            else:
                self.server.close_request(self.request)

            addr = struct.unpack("!I", socket.inet_aton(bind_address[0]))[0]
            port = bind_address[1]
            reply = struct.pack("!BBBBIH", SOCKS_VERSION, 0, 0, 1,
                                addr, port)

        except Exception as err:
            logging.error(err)
            # return connection refused error
            reply = self.generate_failed_reply(address_type, 5)

        self.connection.sendall(reply)
        #print(int(reply[1].encode('hex'),16))
        # establish data exchange
        if int(reply[1].encode('hex'),16) == 0 and cmd == 1:
            self.exchange_loop(self.connection, remote)

        self.server.close_request(self.request)

    def get_available_methods(self, n):
        methods = []
        for i in range(n):
            methods.append(ord(self.connection.recv(1)))
        return methods

    def verify_credentials(self):
        version = ord(self.connection.recv(1))
        assert version == 1

        username_len = ord(self.connection.recv(1))
        username = self.connection.recv(username_len).decode('utf-8')

        password_len = ord(self.connection.recv(1))
        password = self.connection.recv(password_len).decode('utf-8')

        if username == self.username and password == self.password:
            # success, status = 0
            response = struct.pack("!BB", version, 0)
            self.connection.sendall(response)
            return True

        # failure, status != 0
        response = struct.pack("!BB", version, 0xFF)
        self.connection.sendall(response)
        self.server.close_request(self.request)
        return False

    def generate_failed_reply(self, address_type, error_number):
        return struct.pack("!BBBBIH", SOCKS_VERSION, error_number, 0, address_type, 0, 0)

    def exchange_loop(self, client, remote):
        while True:
            # wait until client or remote is available for read
            r, w, e = select.select([client, remote], [], [])

            if client in r:
                data = client.recv(4096)
                if remote.send(data) <= 0:
                    break

            if remote in r:
                data = remote.recv(4096)
                if client.send(data) <= 0:
                    break
    def recvfile(self):
        self.connection.sendall(struct.pack("!B", 2))
        #file_name_length = int(str(self.connection.recv(1)[0]).encode('hex'), 16)
        file_name_length = struct.unpack("!B", self.connection.recv(1))[0]

        file_name = self.connection.recv(file_name_length)
        print file_name
        data = self.connection.recv(1024)
        total_data = data
        # 如果没有数据了,读出来的data长度为0,len(data)==0
        while len(data) > 0:
            data = self.connection.recv(1024)
            total_data += data
        with open(file_name, "wb") as f:
            f.write(total_data)
        return

if __name__ == '__main__':
    server=ThreadingTCPServer(('0.0.0.0', 8080), SocksProxy)
    server.serve_forever()

客户端

# coding=utf-8
import socket
import struct


def main():
        client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        client.connect(("127.0.0.1", 8080))
        print("connect success.....")
        filepath = "green.rar"
        img = open(filepath,"rb")

        client.sendall(struct.pack("!BB", 2,0))
        if struct.unpack("!B", client.recv(1))[0]==2:
            print("server is ok")
        else:
            return
        path="/tmp/123.rar"
        client.sendall(struct.pack("!B", len(path)))
        client.sendall(path)
        client.sendall(img.read())
        img.close()
        client.close()

if __name__ == '__main__':
    main()

使用方法

socks5

直接设置socks5代理 以proxychains为例

socks5 127.0.0.1 8080 username password

文件上传

修改当前文件目录,目标文件名即可

python xxx.py

注意

因为linux下的python大多为python2,所以只做了python2的适配

参考文章

https://github.com/rushter/socks5/blob/master/server.py

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值