Spaces:
Sleeping
Sleeping
Fix yara
Browse files
app.py
CHANGED
|
@@ -65,31 +65,84 @@ async def clone_yara_repo():
|
|
| 65 |
logger.error(f"Error cloning YARA repository: {str(e)}")
|
| 66 |
return None
|
| 67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
def compile_yara_rules(repo_path: Path) -> Optional[yara.Rules]:
|
| 69 |
-
"""Compile YARA rules from repository"""
|
| 70 |
try:
|
| 71 |
-
|
|
|
|
|
|
|
| 72 |
if not yara_files:
|
| 73 |
-
logger.warning("No YARA files
|
| 74 |
return None
|
| 75 |
|
| 76 |
-
logger.info(f"
|
| 77 |
rules = {}
|
| 78 |
|
| 79 |
for yara_file in yara_files:
|
| 80 |
try:
|
| 81 |
-
|
|
|
|
|
|
|
| 82 |
except Exception as e:
|
| 83 |
-
logger.warning(f"Error
|
| 84 |
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
| 89 |
except Exception as e:
|
| 90 |
logger.error(f"Error compiling YARA rules: {str(e)}")
|
| 91 |
-
|
| 92 |
-
return None
|
| 93 |
|
| 94 |
@asynccontextmanager
|
| 95 |
async def lifespan(app: FastAPI):
|
|
|
|
| 65 |
logger.error(f"Error cloning YARA repository: {str(e)}")
|
| 66 |
return None
|
| 67 |
|
| 68 |
+
def preprocess_yara_rules(repo_path: Path) -> Path:
|
| 69 |
+
"""Preprocess YARA rules to fix syntax issues"""
|
| 70 |
+
processed_dir = Path("processed_yara_rules")
|
| 71 |
+
if processed_dir.exists():
|
| 72 |
+
shutil.rmtree(processed_dir)
|
| 73 |
+
processed_dir.mkdir()
|
| 74 |
+
|
| 75 |
+
for yara_file in repo_path.glob("**/*.yar"):
|
| 76 |
+
try:
|
| 77 |
+
content = yara_file.read_text(encoding='utf-8', errors='replace')
|
| 78 |
+
|
| 79 |
+
# Fix invalid rule names and string identifiers
|
| 80 |
+
processed_content = []
|
| 81 |
+
rule_counter = 1
|
| 82 |
+
string_counter = 1
|
| 83 |
+
current_rule = None
|
| 84 |
+
|
| 85 |
+
for line in content.split('\n'):
|
| 86 |
+
# Normalize rule names
|
| 87 |
+
if line.strip().startswith('rule '):
|
| 88 |
+
rule_name = line.split('{')[0].split('rule ')[1].strip()
|
| 89 |
+
# Replace invalid characters and ensure unique names
|
| 90 |
+
clean_name = rule_name.replace('#', '').replace(' ', '_').replace('-', '_')
|
| 91 |
+
clean_name = f"Rule_{rule_counter}_{clean_name}"[:128]
|
| 92 |
+
processed_content.append(f"rule {clean_name} {{")
|
| 93 |
+
current_rule = clean_name
|
| 94 |
+
rule_counter += 1
|
| 95 |
+
string_counter = 1
|
| 96 |
+
# Make string identifiers unique per rule
|
| 97 |
+
elif '$a_01_' in line and current_rule:
|
| 98 |
+
new_id = f"${current_rule}_str_{string_counter}"
|
| 99 |
+
line = line.replace('$a_01_', new_id, 1)
|
| 100 |
+
string_counter += 1
|
| 101 |
+
processed_content.append(line)
|
| 102 |
+
else:
|
| 103 |
+
processed_content.append(line)
|
| 104 |
+
|
| 105 |
+
# Save processed file
|
| 106 |
+
processed_file = processed_dir / yara_file.name
|
| 107 |
+
processed_file.write_text('\n'.join(processed_content))
|
| 108 |
+
|
| 109 |
+
except Exception as e:
|
| 110 |
+
logger.warning(f"Error processing {yara_file}: {str(e)}")
|
| 111 |
+
continue
|
| 112 |
+
|
| 113 |
+
return processed_dir
|
| 114 |
+
|
| 115 |
def compile_yara_rules(repo_path: Path) -> Optional[yara.Rules]:
|
| 116 |
+
"""Compile YARA rules from repository with error handling"""
|
| 117 |
try:
|
| 118 |
+
processed_dir = preprocess_yara_rules(repo_path)
|
| 119 |
+
yara_files = list(processed_dir.glob("**/*.yar"))
|
| 120 |
+
|
| 121 |
if not yara_files:
|
| 122 |
+
logger.warning("No valid YARA files after preprocessing")
|
| 123 |
return None
|
| 124 |
|
| 125 |
+
logger.info(f"Compiling {len(yara_files)} processed YARA files")
|
| 126 |
rules = {}
|
| 127 |
|
| 128 |
for yara_file in yara_files:
|
| 129 |
try:
|
| 130 |
+
# Use namespace based on file path to avoid conflicts
|
| 131 |
+
namespace = str(yara_file.relative_to(processed_dir)).replace('/', '_')
|
| 132 |
+
rules[namespace] = str(yara_file)
|
| 133 |
except Exception as e:
|
| 134 |
+
logger.warning(f"Error adding {yara_file}: {str(e)}")
|
| 135 |
|
| 136 |
+
# Compile with error handling
|
| 137 |
+
try:
|
| 138 |
+
return yara.compile(filepaths=rules, error_on_warning=False)
|
| 139 |
+
except yara.SyntaxError as e:
|
| 140 |
+
logger.error(f"YARA syntax error in processed rules: {str(e)}")
|
| 141 |
+
return None
|
| 142 |
+
|
| 143 |
except Exception as e:
|
| 144 |
logger.error(f"Error compiling YARA rules: {str(e)}")
|
| 145 |
+
return None
|
|
|
|
| 146 |
|
| 147 |
@asynccontextmanager
|
| 148 |
async def lifespan(app: FastAPI):
|