JavaScript 反混淆与 Python 执行JS

tags: (大模型生成,存档备查)

JavaScript 反混淆与 Python 执行

1. JavaScript 反混淆方法

JavaScript 反混淆是一个复杂的过程,因为混淆的目的是使代码难以阅读和理解。以下是一些常用的反混淆方法:

1.1. 代码美化 (Code Beautification)

混淆后的代码通常会删除空格、换行符,并缩短变量名。代码美化工具可以恢复代码的可读性,使其更易于分析。

示例 (混淆前):

function add(a, b) { return a + b; }

示例 (混淆后):

function _0x123456(a,b){return a+b}

示例 (美化后):

function _0x123456(a, b) {
    return a + b;
}

1.2. 变量和函数重命名 (Variable and Function Renaming)

混淆器通常会将有意义的变量和函数名替换为无意义的短名称(如 _0x123456)。手动或使用工具将这些名称改回有意义的名称可以大大提高可读性。

1.3. 去除死代码和无用代码 (Dead Code and Obfuscation-Specific Code Removal)

混淆器可能会插入不会执行的“死代码”或专门用于混淆的复杂逻辑。识别并移除这些代码可以简化程序流程。

1.4. 字符串解密 (String Decryption)

许多混淆器会将字符串进行编码(如 Base64、Hex、Unicode 转义等),并在运行时解密。你需要找到解密函数并模拟其行为来获取原始字符串。

示例:

// 混淆代码中可能包含的字符串解密函数
function decryptString(encodedStr) {
    // 假设这里是Base64解码逻辑
    return atob(encodedStr);
}

var message = decryptString("SGVsbG8gV29ybGQ="); // "Hello World"

1.5. 控制流平坦化 (Control Flow Flattening) 反转

控制流平坦化将代码的线性执行流程转换为一个大的 switch 语句,使得难以跟踪执行路径。反转这种混淆通常需要深入理解混淆器的逻辑,并可能需要编写脚本来重建原始控制流。

1.6. 反调试和反篡改技术绕过 (Anti-Debugging and Anti-Tampering Bypass)

一些混淆代码会检测调试器或代码修改。反混淆前可能需要绕过这些保护措施。

1.7. 抽象语法树 (AST) 转换

对于复杂的混淆,直接操作代码字符串可能不够。将代码解析成抽象语法树 (AST),然后在 AST 层面进行转换和优化,最后再生成代码,是更强大的反混淆方法。

2. 通过 Python 执行混淆的 JS 文件并获取运行结果

Python 本身不能直接执行 JavaScript 代码。你可以通过调用外部 JavaScript 运行时(如 Node.js)或使用 Python 库来桥接 JavaScript 环境。

2.1. 使用 subprocess 模块调用 Node.js (推荐)

这是最常用且可靠的方法,特别是当 JavaScript 代码依赖于 Node.js 环境或浏览器 API(如 document.writeln,虽然 document 对象在 Node.js 中不存在,但可以通过模拟或修改 JS 代码来适应)。

前提: 确保你的系统上安装了 Node.js。

示例 (web.js):

// web.js (假设这是混淆后的JS文件,其中包含一个简单的输出)
var _0x516401 = "Hello from obfuscated JS!";
console.log(_0x516401);

// 如果web.js中包含document.writeln,你需要将其替换为console.log才能在Node.js中看到输出
// 例如,将 document.writeln('...') 改为 console.log('...')

Python 代码 (execute_js.py):

import subprocess
import os

def execute_js_with_nodejs(js_file_path):
    try:
        # 确保 Node.js 可执行文件在 PATH 中,或者提供完整路径
        # 如果 web.js 中有 document.writeln,需要先手动修改为 console.log
        command = ["node", js_file_path]
        
        # 执行命令并捕获标准输出和标准错误
        result = subprocess.run(
            command,
            capture_output=True,
            text=True, # 以文本模式捕获输出,自动解码
            check=True # 如果命令返回非零退出码,则抛出CalledProcessError
        )
        print("JS Output:")
        print(result.stdout)
        if result.stderr:
            print("JS Error (stderr):")
            print(result.stderr)
        return result.stdout
    except subprocess.CalledProcessError as e:
        print(f"Error executing JS: {e}")
        print(f"Stdout: {e.stdout}")
        print(f"Stderr: {e.stderr}")
        return None
    except FileNotFoundError:
        print("Error: Node.js not found. Please ensure Node.js is installed and in your system's PATH.")
        return None

# 假设 web.js 位于当前脚本的同级目录
js_file = os.path.join(os.path.dirname(__file__), 'web.js')

# 或者提供绝对路径
# js_file = 'f:\\python code\\爬虫\\论坛\\web.js'

if os.path.exists(js_file):
    print(f"Executing {js_file}...")
    js_output = execute_js_with_nodejs(js_file)
    if js_output:
        print("Successfully executed JS.")
else:
    print(f"Error: JS file not found at {js_file}")

2.2. 使用 PyExecJS

PyExecJS 是一个 Python 库,它会自动寻找并使用可用的 JavaScript 运行时(如 Node.js, PhantomJS, Nashorn, JScript 等)来执行 JavaScript 代码。它提供了一个更高级的接口。

安装:

pip install PyExecJS

示例 (web.js):

// web.js (假设这是混淆后的JS文件,其中包含一个简单的输出)
var _0x516401 = "Hello from obfuscated JS!";
// 注意:PyExecJS 默认不会直接捕获 console.log 的输出,除非你配置它。
// 通常,你需要让JS代码返回一个值,或者通过特定的方式将输出传递回Python。
// 对于简单的值,可以直接返回。
_0x516401;

Python 代码 (execute_js_pyexecjs.py):

import execjs
import os

def execute_js_with_pyexecjs(js_file_path):
    try:
        with open(js_file_path, 'r', encoding='utf-8') as f:
            js_code = f.read()
        
        # 创建一个JS上下文
        ctx = execjs.compile(js_code)
        
        # 执行JS代码并获取返回值
        # 如果JS文件中有全局变量或函数,你可以通过call方法调用它们
        # 例如:result = ctx.call("myFunction", arg1, arg2)
        # 对于简单的JS文件,如果最后一行是一个表达式,它的值会被返回
        result = ctx.eval("_0x516401") # 假设 _0x516401 是一个全局变量或表达式
        print("JS Execution Result:")
        print(result)
        return result
    except execjs.RuntimeUnavailableError:
        print("Error: No JavaScript runtime found. Please install Node.js or another compatible runtime.")
        return None
    except Exception as e:
        print(f"Error executing JS with PyExecJS: {e}")
        return None

# 假设 web.js 位于当前脚本的同级目录
js_file = os.path.join(os.path.dirname(__file__), 'web.js')

# 或者提供绝对路径
# js_file = 'f:\\python code\\爬虫\\论坛\\web.js'

if os.path.exists(js_file):
    print(f"Executing {js_file}...")
    js_output = execute_js_with_pyexecjs(js_file)
    if js_output:
        print("Successfully executed JS.")
else:
    print(f"Error: JS file not found at {js_file}")

注意: PyExecJS 在处理 console.logdocument.writeln 等副作用时可能不如 subprocess 直接。如果你的 JavaScript 代码主要通过这些方式输出,你可能需要修改 JavaScript 代码以返回所需的值,或者使用 subprocess 方法。

3. 在线 JavaScript 反混淆工具

以下是一些常用的在线 JavaScript 反混淆工具:

  1. JS Beautifier: <mcurl name="https://beautifier.io/" url="https://beautifier.io/"></mcurl> (主要用于代码美化,对轻度混淆有效)
  2. de4js (Online JavaScript Deobfuscator): <mcurl name="https://de4js.net/" url="https://de4js.net/"></mcurl> (支持多种混淆类型,功能较强大)
  3. Obfuscator.io Deobfuscator: <mcurl name="https://deobfuscate.io/" url="https://deobfuscate.io/"></mcurl> (专门针对 javascript-obfuscator 工具生成的代码)
  4. Unminify: <mcurl name="https://unminify.com/" url="https://unminify.com/"></mcurl> (一个通用的代码美化和格式化工具)
  5. Online JavaScript Deobfuscator (by dcode.fr): <mcurl name="https://www.dcode.fr/javascript-deobfuscator" url="https://www.dcode.fr/javascript-deobfuscator"></mcurl> (提供多种解码和反混淆选项)

4. 常用混淆方案及其对应的在线反混淆网址

JavaScript 混淆方案多种多样,以下是一些常见的类型及其对应的反混淆策略或工具:

混淆方案类型 特点 常见混淆器/工具 在线反混淆网址/策略
代码压缩/美化 移除空格、换行、注释,缩短变量名,但代码结构不变。 UglifyJS, Terser, Google Closure Compiler <mcurl name="JS Beautifier" url="https://beautifier.io/"></mcurl>, <mcurl name="Unminify" url="https://unminify.com/"></mcurl> (直接美化即可)
字符串编码 将字符串转换为 Base64, Hex, Unicode 转义等形式,运行时解密。 所有主流混淆器都支持 通常需要找到解密函数并手动模拟,或使用 <mcurl name="de4js" url="https://de4js.net/"></mcurl> 等工具尝试自动识别和解密。
变量/函数名重命名 将有意义的名称替换为短的、无意义的名称(如 _0x...)。 所有主流混淆器都支持 代码美化后,手动重命名或使用某些反混淆工具的辅助重命名功能。
控制流平坦化 将代码的线性执行流程转换为一个大的 switch 语句,通过数组索引跳转。 javascript-obfuscator <mcurl name="Obfuscator.io Deobfuscator" url="https://deobfuscate.io/"></mcurl> (专门针对此工具),<mcurl name="de4js" url="https://de4js.net/"></mcurl> (可能支持部分)
自执行匿名函数 (IIFE) 将代码包裹在 IIFE 中,创建私有作用域,防止外部访问。 常见模式 代码美化后,结构会更清晰,但核心逻辑仍需进一步反混淆。
数组混淆 将字符串或其他常量存储在一个数组中,通过索引访问。 javascript-obfuscator <mcurl name="Obfuscator.io Deobfuscator" url="https://deobfuscate.io/"></mcurl>,或手动提取数组并替换索引。
调试器检测/反调试 插入代码检测调试器,如果检测到则阻止代码执行或进入无限循环。 常见于恶意脚本 需要在调试器中绕过或禁用这些检测点。
Domain Lock / Time Lock 代码只在特定域名或特定时间段内执行。 自定义混淆 需要修改或绕过检查逻辑。

重要提示:

  • 没有一个通用的反混淆工具可以解决所有类型的混淆。对于复杂的混淆,通常需要结合多种工具、手动分析和逆向工程技术。
  • 在线工具可能存在安全风险,不要上传包含敏感信息的代码。
  • 理解混淆原理是有效反混淆的关键。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容