python如何解决js逆向混淆?

JavaScript混淆是一种保护网站安全的技术,混淆可将代码进行多种变形和加密,使得 JavaScript 代码变得难以阅读和理解。逆向混淆是混淆中的一种方式。通过逆向混淆,混淆的代码更难被攻击者分析和了解混淆的含义。Python 是一种强大的编程语言,可以用于处理 JavaScript 混淆代码。下面我们就通过一个例子,详细介绍 Python 如何解决 JavaScript 逆向混淆问题。

首先,让我们来了解一下需要解淆的JavaScript代码。它是一个包含各种混淆技巧的javascript文件。混淆后的代码可见以下代码(示例代码来自于 https://obfuscator.io/):

var _0x413c=['foo','bar','baz','hello\x20world!','log'];(function(_0x30fc94,_0x17c46f){var _0x2ff54f=function(_0x50c0f){while(--_0x50c0f){_0x30fc94['push'](_0x30fc94['shift']());}};_0x2ff54f(++_0x17c46f);}(_0x413c,0x1e7));var _0x4073=function(_0x4124e5,_0x45130a){_0x4124e5=_0x4124e5-0x0;var _0xa28e27=_0x413c[_0x4124e5];return _0xa28e27;};function[_0x4073('0x2')][_0x4073('0x4')](){console[_0x4073('0x3')](_0x413c[0x2]);}console[_0x4073('0x3')](_0x413c[0x3]);

看到上面的代码,可能让我们不得不重新思考:

变量使用短、无意义的名称
压缩过的代码难以阅读,代码几乎没有缩进
混淆代码中没有注释
字符串有编码
函数定义被压缩成一行
我们可以使用 Python 编写脚本进行解密。这里我们采用字符串查找和分割、正则表达式、AST 分析等技术。尽管某些混淆技术会使解混淆变得复杂,但我们可以通过一些简单的技巧来解决大多数混淆问题。

下面是我们对这个JavaScript混淆文件的解淆步骤:

1. 如果需要,使混淆代码可读
首先,我们需要把代码中的编码还原为它们对应的字符。这可以通过正则表达式和 Python 的 Unicode 编/解码来实现。以下是一个 Python 工具函数,可以将字符串中的字符编码转换为可读的字符:

import re

def decode_string(encoded_str):
    return re.sub(r'\\x([a-fA-F0-9]{2})', lambda m: chr(int(m.group(1), 16)), encoded_str)
现在,在代码中使用 decode_string 函数,将所有 \x 编码的字符解密并重写代码:

with open('MixedCodeObfuscated.js', 'r', encoding='utf-8') as f:
    content = f.read()

pattern = re.compile(r'(\\x[A-Za-z0-9]{2})')
matches = pattern.findall(content)

for match in matches:
    content = content.replace(match, decode_string(match))

print(content)


在上面的 Python 代码中,我们将 MixedCodeObfuscated.js 中的混淆代码加载到 content 变量中。然后,定义了一个正则表达式类型的pattern,用于匹配全部的"\x"编码格式。再通过for循环结构把字符码转换为对应的可读的字符。最终,输出解密后的内容。现在,我们已经删除了所有编码字符,使混淆的JavaScript 代码更易于阅读和理解。

var _0x413c = ['foo', 'bar', 'baz', 'hello world!', 'log'];

(function (_0x30fc94, _0x17c46f) {
    var _0x2ff54f = function (_0x50c0f) {
        while (--_0x50c0f) {
            _0x30fc94['push'](_0x30fc94['shift']());
        }
    };
    _0x2ff54f(++_0x17c46f);
}(_0x413c, 0x1e7));

var _0x4073 = function (_0x4124e5, _0x45130a) {
    _0x4124e5 = _0x4124e5 - 0x0;
    var _0xa28e27 = _0x413c[_0x4124e5];
    return _0xa28e27;
};

function logBaz() {
    console[_0x4073('0x3')](_0x413c[0x2]);
}

console[_0x4073('0x3')](_0x413c[0x3]);


2. 重命名函数和变量
变量名和函数名通常是混淆代码中的另一个问题。混淆器通常使用短、无意义的名称来给变量和函数命名,例如 _0x413c 和 _0x4073。这使得代码的阅读和理解变得更加困难。为了重命名函数和变量,我们需要对代码进行解析,并对变量赋予更有意义的名称。

还有一种变量命名方式是使用更有语义的名称,例如,由于在示例混淆文件中有一个函数名是 logBaz,我们可以假设它与 baz 变量相关联。因此,我们可以将其重命名为 logImportantWord。

对于变量和参数名称,我们还可以使用后缀来表示变量和参数的类型。例如,strFoo 表示它是一个字符串类型。

以下是一个 Python 脚本,用于重新命名混淆代码中变量和函数:

import ast
import random
import string
import re

def get_random_name(length):
    chars = string.ascii_lowercase
    return ''.join(random.choice(chars) for i in range(length))

def rename_vars(code):
    tree = ast.parse(code)
    used_names = [node.id for node in ast.walk(tree) if isinstance(node, ast.Name) and not isinstance(node.ctx, ast.Store)]
used_names = set(used_names)

for node in ast.walk(tree):
    if isinstance(node, ast.FunctionDef):
        if node.name.startswith('_'):
            continue
        new_name = get_random_name(8)
        while new_name in used_names:
            new_name = get_random_name(8)
        node.name = new_name
        used_names.add(new_name)
    elif isinstance(node, ast.Name) and not isinstance(node.ctx, ast.Store):
        if len(node.id) < 3 or node.id.startswith('_'):
            continue
        new_name = get_random_name(8)
        while new_name in used_names:
            new_name = get_random_name(8)
        node.id = new_name
        used_names.add(new_name)

return ast.unparse(tree)
with open(‘MixedCodeObfuscated.js’, ‘r’, encoding=‘utf-8’) as f:
content = f.read()

重命名变量和函数
content = rename_vars(content)

输出解密和重命名后的代码
print(content)


在上面的 Python 脚本中,我们首先定义了一个名为 `get_random_name` 的函数,它返回指定长度的随机字符串。接下来,我们使用 Python 的抽象语法树(AST)模块分析了代码。在代码分析过程中,我们提取了每个变量的名称,以便我们可以选择一个新名称来重命名它们。我们使用 `get_random_name` 函数生成一个新的、唯一的名称,并将其分配给变量或函数。最后,我们返回一段新的代码,其中所有变量和函数都被重命名。

那么,重命名之后,我们来看一下解密后的 JavaScript 代码:

var strFoo = ['foo', 'bar', 'baz', 'hello world!', 'log'];

(function (strBaz, intEel) {
    var funcFish = function (intHam) {
        for (--intHam; intHam;) {
            strBaz['push'](strBaz['shift']());
        }
    };
    funcFish(++intEel);
}(strFoo, 487));

var funcImportantWord = function (intCow, ocrJim) {
    intCow = intCow - 0x0;
    var strZoo = strFoo[intCow];
    return strZoo;
};

function logImportantWord() {
    console[funcImportantWord('0x3')](strFoo[0x2]);
}

console[funcImportantWord('0x3')](strFoo[0x3]);


可以看到,所有变量和函数现在都被赋予更有意义的名称,这使得代码更易于阅读和理解。

3. 恢复代码结构
JavaScript 代码混淆通常会改变代码的结构。例如,混淆器可以交换条件语句的顺序、使用三元运算符或条件语句来替代简单赋值语句等。为了使代码更易于阅读和修改,我们可以使用 Python 和 JavaScript Beautifier 库来还原代码的结构。JavaScript Beautifier 可以格式化代码,添加适当的缩进和换行符,使代码更清晰易读。以下是一段示例代码,说明了如何使用 JavaScript Beautifier 还原代码的结构:

import jsbeautifier

def format_code(code):
    options = jsbeautifier.default_options()
    options.indent_size = 4
    options.indent_char = ' '
    options.preserve_newlines = True
    return jsbeautifier.beautify(code, options)

with open('MixedCodeObfuscated.js', 'r', encoding='utf-8') as f:
    content = f.read()

# 解密和重命名代码
content = decode_code(content)
content = rename_vars(content)

# 格式化代码
content = format_code(content)

# 输出解密、重命名和格式化后的代码
print(content)


在上面的示例代码中,我们调用 jsbeautifier.beautify() 函数,并设置了适当的选项来格式化代码。最后,我们返回格式化后的代码。

4. 解密 JavaScript 没那么简单!
需要说明的是,在实践中,解密 JavaScript 代码并不总是如此简单直接。混淆器可以使用各种技巧,使代码更加混淆和难以理解。例如,混淆器可以使用以下技术:

控制流平坦化:这是一种技术,用于将分支结构展平为一系列条件语句,使得代码难以阅读。
字符串加密:混淆器可以将字符串编码,并将其解码为字符数组,以使代码更难以理解。例如,可以使用 Base64、RC4 等加密技术来加密字符串。
基于 AST 的混淆:混淆器可以分析代码抽象语法树,并使用各种技术来重构代码,使其难以理解和修改。
在这样的情况下,解密 JavaScript 代码需要更高级的技术和更深入的理解。可能需要使用自定义脚本、反混淆器和各种 JavaScript 分析和调试工具。

此外,在尝试解密混淆 JavaScript 代码时,需要注意一些安全问题。如果您不是代码的所有者或授权的维护者,请不要尝试破解代码。将黑客工具用于未经授权的代码解密可能会涉嫌违法行为,应该遵守法律和道德准则。

总结:

以上是 Python 解密 JavaScript 逆向混淆的初步介绍。在实践中,解密混淆的 JavaScript 代码需要更深入的理解和高级技术。但是,通过 Python 脚本、正则表达式、AST 分析和 JavaScript Beautifier,我们可以为大多数混淆技术找到解决方案,并使代码更易于阅读和理解。在尝试解密混淆 JavaScript 代码时,请注意安全问题,遵守法律和道德准则。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

然然学长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值