2

我正在尝试查看我玩的游戏的这个文件里面有什么(用Lua写的),这样我就可以学习并看看它是如何完成的。但在一开始,它定义了使所有内容都无法读取的功能 - 代码在文件中。

随着代码的继续,您将使用### 获得更多“美化”的编码。有人可以告诉我如何使它再次可读吗?

4

3 回答 3

5

您的文件包含[===[和之间的压缩代码块]===]。压缩只是一个字典编码器,其中关键字被映射到单个字节值。解压是通过prettify(参见 Lorenzo 的帖子)完成的。

运行压缩代码prettify会给你这个代码(压缩率~46%),这恰好是另一个解压缩程序!事实上,它似乎是该代码的最小化版本。

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

信不信由你,该文本通过与 ungzip 代码相同的方案进行压缩,并包含其自己prettify. 通过它运行该文本prettify会给我们最终的 963KB Lua,然后执行。

这是最终的解压缩代码,发布到我发现的第一个允许上传 963KB 的站点。格式就像它来自prettify.

于 2013-08-23T21:39:11.630 回答
3

我是用于创建该文件的实用程序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-23T22:14:27.080 回答
2

由于发布的代码不完整,并且可能搞砸了,我的只是有根据的猜测。

似乎整个代码在变量中存储了ungz对“匿名函数”的调用结果:(function ()片段可能像这样关闭:

ungz = (function()   -- "anonymous function"
    -- ...
    -- definition of `prettify` + helper data
    -- ...
    return assert( loadstring(
        prettify [===[
            ...obfuscated code in this long string...
        ]===]
    ) )  -- end of `loadstring` and of `assert` calls

end)()   --<<-- note the () to call the "anonymous function"

在此函数中,您可能会看到函数的定义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_char202会给出更好的结果,尽管并不完美)。此外,您必须合并该长字符串中的所有行并将其替换为普通字符串,即将其转换为,"yyyy"其中删除了所有硬换行符。yyyyxxxx

可能所有这些代码都以某种更进一步的方式进行了预处理。

于 2013-08-23T13:30:58.580 回答