第4回:Pythonでネットワークプログラミング(Netcat的なものを実装)
そもそも、Netcaってなんなの?ということで、Wikipediaへ。どうやら、TCPやUDPのパケットを読み書きできるコマンドラインツールらしい...。とりあえず、本で紹介されているので実装してみましょう。紹介したプログラムは、ファイルのアップロード、コマンドの実行をすることができます。sshとscpの非常に簡単版です。もちろん暗号化されていないのでお遊びだと考えてください。参考としている本とは、多少コードが違いますので、元ネタを知りたい方は参考文献へ。ここで力尽きました...。残っているタイトルは後日作成します。
Black Hat Python: Python Programming for Hackers and Pentesters
- 作者: Justin Seitz
- 出版社/メーカー: No Starch Pr
- 発売日: 2014/12/14
- メディア: ペーパーバック
- この商品を含むブログを見る
Netcat的なものを実装
#! /usr/bin/env python # coding:utf-8 # netcat.py import sys import socket from optparse import OptionParser import threading import subprocess listen = False command = False upload = False execute = '' target = '' upload_destination = '' port = 0 def usage(): """オプションの解析""" """サーバー側での実行例(コマンドの受付):netcat.py -l -p 5555 -c """ """クライアント側での実行例(コマンドの受け渡し):netcat.py -t 0.0.0.0 -p 5555""" """Fileのアップロード,-u""" description="Examples:\n\r\ netcat.py -t 192.168.0.1 -p 5555 -l -c\n\ netcat.py -t 192.168.0.1 -p 5555 -l -c -u=c:\\target.ext\n\ netcat.py -t 192.168.0.1 -p 5555 -l -c -e=\"cat /etc/passwd\"\n\ echo 'ABCDEFGHI' | netcat.py -t 192.168.0.1 -p 135\n\ " parser=OptionParser(usage='%prog [-c] [-l] [-u] [-e] [-t] [-p]',epilog=description) parser.add_option('-c','--commandshell',help='initialize a command shell',default=False,action='store_true') parser.add_option('-u','--upload',help='upon receiving connection upload a file and write to [destination]',default='') parser.add_option('-l','--listen',help='listen on [host]:[port] for incoming connections',default=False,action='store_true') parser.add_option('-e','--execute',help='ececute the fiven file upon receiving a command shell',default='') parser.add_option('-t','--target',help='',default='') parser.add_option('-p','--port',help='',type=int) opt,args=parser.parse_args() global listen global port global execute global command global upload_destination global target listen = opt.listen command = opt.commandshell upload = opt.upload execute = opt.execute target = opt.target upload_destination = opt.upload port = opt.port def main(): global listen global port global execute global command global upload_destination global target usage() if not listen and len(target) and port > 0: print ":Client mode" buffer = sys.stdin.readline() client_sender(buffer) if listen: print ":Server mode" server_loop() 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: buf_size = 4096 data = client.recv(buf_size) recv_len = len(data) response += data if recv_len < buf_size: break print response, #クライアント側で実行した結果を受け取り、表示する。 buffer = raw_input('') #クライアントの要求の受付を継続する。 buffer += '\n' client.send(buffer) except: print '[*] Exception! Exiting.' client.close() def server_loop(): global target global port 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() print addr client_thread = threading.Thread(target=client_handler,args=(client_socket,)) #threadingに関しては過去の記事を参照してください。 client_thread.start() def run_command(command): command = command.rstrip() #改行の削除 try: output = subprocess.check_output(command,stderr=subprocess.STDOUT,shell=True) #コマンドの実行を結果をoutputに保存する。 #subprocessはpythonの標準ライブラリなので、勉強する価値はあります。公式のドキュメントが分かりやすいです。 except: output = 'Failed to execute command.\n\r' return output def client_handler(client_socket): global upload global execute global command if len(upload_destination): file_buffe = '' while True: buf_size = 1024 data = client_socket.recv(buf_size) 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 file to %s\r\n' % upload_destination) except: client_socket.send('Failed to save file file to %s\r\n' % upload_destination) if len(execute): output = run_command(execute) client_socket.send(output) if command: #flag -c が設定されているときにcomandが実行される。 while True: client_socket.send('<BF?:#>') cmd_buffer = '' while '\n' not in cmd_buffer: cmd_buffer += client_socket.recv(1024) response = run_command(cmd_buffer) client_socket.send(response) main()