Гайд Crack/Реверсинг (ответ на удаленную тему / пост восстановлен)

asdzxcjqwe

¯\_(ツ)_/¯
Автор темы
Друг
621
704
Ппц вы тему тянете, он же и задаёт вопрос, как это сделать?
Каждый как-то учился, может где читал, скинь ссылку, что смотрел, ты же тоже не родился и уже знал это, как-то ты получал знания.
на это может уйти целая статья, но не факт, что они что-нибудь поймут, я думаю нужно начинать ранее, где-то еще с работы с памятью

он скачал x64dbg и спрашивает как ему научится реверсить
да, потому что изначально ввели в заблуждение

а тогда с луа как? Например у скрипта лицуха есть на сервере. Либо привязка по компу, какими прогами можно все это дело взломать? Например если скрипт без защиты
любой hex редактор для патчинга,
любой язык тебе по душе для автоматизации,
luajit чтобы перевести байткод в псевдоасм,
в папке jit находятся луа файлы, которые можно редачить, чтобы было удобнее изучать преобразованный байткод

http://wiki.luajit.org/Bytecode-2.0
https://github.com/LuaJIT/LuaJIT/blob/v2.1/src/lj_bc.h#L59 - опкоды по порядку, начиная с нуля (для 2.1)
https://github.com/LuaJIT/LuaJIT/blob/v2.0/src/lj_bc.h#L59 - для 2.0
кстати, каждый опкод состоит из 4 байтов.

можно скомпилить простой код, чтобы показать пример:
Lua:
local sampev = require("lib.samp.events")

enabled = false

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then
        return
    end

    while not isSampAvailable() do
        wait(100)
    end

    license = false -- будем считать, что соединились с сервером и он сказал, что лицы нет

    sampAddChatMessage("тестовый скрипт загружен", -1)
    sampAddChatMessage("нельзя просто так взять и не вставить свое сообщение при входе в игру", -1)
    sampAddChatMessage("больше строк, чтоб прям всех раздражать", -1)
    sampAddChatMessage("используйте команду /test", -1)

    if not license then
        sampAddChatMessage("ну крч привязка отсутствует, надо купить", 0xdd0000)
        thisScript():unload()
    end

    sampRegisterChatCommand("test", function ()
        enabled = not enabled
        sampAddChatMessage(string.format("тестовая функция которая ничего не делает %s", enabled and "{00dd00}включена" or "{dd0000}отключена"), -1)
    end)

    wait(-1)
end

я ввел /test в игре, но ничего не произошло, так как скрипт уже выгружен:

B2t8YvA.png


в таком случае достаточно через hex редактор в luac файле все строки "unload" заменить, например, на "resume" (они одинаковы по размеру - 6 символов)
после патчинга в игре будет писать, что скрипт не привязан и был выгружен, но на самом деле он продолжит работу (такой способ не всегда сработает из-за дополнительных проверок)

Ha1wZ7a.png


посложнее:
Lua:
local sampev = require("lib.samp.events")

enabled = false

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then
        return
    end

    while not isSampAvailable() do
        wait(100)
    end

    license = false -- будем считать, что соединились с сервером и он сказал, что лицы нет

    sampAddChatMessage("тестовый скрипт загружен", -1)
    sampAddChatMessage("нельзя просто так взять и не вставить свое сообщение при входе в игру", -1)
    sampAddChatMessage("больше строк, чтоб прям всех раздражать", -1)

    if not license then
        sampAddChatMessage("ну крч привязка отсутствует, надо купить", -1)
        return -- завершаем выполнение скрипта (return в main)
    end

    sampAddChatMessage("используйте команду /test", -1) -- если попали сюда, значит прошли проверку (кэп)

    sampRegisterChatCommand("test", function ()
        enabled = not enabled
        sampAddChatMessage(string.format("тестовая функция которая ничего не делает %s", enabled and "{00dd00}включена" or "{dd0000}отключена"), -1)
    end)

    wait(-1)
end

можно использовать любой декомпилятор, чтобы лучше понимать, что происходит (конечно, если код не обфусцирован, иначе всё сложнее)
если всё норм, то после декомпиляции можно увидеть что нам мешает запустить скрипт

kOiwCDF.png


после чего можно заглянуть в байткод, преобразованный в псевдоасм, используя luajit -blg

Rg54OBF.png


этот return находится по адресу 0x1a8 в luac файле, а прыжок на него происходит с 0x170
по адресу 0x170 заменим прыжок с 0xd4 на 0xa0 (это 0 шагов вперед)

откроем luac файл через hex редактор и заменим 32 00 0D 80 на 32 00 00 80
третий байт значит, что мы никуда не прыгаем, по сути этот прыжок становится нопом

IQv6Tii.png


либо можно заменить условие с if license == false на if license == true, но такой скрипт будет работать только у тех, кто не имеет лицензии, в этом тупость такого кряка, поэтому предпочитаю сразу перепрыгнуть с 0x154 на 0x174 (в самом прототипе это 0xA0)
тогда по адресу 0x154 заменяю опкод на JUMP (0x58), который в hex будет выглядеть так: 58 02 ?? 80, где третий байт это сколько опкодов нужно перепрыгнуть. отсчитаем что надо перепрыгнуть 7 опкодов, значит это будет 58 02 07 80

после повторного листинга байткода это выглядит так:

IRRz8u2.png


и в игре:

omXtSG3.png


также можно перепрыгнуть все эти надоедливые сообщения при запуске игры, для этого тоже можно добавить джамп где-нибудь там выше

s5Ol9sc.png


возможно, это всё можно было сделать куда проще, но это всё, что я знаю в реверсинге luajit
это всё основы основ и конечно грамотные авторы скриптов добавляют много проверок в разных участках кода + криптуют/обфусцируют, поэтому над грамотно собранными скриптами либо придется посидеть, либо забить и не тратить своё время

upd: мой декодер - https://yadi.sk/d/XBYT5Rn5ymS2oA (просто перетащить luac на батник)

upd 2: более стабильный листер байткода (которому уже больше года) - https://yadi.sk/d/f1MUO0RWxdlxxw
использование: перетащить скрипт на decompiler.py и выбрать пункт 3
 

Вложения

  • test.lua
    1 KB · Просмотры: 42
  • test-compiled.luac
    818 байт · Просмотры: 68
  • test-patched.luac
    818 байт · Просмотры: 23
  • test-patched-no-messages.luac
    818 байт · Просмотры: 27
  • test-bytecode.txt
    4.7 KB · Просмотры: 56
Последнее редактирование:

imring

Ride the Lightning
Всефорумный модератор
2,353
2,512
либо можно заменить условие с if license == false на if license == true
либо выдать license значение true
оффсет 00000110
было: 2B 00 01 00
стало: 2B 00 02 00

если кто не понял, что за число, то вот:
pri: primitive type (0 = nil, 1 = false, 2 = true)
 
  • Нравится
Реакции: mzxer и asdzxcjqwe

asdzxcjqwe

¯\_(ツ)_/¯
Автор темы
Друг
621
704
либо выдать license значение true
оффсет 0000011C
было: 2B 00 01 00
стало: 2B 00 02 00

если кто не понял, что за число, то вот:
pri: primitive type (0 = nil, 1 = false, 2 = true)
да, но это только в нашем примере, а в больших скриптах среди кучи переменных, причем с затертыми именами, мы вряд ли когда-нибудь отыщем ту самую)
+ никто не присваивает true/false, обычно в них присваивают ответ от сервера
+ переменные часто изменяются по всем участкам кода (например, связь с сервером по таймеру)
поэтому искать условие легче, чем переменную, но да, это конечно как вариант, где-то может сработать
 
  • Нравится
Реакции: k1zn