from tools.ToolBase import ToolBase
import re
import json
import subprocess
import os
import shutil
from pathlib import Path
class SearchsploitTool(ToolBase):
    def validate_instruction(self, instruction):
        #指令过滤
        timeout = 0
        if "-m " in instruction:  # 下载利用代码
            timeout = 60
        return instruction,timeout

    def analyze_result(self, result,instruction,stderr,stdout):
        #获取当前路径
        cur_path =  Path(__file__).resolve().parent
        payload_dir = cur_path / "../payload"

        #if instruction(result,bytes):
        if type(result) is bytes:
            result = result.decode('utf-8',errors='ignore')

        """去除 ANSI 颜色码"""
        ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
        clean_result =  ansi_escape.sub('', result)
        # 指令结果分析
        if "-m " in instruction:#下载利用代码
            if "Copied to:" in clean_result or "cp: overwrite " in clean_result:
                result = "下载完成"
            else:
                result = "下载失败"
        else: #目前只遇到两种searchsploit命令格式:
            lines = clean_result.split("\n")
            exploits = []

            for line in lines:
                match = re.match(r"(.+?)\s+\|\s+(\S+)", line)
                if match:
                    title = match.group(1).strip()
                    path = match.group(2).strip()
                    if "Path" not in path:
                        #下载渗透脚本--进一步推进
                        ext_str = self.do_ext(path,payload_dir)
                        exploits.append({"title": title, "path": path,"补充信息":ext_str})

            if len(exploits) > 0:
                result = json.dumps(exploits,ensure_ascii=False)       #输出原始的中文字符
            else:
                result = "没有检索到漏洞利用脚本"
        return result

    def find_file_in_directory(self,target_file, dir_path, case_sensitive=True, recursive=False):
        """
        在指定目录中查找文件是否存在
        :param target_file: 要查找的目标文件名(含扩展名)
        :param search_dir: 要搜索的目录路径
        :param case_sensitive: 是否区分大小写(默认True)
        :param recursive: 是否递归搜索子目录(默认False)
        :return: (bool, str) 是否存在,完整路径(如果找到)
        """
        try:
            #dir_path = Path(search_dir)

            # 验证目录是否存在
            if not dir_path.is_dir():
                return False, None

            # 根据是否递归选择遍历方式
            iterator = dir_path.rglob('*') if recursive else dir_path.iterdir()

            for entry in iterator:
                # 跳过目录只处理文件
                if entry.is_file():
                    # 根据是否区分大小写进行比较
                    if case_sensitive:
                        match = entry.name == target_file
                    else:
                        match = entry.name.lower() == target_file.lower()

                    if match:
                        return True, str(entry.resolve())

            return False, None

        except Exception as e:
            print(f"查找出错: {str(e)}")
            return False, None

    def do_download(self,filepath,dirpath):
        '''
        下载渗透脚本
        :return:
        '''
        filename = filepath.split("/")[-1]
        if ".py" in filename:
            #对应payload库中是否存在该脚本
            bfind,_ = self.find_file_in_directory(filename,dirpath)
            if bfind:
                return True
            else:#下载
                instruction = f"searchsploit -m {filepath}"
                try:
                    subprocess.run(instruction, shell=True, check=True,timeout=60)
                    print("命令执行成功,文件下载完成。")
                except subprocess.CalledProcessError as e: #超时暂不处理--后续补充
                    print(f"命令执行失败: {e}")
                    return False

                if not os.path.exists(filename):
                    return False
                # 移动文件到目标目录
                try:
                    shutil.move(filename, os.path.join(dirpath, filename))
                    print(f"文件已成功移动到 {dirpath}")
                    return True
                except Exception as e:
                    print(f"移动文件失败: {e}")
                    return False
        else:   #暂时只利用python脚本
            return False

    def do_ext(self,filepath,payload_dir) -> str:
        bdownload = self.do_download(filepath,payload_dir)
        if bdownload:
            return "该渗透脚本已经复制到当前路径。"
        else:
            return "暂时不利用该渗透脚本。"