简单介绍了 netcat 的功能和运用后,开始学习理解该书中实现的 netcat 代码。

功能

  • 从标准输入中读取数据,并通过网络发送数据。
  • 上传文件。
  • 执行命令。
  • 命令行 shell.

实现

  1. 解析命令行选项和参数,根据选项设置相应功能标识及参数变量,如果选项和参数不正确打印帮助信息。
  2. 依据功能标识变量,设计调用功能函数的逻辑流程。主体包括两部分,向外连接和本地监听。
  3. 向外连接部分,自身作为客户端,向服务端发送和接收数据。
  4. 本地监听部分,自身作为服务端,绑定端口监听,对连接进来的客户端,新创建客户端处理线程,处理客户端请求。
  5. 客户端处理线程,根据上传文件、执行命令、命令行 shell 等功能,调用相应功能函数,完成数据发送和接收。
  6. 命令行 shell 功能,创建一个 shell 的子进程,传入客户端发送过来的 shell 命令给子进程,并把执行结果发送给客户端。
  7. 执行命令功能,会创建一个子进程,根据 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 uploadif len(upload_destination):# read in all the bytes of the file and write to our destinationfile_buffer = ""# keep reading data until none is availablewhile True:data = client_socket.recv(1024)if not data:breakelse:file_buffer += data# now we take these bytes and write them outtry:file_descriptor = open(upload_destination, "wb")file_descriptor.write(file_buffer)file_descriptor.close()# acknowledge that we wrote the file outclient_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\Scripts\python.exe D:/myProjects/Black-Hat-Python/codes-p2/bhpnet.py -l -p2222 -u1.txt
Exception in thread Thread-1:
Traceback (most recent call last):File "C:\Python27\Lib\threading.py", line 801, in __bootstrap_innerself.run()File "C:\Python27\Lib\threading.py", line 754, in runself.__target(*self.__args, **self.__kwargs)File "D:/myProjects/Black-Hat-Python/codes-p2/bhpnet.py", line 124, in client_handlerdata = client_socket.recv(1024)
error: [Errno 10054] 

socket.error: [Errno 10054] 的原因,是由于远程主机强迫关闭了一个现有的连接,比如没有调用 socket.close() 或 socket 超时。在写爬虫的时候也经常会遇到,比如,服务器发现你的爬虫了,会强制断开你的连接,你的爬虫程序就可能出现 10054 错误。

解决这种情况的常用方法是:

  • 读入新数据;
  • 判断有没有完整的新信息(如数据结束标志,新的数据请求等);
  • 处理新消息。

也是其他 TCP 的 socket 编程都普遍采用的方法,即在调用 socket.send()socket.recv(), 要设置自己的结束字符来判断数据是否收发完毕。

Python2 代码

#!/opt/local/bin/python2.7import sys
import socket
import getopt
import threading
import subprocess# define some global variables
listen             = False
command            = False
upload             = False
execute            = ""
target             = ""
upload_destination = ""
port               = 0# this runs a command and returns the output
def run_command(command):# trim the newlinecommand = command.rstrip()# run the command and get the output backtry:output = subprocess.check_output(command,stderr=subprocess.STDOUT, shell=True)except:output = "Failed to execute command.\r\n"# send the output back to the clientreturn output# this handles incoming client connections
def client_handler(client_socket):global uploadglobal executeglobal command# check for uploadif len(upload_destination):# read in all of the bytes and write to our destinationfile_buffer = ""# keep reading data until none is availablewhile True:data = client_socket.recv(1024)if not data:breakelse:file_buffer += data# now we take these bytes and try to write them outtry:file_descriptor = open(upload_destination,"wb")file_descriptor.write(file_buffer)file_descriptor.close()# acknowledge that we wrote the file outclient_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)# check for command executionif len(execute):# run the commandoutput = run_command(execute)client_socket.send(output)# now we go into another loop if a command shell was requestedif command:while True:# show a simple promptclient_socket.send("<BHP:#> ")# now we receive until we see a linefeed (enter key)cmd_buffer = ""while "\n" not in cmd_buffer:cmd_buffer += client_socket.recv(1024)# we have a valid command so execute it and send back the resultsresponse = run_command(cmd_buffer)# send back the responseclient_socket.send(response)# this is for incoming connections
def server_loop():global targetglobal port# if no target is defined we listen on all interfacesif 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()# spin off a thread to handle our new clientclient_thread = threading.Thread(target=client_handler,args=(client_socket,))client_thread.start()# if we don't listen we are a client....make it so.
def client_sender(buffer):client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)try:# connect to our target hostclient.connect((target,port))# if we detect input from stdin send it # if not we are going to wait for the user to punch some inif len(buffer):client.send(buffer)while True:# now wait for data backrecv_len = 1response = ""while recv_len:data     = client.recv(4096)recv_len = len(data)response+= dataif recv_len < 4096:breakprint response, # wait for more inputbuffer = raw_input("")buffer += "\n"                        # send it offclient.send(buffer)except:# just catch generic errors - you can do your homework to beef this upprint "[*] Exception! Exiting."# teardown the connection                  client.close()  def usage():print "Netcat Replacement"printprint "Usage: bhpnet.py -t target_host -p port"print "-l --listen                - listen on [host]:[port] for incoming connections"print "-e --execute=file_to_run   - execute the given file upon receiving a connection"print "-c --command               - initialize a command shell"print "-u --upload=destination    - upon receiving connection upload a file and write to [destination]"printprintprint "Examples: "print "bhpnet.py -t 192.168.0.1 -p 5555 -l -c"print "bhpnet.py -t 192.168.0.1 -p 5555 -l -u=c:\\target.exe"print "bhpnet.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\""print "echo 'ABCDEFGHI' | ./bhpnet.py -t 192.168.11.12 -p 135"sys.exit(0)def main():global listenglobal portglobal executeglobal commandglobal upload_destinationglobal targetif not len(sys.argv[1:]):usage()# read the commandline optionstry:opts, args = getopt.getopt(sys.argv[1:],"hle:t:p:cu:",["help","listen","execute","target","port","command","upload"])except getopt.GetoptError as err:print str(err)usage()for o,a in opts:if o in ("-h","--help"):usage()elif o in ("-l","--listen"):listen = Trueelif o in ("-e", "--execute"):execute = aelif o in ("-c", "--commandshell"):command = Trueelif o in ("-u", "--upload"):upload_destination = aelif o in ("-t", "--target"):target = aelif o in ("-p", "--port"):port = int(a)else:assert False,"Unhandled Option"# are we going to listen or just send data from stdinif not listen and len(target) and port > 0:# read in the buffer from the commandline# this will block, so send CTRL-D if not sending input# to stdinbuffer = sys.stdin.read()# send data offclient_sender(buffer)   # we are going to listen and potentially # upload things, execute commands and drop a shell back# depending on our command line options aboveif listen:server_loop()main()       

《Python 黑帽子》学习笔记 - 原书 netcat 代码分析 - Day 7相关推荐

  1. python白帽子学习笔记(整合)

    python白帽子学习笔记(整合) 学习笔记目录 python白帽子学习笔记(整合) 前言 一.基础篇 1.正则表达式 2.列表 3.元组带上了枷锁的列表 4.奇葩的内置方法 5.格式化字符 6.序列 ...

  2. 学习笔记-第一章 恶意代码分析实战

    第一章 从可执行文件提取有用信息的多种方法,包括以下技术:1.使用反病毒软件来确认程序样本的恶意性:2.使用哈希来识别恶意代码:3.从文件的字符串列表,函数和文件头信息中发掘有用信息.字符串包括 AS ...

  3. scapy python3_【Python3黑帽子学习笔记 on Mac】第四章 Scapy:网络的掌控者

    Scapy:网络掌控者? 哇咔咔,我喜欢!可是我的问题来了,貌似Scapy只支持Python2,那哥哥这Python3咋办呢? [最新更新:目前scapy目前已经支持Python3了,就不用折腾这个了 ...

  4. 学习笔记-第九章 恶意代码分析实战

    第九章 OllyDbg 1.加载恶意代码直接加载可执行文件,甚至dll程序.如果恶意代码已经在你的系统上运行,你可以通过附加进程的方式调试它.另外,ollydbg是一个灵活的调试系统,可以使用命令行选 ...

  5. 关于《Python黑帽子:黑客与渗透测试编程之道》的学习笔记

    本篇文章是学习<Python黑帽子:黑客与渗透测试编程之道>的笔记,会持续地将书上的代码自己敲一遍,从而让自己对Python的安全编程有更多的了解,同时希望各位可以给给建议,不足之处太多了 ...

  6. 《Python 黑帽子》学习笔记 - Python3 实现 netcat - Day 8

    原书的代码主要考虑的是如何实现功能,在字符编码,socket 阻塞和数据交互,异常处理等方面存在一些问题,造成了程序功能不完善,逻辑出差和退出等情况. 本篇笔记记录用 Python3 实现原书的 ne ...

  7. 《Python 黑帽子》学习笔记 - 命令行选项和参数处理 - Day 4

    在学习书中 netcat 代码的时候,发现其命令行选项和参数的处理存在一些小问题,由于调用 getopt 模块的 getopt() 函数时参数设置不当,会引起代码执行时获取不到参数值或引发异常.该问题 ...

  8. 《Python 黑帽子》学习笔记 - 准备 - Day 1

    信息安全是一个有意思的方向,也是自己的爱好,从零开始,想在工作之余把这个爱好培养为自己的技术能力,而 web 安全相对来说容易入门些,于是选择 web 渗透测试作为学习的起点,并选择同样是容易入门的 ...

  9. 《Python黑帽子:黑客与渗透测试编程之道》读书笔记(四):web攻击

    目录 前言 1.urllib2 2.开源web应用安装 3.破解目录和文件位置 4.破解HTML表格认证 结语 前言 <Python黑帽子:黑客与渗透测试编程之道>的读书笔记,会包括书中源 ...

  10. 《Python黑帽子:黑客与渗透测试编程之道》读书笔记(三):scapy——网络的掌控者

    目录 前言 1.窃取email认证 2.ARP缓存投毒 3.PCAP文件处理 结语 前言 <Python黑帽子:黑客与渗透测试编程之道>的读书笔记,会包括书中源码,并自己将其中一些改写成P ...

最新文章

  1. Android 实用开源控件
  2. RHEL 6.5 中的KVM虚拟化新特性
  3. Java Web学习总结(10)——Session详解
  4. CODE Unicode roleName_字符类型数据 人物名子
  5. PHP之mb_convert_case使用
  6. SilverLight跨域访问及其常用的几种解决方法
  7. win10关闭电池保护模式_近年最稳的Win10更新?Win10 1909值得升级吗
  8. C++中的 求模运算 和 求余运算
  9. 浅谈AI芯片的简要发展历史
  10. python+openCV+tkinter---人脸识别登录系统
  11. ColdFusion CGI or Application variables
  12. oracle左外链接多表,sql – 在Oracle中的多个表的左外连接
  13. 探秘金山隐私保险箱 (解密出加密的数据)
  14. 传奇人物《周兴和》书连载30 成功背后的陷阱
  15. Kubelet Eviction Manager工作机制
  16. CISP证书的基本常识
  17. cobra是什么鬼?
  18. Apple TV 人机界面指南
  19. 如何在Deepin Linux下安装Docker容器经验分享
  20. 微信多开?一招教你想开几个开几个

热门文章

  1. android 设备实现定时重启(无root权限或已root)
  2. node.js 谷歌翻译api
  3. 破解入门(八)-----算法分析与注册机编写
  4. android qq输入法表情,QQ输入法-问题反馈
  5. php酒店预订源码,如家快捷酒店预订源码 for php
  6. 计算机网络——计算机网络病毒和黑客
  7. 黑苹果固态硬盘_普通电脑也能尝试:MacOS黑苹果+雷电3硬盘盒测试
  8. 在线教学试卷讲评利器——屏幕画笔
  9. 廖雪峰Git教程学习总结
  10. DDS原理以及MATLAB实现