原书的代码主要考虑的是如何实现功能,在字符编码,socket 阻塞和数据交互,异常处理等方面存在一些问题,造成了程序功能不完善,逻辑出差和退出等情况。
本篇笔记记录用 Python3 实现原书的 netcat, 脚本功能和步骤主要是参照原书的实现思路,会对部分代码的逻辑进行更合理的调整,并学习字符编码,异常处理,调试日志记录等知识点。
功能和实现思路见上一篇笔记。
Python3 代码
#!/usr/bin/env python3
# -*- code: utf-8 -*-
import sys
import getopt
import socket
import subprocess
import threading
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(filename)s[line:%(lineno)d] %(levelname)s: %(message)s',
# format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s: %(message)s',
# datefmt='%Y/%m/%d %H:%M:%S',
# filename='myapp.log',
filemode='a')
# define some global variables
listen = False
command = False
upload = False
execute = ""
target = ""
upload_destination = ""
port = 0
def run_command(command):
"""
execute the shell command, or file received from client.
:param command:
:return: output: shell command result.
"""
# trim the newline.(delete the characters of the string end.)
command = command.rstrip()
# run the command and get the output back
try:
# run command with arguments and return its output.
output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
logging.debug(output)
except Exception as e:
logging.error(e)
output = b"Failed to execute command.\r\n"
# send the output back to the client
return output
def client_handler(client_socket):
"""
the thread function of handling the client.
:param client_socket:
:return:
"""
global upload
global execute
global command
# upload file
if len(upload_destination):
# read in all of the bytes and write to our destination
file_buffer = ""
# keep reading data until none is available
while True:
data = client_socket.recv(1024)
file_buffer += data.decode("utf-8")
logging.debug(data)
# "#EOF#" tell the server, file is end.
if "#EOF#" in file_buffer:
file_buffer = file_buffer[:-6]
break
# for interaciton, like heart packet.
client_socket.send(b"#")
# now we take these bytes and try to write them out
try:
with open(upload_destination, "wb") as fw:
fw.write(file_buffer.encode("utf-8"))
client_socket.send(