简单介绍了 netcat 的功能和运用后,开始学习理解该书中实现的 netcat 代码。
功能
- 从标准输入中读取数据,并通过网络发送数据。
- 上传文件。
- 执行命令。
- 命令行 shell.
实现
- 解析命令行选项和参数,根据选项设置相应功能标识及参数变量,如果选项和参数不正确打印帮助信息。
- 依据功能标识变量,设计调用功能函数的逻辑流程。主体包括两部分,向外连接和本地监听。
- 向外连接部分,自身作为客户端,向服务端发送和接收数据。
- 本地监听部分,自身作为服务端,绑定端口监听,对连接进来的客户端,新创建客户端处理线程,处理客户端请求。
- 客户端处理线程,根据上传文件、执行命令、命令行 shell 等功能,调用相应功能函数,完成数据发送和接收。
- 命令行 shell 功能,创建一个 shell 的子进程,传入客户端发送过来的 shell 命令给子进程,并把执行结果发送给客户端。
- 执行命令功能,会创建一个子进程,根据 execute 选项的参数执行相应命令,命令可以为程序或脚本。
原书代码附笔记最后,也可以在下面的地址下载。
https://nostarch.com/blackhatpython
测试
对原书 netcat 的测试,这里选取 “命令行 shell ” 和 “执行命令” 两个功能进行测试。
“命令行 shell ” 功能:
“执行命令” 功能:
要注意的是,对于 sys.stdin.read()
, 需要发送 ctrl + d
(Linux) 或 ctrl + z
(Windows) 以避免从标准输入中读取数据,程序才能往下继续执行。
原书 netcat 的代码要优化的地方非常多,而且有些代码会让 Python 进程死掉,用了 N 次 taskkill /f /im python.exe
来结束进程,重新测试。搞得自己都没信心再往下跟,举个测试上传文件功能的例子,如图:
服务端运行
python bhpnet.py -l -p2222 -u1.txt
等待客户端连接,并接受客户端发送的数据,存为文件。客户端用
nc 127.0.0.1 2222
连接服务端,并发送数据。或者用 echo 和管道直接发送数据。
echo -ne "aaaaaaaasssssssss\r\naaaaa\nss\n" | nc 127.0.0.1 2222
代码为:
# check for upload
if len(upload_destination):
# read in all the bytes of the file and write to our destination
file_buffer = ""
# keep reading data until none is available
while True:
data = client_socket.recv(1024)
if not data:
break
else:
file_buffer += data
# now we take these bytes and write them out
try:
file_descriptor = open(upload_destination, "wb")
file_descriptor.write(file_buffer)
file_descriptor.close()
# acknowledge that we wrote the file out
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)
异常发生在
data = client_socket.recv()
语句,调试的时候,当客户端主动强制断开连接后(Windows 终端下 ctrl+c),socket.recv()
函数产生异常,错误为 [Errno 10054]. 而且这里的 data 不会为空,socket 不管是阻塞还是非阻塞,socket.recv()
的返回值都不会为空字符,所以用 if not data:
作为跳出循环的判断不合适。
D:\myProjects\Black-Hat-Python\venv-p2\