import os from typing import Dict, List, Tuple from reportlab.lib.pagesizes import letter from reportlab.pdfgen import canvas from reportlab.lib.styles import getSampleStyleSheet from reportlab.platypus import Paragraph, Spacer, SimpleDocTemplate from reportlab.lib import colors from .Regexdetection import find_dangerous_functions from .GPTdetection import detectGPT from .utils import * SUPPORTED_EXTENSIONS = {".py", ".js", ".cpp"} OUTPUT_FORMATS = ["html", "md", "txt", "pdf"] def generate_text_content(results): text_output = "Security Analysis Report\n" for risk_level, entries in results.items(): if entries and risk_level != "none": text_output += f"{risk_level.capitalize()} Risk:\n" for line_num, line in entries: text_output += f" Line {line_num}: {line}\n" return text_output def output_results(results, output_format, output_file=None): if output_file: file_name, file_extension = os.path.splitext(output_file) if output_format not in OUTPUT_FORMATS: output_format = "txt" output_file = f"{file_name}.txt" results_dir = os.path.dirname(output_file) if not os.path.exists(results_dir): os.makedirs(results_dir) if output_format == "pdf": output_pdf(results, output_file) elif output_format == "html": output_html(results, output_file) elif output_format == "md": output_markdown(results, output_file) else: # Default to txt output_text(results, output_file) else: # If no output file is specified, default to text output to the terminal. txt_output = generate_text_content(results) print(txt_output) def output_pdf(results: Dict[str, List[Tuple[int, str]]], file_name): doc = SimpleDocTemplate(file_name, pagesize=letter) story = [] styles = getSampleStyleSheet() # Add the title centered title_style = styles["Title"] title_style.alignment = 1 # Center alignment title = Paragraph("Security Analysis Report", title_style) story.append(title) story.append(Spacer(1, 20)) # Space after title # Add risk levels and entries normal_style = styles["BodyText"] for risk_level, entries in results.items(): if risk_level != "none": story.append( Paragraph(f"{risk_level.capitalize()} Risk:", styles["Heading2"]) ) for line_num, line in entries: entry = Paragraph(f"Line {line_num}: {line}", normal_style) story.append(entry) story.append(Spacer(1, 12)) # Space between sections doc.build(story) def output_html(results: Dict[str, List[Tuple[int, str]]], file_name=None): html_output = "Security Analysis Report" html_output += "

Security Analysis Report

" for risk_level, entries in results.items(): if risk_level != "none": html_output += f"

{risk_level.capitalize()} Risk

" html_output += "" if file_name: with open(file_name, "w") as file: file.write(html_output) else: return html_output def output_markdown(results: Dict[str, List[Tuple[int, str]]], file_name=None): md_output = "# Security Analysis Report\n" for risk_level, entries in results.items(): if risk_level != "none": md_output += f"## {risk_level.capitalize()} Risk\n" for line_num, line in entries: md_output += f"- {line_num}: {line}\n" if file_name: with open(file_name, "w") as file: file.write(md_output) else: return md_output def output_text(results: Dict[str, List[Tuple[int, str]]], file_name=None): text_output = "Security Analysis Report\n" for risk_level, entries in results.items(): if risk_level != "none": text_output += f"{risk_level.capitalize()} Risk:\n" for line_num, line in entries: text_output += f" {line_num}: {line}\n" if file_name: with open(file_name, "w") as file: file.write(text_output) else: return text_output def checkModeAndDetect(mode: str,filePath: str,fileExtension: str): #TODO:添加更多方式,这里提高代码的复用性和扩展性 if mode == "regex": return find_dangerous_functions(read_file_content(filePath), fileExtension) elif mode == "llm": return detectGPT(read_file_content(filePath)) def process_path(path: str, output_format: str, mode: str, output_file=None): results = {"high": [], "medium": [], "low": [], "none": []} if os.path.isdir(path): for root, dirs, files in os.walk(path): for file in files: file_extension = os.path.splitext(file)[1] if file_extension in SUPPORTED_EXTENSIONS: file_path = os.path.join(root, file) file_results = checkModeAndDetect(mode,file_path,file_extension) for key in file_results: if key != "none": # Exclude 'none' risk level results[key].extend( [ (f"{file_path}: Line {line_num}", line) for line_num, line in file_results[key] ] ) elif os.path.isfile(path): file_extension = os.path.splitext(path)[1] if file_extension in SUPPORTED_EXTENSIONS: file_results = checkModeAndDetect(mode,path,file_extension) for key in file_results: if key != "none": # Exclude 'none' risk level results[key].extend( [ (f"{path}: Line {line_num}", line) for line_num, line in file_results[key] ] ) else: print("Unsupported file type.") return else: print("Invalid path.") sys.exit(1) output_results(results, output_format, output_file) def main(): import argparse parser = argparse.ArgumentParser(description="Backdoor detection tool.") parser.add_argument("path", help="Path to the code to analyze") parser.add_argument("-o", "--output", help="Output file path", default=None) parser.add_argument("-m", "--mode", help="Mode of operation:[regex,llm]", default="regex") args = parser.parse_args() output_format = "txt" # Default output format output_file = None if args.output: _, ext = os.path.splitext(args.output) ext = ext.lower() if ext in [".html", ".md", ".txt", ".pdf"]: output_format = ext.replace(".", "") output_file = args.output else: print( "Your input file format was incorrect, the output has been saved as a TXT file." ) output_file = args.output.rsplit(".", 1)[0] + ".txt" process_path(args.path, output_format, args.mode, output_file) if __name__ == "__main__": main()