Интерпретация Скрытого Кода


Я пытаюсь увидеть, что находится внутри этого файла (записанного в L u a) для игры, в которую я играю, чтобы я мог узнать и увидеть, как это делается. Но в начале у него есть определенные функции, которые делают все нечитаемым-код находится в файле.

И по мере того, как код продолжается, вы получаете более "приукрашенное" кодирование с ###. Может ли кто-нибудь сказать мне, как сделать его таким, чтобы он снова стал читаемым?

3 2

3 ответа:

Ваш файл содержит блок сжатого кода между [===[ и ]===]. Сжатие-это просто кодер словаря , где ключевые слова сопоставляются с отдельными байтовыми значениями. Декомпрессия производится через prettify (см. сообщение Лоренцо).

Запуск сжатого кода через prettify дает вам этот код (степень сжатия ~46%), который оказывается другой процедурой декомпрессии! На самом деле, это, кажется, минимизированная версия этого код .

Эта процедура "ungzip" затем используется для обработки другой строки ~150 КБ, содержащейся в файле, которая расширяется до 675 КБ текста.

Верьте или нет, но текст также сжат по той же схеме, что и код ungzip, и содержит свою собственную копию prettify. Прогон этого текста через его prettify дает нам окончательный 963KB Lua, который затем выполняется.

Вот окончательный, распакованный код , опубликованный на первом сайте, который я нашел, что позволит загрузить 963 КБ. Форматирование происходит так же, как и из prettify.

Я автор утилиты 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)

Вы можете разделить их обратно на отдельные файлы, если хотите, чтобы помочь с удобочитаемостью.

Надеюсь, это поможет!

Edit: будьте осторожны при использовании эта техника для файлов, которым вы не доверяете, так как она будет выполнять их по мере выполнения. Не очень хорошая идея, если вы еще не знаете, что они делают!

Поскольку опубликованный код не является полным и, вероятно, перепутан,мои предположения являются только обоснованными.

Похоже, что весь код хранит в переменной 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_char 202 даст лучшие результаты, хотя и не идеальные). Более того вы нужно объединить все строки внутри этой длинной строки и заменить ее обычной строкой, т. е. превратить ее в "yyyy", где yyyy - это xxxx со всеми удаленными жесткими новыми строками.

Вероятно, весь этот код предварительно обрабатывается каким-то другим способом.