You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
11 KiB
252 lines
11 KiB
'''
|
|
渗透测试任务管理类 一次任务的闭合性要检查2025-3-10 一次任务后要清理LLM和InstrM的数据
|
|
'''
|
|
from TargetManager import TargetManager # 从模块导入类
|
|
from LLMManager import LLMManager # 同理修正其他导入
|
|
from myutils.FileManager import FileManager
|
|
from InstructionManager import InstructionManager
|
|
from mycode.DBManager import DBManager
|
|
from myutils.MyTime import get_local_timestr
|
|
import queue
|
|
import time
|
|
import os
|
|
import threading
|
|
class TaskManager:
|
|
|
|
def __init__(self):
|
|
self.TargetM = TargetManager()
|
|
# 生成功能对象
|
|
self.LLMM = LLMManager(1)
|
|
self.InstrM = InstructionManager()
|
|
self.DBM = DBManager() #主进程一个DBM
|
|
self.DBM.connect()
|
|
# 控制最大并发指令数量
|
|
self.max_thread_num = 2
|
|
self.task_id = 0 #任务id --
|
|
self.do_sn = 0 #指令执行顺序号--暂时已执行完成顺序记录
|
|
self.workth_list = [] #线程句柄list
|
|
self.batch_num = 0 #一个批次的指令数量
|
|
self.long_instr_num = 0 #耗时指令数量
|
|
self.long_time_instr = ['nikto'] #耗时操作不计入批量执行的数量,不加不减
|
|
self.instr_queue = queue.Queue() #线程安全 --待执行指令
|
|
self.user_instr = queue.Queue() #需要用确认或手动执行的命令--待执行指令
|
|
self.user_done_instr = queue.Queue() #执行完成需要用户确认的指令
|
|
self.doing_instr = queue.Queue()#执行中的指令
|
|
self.done_instr = queue.Queue() #执行完成的指令
|
|
self.res_queue = queue.Queue() #结果队列
|
|
self.lock = threading.Lock() #线程锁
|
|
self.do_sn_lock = threading.Lock() #指令执行顺序号锁
|
|
self.brun = True
|
|
|
|
def is_user_instr(self,instr):
|
|
'''
|
|
过滤需要人工确认或手动执行的指令 ---- 待完善
|
|
:param instr:
|
|
:return:
|
|
'''
|
|
#if instr.startswith("curl") or instr.startswith("http") or instr.startswith("wget"):
|
|
if instr.startswith("http") or instr.startswith("wget") or instr.startswith("ssh"):
|
|
return True
|
|
|
|
def instr_in_quere(self,instr_list):
|
|
'''
|
|
对于运行需要较长时间的不强求同一批次返回给LLM
|
|
:param instr_list:
|
|
:return:
|
|
'''
|
|
for instr in instr_list:
|
|
if self.is_user_instr(instr):
|
|
self.user_instr.put(instr)
|
|
print(f"需要人工确认的指令{instr}")
|
|
else:
|
|
matched =False
|
|
for prefix in self.long_time_instr:
|
|
if instr.startswith(prefix):
|
|
matched =True
|
|
if not matched:
|
|
with self.lock:
|
|
self.batch_num += 1 #非耗时指令+1
|
|
print(f"&&&&&&当前batch_num:{self.batch_num}")
|
|
else:
|
|
with self.lock:
|
|
self.long_instr_num +=1 #耗时指令数量+1
|
|
# 指令入队列
|
|
self.instr_queue.put(instr)
|
|
|
|
#入数据库放哪一层要待定-TaskManager , InstructionM,ToolBase-2025-3-10
|
|
def res_in_db(self,bres,instr,reslut,start_time,end_time,th_DBM,source_result,ext_params):
|
|
if th_DBM.ok:
|
|
with self.do_sn_lock:
|
|
self.do_sn += 1 #指令的执行序列是一个任务共用,要线程锁,错误问题也不大
|
|
th_DBM.insetr_result(self.task_id,instr,reslut,self.do_sn,start_time,end_time,source_result,ext_params)
|
|
else:
|
|
print("数据库连接失败!!")
|
|
|
|
def res_in_quere(self,bres,instr,reslut,start_time,end_time,th_DBM,source_result,ext_params):
|
|
'''
|
|
执行结果入队列,若批量执行的指令都完成,则提交LLM生成下一步指令
|
|
:param bres:
|
|
:param instr:
|
|
:param reslut:
|
|
:return:
|
|
'''
|
|
matched = False
|
|
bover = False
|
|
#入数据库 -- bres True和False 都入数据库2025-3-10
|
|
self.res_in_db(bres,instr,reslut,start_time,end_time,th_DBM,source_result,ext_params)
|
|
|
|
#结果入队列
|
|
if bres:
|
|
res = {'instr':instr,'reslut':reslut}
|
|
self.res_queue.put(res) #入队列
|
|
else: #对于不需要再提交给LLM的结果,如何处理待定。有执行false、未知工具
|
|
pass
|
|
#判断批次指令是否都执行完
|
|
for prefix in self.long_time_instr:
|
|
if instr.startswith(prefix):
|
|
matched = True
|
|
if not matched:
|
|
with self.lock:
|
|
self.batch_num -= 1 #非耗时指令-1
|
|
print(f"&&&&&&当前batch_num:{self.batch_num}")
|
|
if self.batch_num ==0: #只会轮询到最后一个线程才会是0
|
|
bover = True
|
|
else:
|
|
#这里会有个问题,若耗时指令执行完,结果入队列后,但LLM没有进一步的指令下发,会造成结果不会提交
|
|
#需要在生成“生成报告”的指令时进行研判--该点很重要
|
|
with self.lock:
|
|
self.long_instr_num -=1 #耗时指令数量-1
|
|
if bover:
|
|
#整合结果提交 -- 需要确保只有一个线程会执行
|
|
self.batch_res_post(th_DBM)
|
|
|
|
def batch_res_post(self,th_DBM):
|
|
'''
|
|
组合批量指令的结果,一起提交到LLM,生成下一步具体指令
|
|
:return:
|
|
'''
|
|
post_string = ""
|
|
while not self.res_queue.empty():
|
|
res = self.res_queue.get()
|
|
str = f"执行指令:{res['instr']}的结果是:{res['reslut']}。"
|
|
post_string = post_string + "\n"
|
|
post_string = post_string + str
|
|
|
|
if post_string:
|
|
post_string = post_string + "\n请根据这些结果生成下一步具体的指令。"
|
|
|
|
print(f"***************\n{post_string}")
|
|
with open("res","w",encoding="utf-8") as f:
|
|
f.write(post_string)
|
|
#*****测试时中断下一步指令的获取
|
|
# 提交提示词,得到下一步指令
|
|
# instr_list = self.LLMM.get_llm_instruction(post_string,th_DBM)
|
|
# if instr_list:
|
|
# if instr_list[0] == "生成报告": #“生成报告”要特殊处理#?
|
|
# self.brun = False
|
|
# print("生成报告--退出工作线程")
|
|
# else: # 继续工作
|
|
# self.instr_in_quere(instr_list)
|
|
|
|
def do_worker_th(self):
|
|
#线程的dbm需要一个线程一个
|
|
th_DBM = DBManager()
|
|
th_DBM.connect()
|
|
while self.brun:
|
|
try:
|
|
instruction = self.instr_queue.get(block=False) #quere线程安全,block=false非阻塞get
|
|
self.doing_instr.put(instruction) #入执行队列
|
|
#执行中会对指令进行微调,并有可能不执行直接返回空结果
|
|
start_time = get_local_timestr() #指令执行开始时间
|
|
bres,instr,reslut,source_result,ext_params = self.InstrM.execute_instruction(instruction)
|
|
end_time = get_local_timestr() #指令执行结束时间
|
|
self.res_in_quere(bres,instr,reslut,start_time,end_time,th_DBM,source_result,ext_params) #执行结果入队列
|
|
self.done_instr.put(instruction) #执行完成队列
|
|
#执行情况是否需要用户确认
|
|
if ext_params["is_user"]:
|
|
pass
|
|
#print("该指令执行需要用户确认")
|
|
except queue.Empty:
|
|
time.sleep(10)
|
|
#函数结束,局部变量自动释放
|
|
|
|
def start_task(self,target_name,target_in):
|
|
#判断目标合法性
|
|
bok,target,type = self.TargetM.validate_and_extract(target_in)
|
|
if bok:
|
|
self.target = target
|
|
self.type = type #1-IP,2-domain
|
|
self.task_id = self.DBM.start_task(target_name,target_in) #数据库新增任务记录
|
|
#获取基本信息: 读取数据库或预生成指令,获取基本的已知信息
|
|
know_info = "无" #?
|
|
#启动--初始化指令
|
|
prompt = self.LLMM.build_initial_prompt(target,know_info)
|
|
instr_list = self.LLMM.get_llm_instruction(prompt,self.DBM)
|
|
self.instr_in_quere(instr_list) #指令入队列
|
|
|
|
#创建工作线程
|
|
for i in range(self.max_thread_num):
|
|
w_th = threading.Thread(target=self.do_worker_th)
|
|
w_th.start()
|
|
self.workth_list.append(w_th)
|
|
|
|
#等待线程结束--执行生成报告
|
|
for t in self.workth_list:
|
|
t.join()
|
|
#生成报告
|
|
pass
|
|
else:
|
|
return False,"{target}检测目标不合规,请检查!"
|
|
|
|
def stop_task(self):
|
|
self.brun = False
|
|
self.LLMM.init_data() #清空一些全局变量
|
|
self.InstrM.init_data()
|
|
#结束任务需要收尾处理#?
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import json
|
|
TM = TaskManager()
|
|
FM = FileManager()
|
|
current_path = os.path.dirname(os.path.realpath(__file__))
|
|
strMsg = FM.read_file("test",1)
|
|
TM.LLMM.test_old_message(strMsg) #先设置message的值
|
|
test_type = 3
|
|
if test_type == 1:
|
|
#测试执行指令
|
|
# instrS = ['gobuster dir -u https://58.216.217.70 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -k -t 20 --timeout 10s',
|
|
# 'searchsploit SoftEther VPN',
|
|
# 'curl -kv -X POST -d "username=admin&password=admin" https://58.216.217.70/vpn/index.html --connect-timeout 10',
|
|
# 'gobuster dir -u http://58.216.217.70:10001 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 20 --timeout 10s']
|
|
#instrS = ['nmap -sV -sC -p- -Pn 192.168.204.137']
|
|
with open("test", "r", encoding="utf-8") as f:
|
|
messages = json.load(f)
|
|
text = messages[-1]["content"]
|
|
#list = TM.LLMM.fetch_instruction(text)[9:10]
|
|
list = TM.LLMM.fetch_instruction(text)
|
|
#print(list)
|
|
TM.instr_in_quere(list)
|
|
#创建线程执行指令
|
|
for i in range(TM.max_thread_num):
|
|
w_th = threading.Thread(target=TM.do_worker_th)
|
|
w_th.start()
|
|
TM.workth_list.append(w_th)
|
|
# 等待线程结束--执行生成报告
|
|
for t in TM.workth_list:
|
|
t.join()
|
|
elif test_type ==2:
|
|
#测试LLM返回下一步指令
|
|
with open("res", "r", encoding="utf-8") as f:
|
|
prompt = f.read()
|
|
if prompt:
|
|
instr_list = TM.LLMM.get_llm_instruction(prompt,TM.DBM)
|
|
TM.instr_in_quere(instr_list) # 指令入队列问题不大,任务执行线程没有起
|
|
elif test_type ==3: #新目标测试
|
|
prompt = TM.LLMM.build_initial_prompt("192.168.204.137","无")
|
|
if prompt:
|
|
instr_list = TM.LLMM.get_llm_instruction(prompt,TM.DBM)
|
|
TM.instr_in_quere(instr_list) # 指令入队列问题不大,任务执行线程没有起
|
|
else:
|
|
#完整过程测试---要设定终止条件
|
|
pass
|
|
|