解释隐藏代码

我正在尝试查看我玩的游戏中的文件(使用 L u a 编写),以便我可以学习并了解其操作方式。但是在开头有一些定义了函数的代码,这使得一切都无法阅读 - 代码在文件中。

随着代码的执行,您会得到更多“美化”的###代码。是否有人告诉我如何使其可读?

点赞
用户2633423
用户2633423

由于发布的代码不完整,而且可能错乱,我的只是猜测。

似乎整个代码在变量 ungz 中存储了一个“匿名函数”的调用结果:(function() 片段可能在某个地方关闭,例如:

ungz = (function()   -- “匿名函数”
    -- ...
    -- prettify 的定义+帮助数据
    -- ...
    return assert( loadstring(
        prettify [===[
            ...这个长字符串中的混淆代码...
        ]===]
    ) )  -- `loadstring` 和 `assert` 调用的结尾

end)()   --<<-- 注意括号来调用“匿名函数”

在这个函数里面,您可以看到prettify函数的定义和它的帮助数据。可以这样改写它以便更易于理解:

local base_char,keywords=128, {
    "and","break","do","else","elseif","end","false","for",
    "function","if","in","local","nil","not","or","repeat","return",
    "then","true","until","while","read","nbits","nbits_left_in_byte",
    "wnd_pos","output","val","input",};
function prettify(code)
    return code:gsub(
        "["..string.char(base_char).."-"..string.char(base_char+#keywords).."]",
        function (c)
            return keywords[c:byte()-base_char];
        end
    )
end

当应用于字符串时,函数 prettify 将返回相同的字符串,其中任何编码在 base_char-base_char+#keywords 范围内的字符都替换为 keyword 列表中的关键字。

这用于使用 assert(loadstring(prettify [===[xxxx]===])) 来“反混淆”“混淆”的代码,其中将混淆的代码表示为xxxx

补充说明: 注意,将prettify 应用于片段 [===[xxxx]===] 不会返回有意义的代码(将 base_char 值设为 202 会获得更好的结果,尽管不完美)。而且,您必须合并该长字符串中的所有行,并将其替换为普通字符串,即将其转换为 "yyyy",其中 yyyyxxxx,除去所有硬换行符。

可能所有的代码都经过了进一步的预处理。

2013-08-23 13:30:58
用户501459
用户501459

你的file 中包含一个被[===[]===]包围的压缩代码块。压缩仅仅是一个词典编码器,其中关键词映射到单个字节值。解压缩通过prettify(见Lorenzo的帖子)完成。

将压缩代码输入prettify中可获得这段代码(压缩比约为46%),这恰好是另一个解压缩例程!实际上,它似乎是这段代码的最小化版本。

然后,“ungzip”例程被用于处理文件中包含的另一个约150KB的字符串,它扩展为675KB的文本内容。

信不信由你,这个文本也是经过压缩的,使用“ungzip”代码与prettify相同的方案进行压缩,并包含其自己的prettify副本。将这个文本输入prettify可以得到最终的963KB的Lua代码,然后执行。

这里是从第一个允许上传963KB的网站中发表的最终解压缩代码。格式就像从prettify中输出的一样。

2013-08-23 21:39:11
用户15996
用户15996

我是这个工具Squish的作者,它被用来创建了那个文件。

Squish的一些过滤器是可逆的,有些则不是。以下是一个尽可能简单地反转它们的技巧:

在文件顶部粘贴以下代码段:

local _ls = loadstring;
function loadstring(...)
    local f = assert(io.open("unsquished.lua", "w+"));
    f:write((...));
    f:close();
    return _ls(...)
end

然后使用Lua运行该文件。它会在当前目录中生成一个新文件unsquished.lua。这个文件现在是100%纯Lua。

但是,您可能不会发现它很容易阅读,因为所有不必要的空格都已被剥离,一些变量名也被替换为短的替代方案。您可以使用lunadry 可以重新格式化代码,但是原始变量名称无法检索。

此外,该文件包含多个模块合并为一个。您会看到它们的样子如下:

package.preload['modulename']=(function(...)
    --code here--
end)

如果您想提高可读性,可以将它们分开成单独的文件。

希望这有所帮助!

编辑:当您在运行该代码时,务必小心使用该技术处理您不信任的文件。因为它会实际运行它们,如果您不知道它们的功能,这不是一个好主意!

2013-08-23 22:14:27