前言
在对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