114 lines
4.1 KiB
Python
114 lines
4.1 KiB
Python
import os
|
||
import re
|
||
import subprocess
|
||
import random
|
||
import string
|
||
import sys
|
||
|
||
# ========== 配置区域 ==========
|
||
# Doxygen 源码根目录(包含源码的路径)
|
||
SOURCE_ROOT = './' # 你放源码的路径(比如克隆的doxygen源码根目录)
|
||
|
||
# 编译数据库路径(compile_commands.json所在目录)
|
||
BUILD_PATH = './build'
|
||
|
||
# clang-rename 可执行文件路径(根据brew或自定义安装路径调整)
|
||
CLANG_RENAME_PATH = '/usr/local/opt/llvm/bin/clang-rename'
|
||
|
||
# 支持的源码文件后缀
|
||
SOURCE_EXTENSIONS = ['.cpp', '.c', '.h', '.hpp', '.cc']
|
||
|
||
# 是否实际执行clang-rename(True执行,False只打印模拟)
|
||
EXECUTE_RENAME = True
|
||
|
||
# ======== 混淆名生成 ========
|
||
def generate_random_name(length=8):
|
||
# 生成随机字母数字串,比如 A1b2C3d4
|
||
letters_and_digits = string.ascii_letters + string.digits
|
||
return ''.join(random.choice(letters_and_digits) for _ in range(length))
|
||
|
||
# ======== 扫描源码符号(示例仅提取函数和类名)========
|
||
def scan_symbols(source_root):
|
||
symbols = set()
|
||
function_pattern = re.compile(r'\b(?:class|struct|void|int|bool|char|float|double|unsigned|static|virtual|inline|constexpr|auto)\s+([a-zA-Z_]\w*)\s*\(')
|
||
class_pattern = re.compile(r'\b(class|struct)\s+([a-zA-Z_]\w*)')
|
||
variable_pattern = re.compile(r'\b(?:int|bool|char|float|double|unsigned|auto|static|constexpr)\s+([a-zA-Z_]\w*)\b')
|
||
|
||
for root, dirs, files in os.walk(source_root):
|
||
for file in files:
|
||
if any(file.endswith(ext) for ext in SOURCE_EXTENSIONS):
|
||
path = os.path.join(root, file)
|
||
try:
|
||
with open(path, 'r', encoding='utf-8', errors='ignore') as f:
|
||
content = f.read()
|
||
|
||
# 提取类名
|
||
for match in class_pattern.finditer(content):
|
||
symbols.add(match.group(2))
|
||
|
||
# 提取函数名
|
||
for match in function_pattern.finditer(content):
|
||
symbols.add(match.group(1))
|
||
|
||
# 提取变量名(谨慎,容易误报)
|
||
# for match in variable_pattern.finditer(content):
|
||
# symbols.add(match.group(1))
|
||
|
||
except Exception as e:
|
||
print(f"读取文件失败 {path}: {e}", file=sys.stderr)
|
||
|
||
# 过滤 C++ 关键字和常见函数名(简单示例)
|
||
keywords = {'if','for','while','switch','return','else','class','struct','static','void','int','bool','char','float','double','unsigned','auto','constexpr','inline','virtual','main'}
|
||
symbols = {s for s in symbols if s not in keywords and len(s) > 2}
|
||
|
||
return symbols
|
||
|
||
# ======== 调用 clang-rename 重命名 ========
|
||
def run_clang_rename(old_name, new_name):
|
||
print(f'[*] Renaming {old_name} -> {new_name}')
|
||
if not EXECUTE_RENAME:
|
||
print(f'(模拟) clang-rename -p {BUILD_PATH} -old-name={old_name} -new-name={new_name}')
|
||
return
|
||
|
||
try:
|
||
subprocess.run([
|
||
CLANG_RENAME_PATH,
|
||
f'-p={BUILD_PATH}',
|
||
f'-old-name={old_name}',
|
||
f'-new-name={new_name}'
|
||
], check=True)
|
||
except subprocess.CalledProcessError as e:
|
||
print(f'[错误] 重命名 {old_name} 到 {new_name} 失败: {e}', file=sys.stderr)
|
||
|
||
def main():
|
||
print('[*] 扫描源码符号...')
|
||
symbols = scan_symbols(SOURCE_ROOT)
|
||
print(f'[+] 共发现 {len(symbols)} 个符号')
|
||
|
||
# 手动排除或者白名单(防止混淆关键API),可自行扩展
|
||
exclude_symbols = {
|
||
'main', 'printf', 'fprintf', 'exit',
|
||
'Doxygen', 'Config', 'Parser', 'run', 'Error',
|
||
# 可以加入更多Doxygen项目的核心接口名
|
||
}
|
||
|
||
symbols = [s for s in symbols if s not in exclude_symbols]
|
||
|
||
print(f'[+] 过滤后准备混淆 {len(symbols)} 个符号')
|
||
|
||
# 构建映射:旧名 -> 新名
|
||
rename_map = {}
|
||
|
||
for s in symbols:
|
||
new_name = generate_random_name(10)
|
||
rename_map[s] = new_name
|
||
|
||
# 逐个重命名
|
||
for old_name, new_name in rename_map.items():
|
||
run_clang_rename(old_name, new_name)
|
||
|
||
print('[*] 混淆完成')
|
||
|
||
if __name__ == '__main__':
|
||
main()
|