Перейти к содержанию

A1t0r

Ветераны
  • Постов

    351
  • Зарегистрирован

  • Посещение

  • Победитель дней

    39

Сообщения, опубликованные A1t0r

  1. Итак, Adventure Island, первая часть. так и не прошёл в детстве, хоть сейчас отыграюсь)))

    Проходим до конца уровня и сохраняемся. Открываем RAM Search и ищем единичку(первый уровень). Проходим на 2-й и ищем двойку. Нету. Хм. Попробуем на 1-м уровне поискать ноль, а на втором единицу. Находится десяток адресов, но интересный первый 0038. Ставим в Debugger'e бряк на запись по этому адресу, вываливаемся по адресу 815B:

    00:815B:E6 38     INC $0038 = #$00  

    это увеличение номера round'а. Запомнили место, пригодится если надо будет прыгнуть на следующий уровень.

    Идем ниже по коду. В 0037 номер area, запомнили. Идём дальше. Вот он прыжок на начало уровня:

    00:816F:4C 9A 80  JMP $809A

    Теперь можно писать скрипт.

     

    Напишем функцию обратного вызова для нажатия на кнопку перехода:

    cheats = { --название таблицы с функциями обратного вызова, пока только одна функция пусть будет "toLevel"									["toLevel"] = function(...) --в функцию передаются некоторые параметры					local val, area, round = {...}, nil, nil --пишем их в таблицу val, а также заведём локальные переменные area и round					area, round = tonumber(val[1]), tonumber(val[2]) --переписываем параметры в соответствующие переменные                                        ----------------------------------                                        --если переход запускается из меню                                        memory.writebyte(0x003F, 3) --устанавливаем кол-во жизней                                        memory.writebyte(0x0076, 10) --сытость                                        memory.writebyte(0x0528, 10) --сытость                                        memory.writebyte(0x0077, 0xFF) --сытость                                        ---------------------------------					if (area == 0) or (round == 0) then --если любой аргумент равен 0 будем прыгать на след. уровень						memory.setregister("pc", 0x815B) --прыгаем на место увеличения round, дальше игра сама разберётся						print("Jumped to next level") --печатаем в консоль					else --если переход на конкретный уровень						memory.writebyte(0x0037, area-1) --записываем в area и round значения						memory.writebyte(0x0038, round-1) --на 1 меньшие						memory.setregister("pc", 0x809A) -- и прыгаем на начало уровня						print("Jumped to area "..area..", round "..round) --печатаем для отладки					end 				end}

    Теперь напишем интерфейс и зададим функцию обратного вызова для кнопки:

    function winDraw()	-- переход на уровень	levelSpinArea = iup.text{ --спиннер для area 						spinmin = 0, --ограничиваем значения					spinmax = 8, --от 0 до 8					spin = "YES", 					readonly = "YES" --только чтение(от шаловливых ручек)				}	levelSpinRound = iup.text{--спиннер для round					spinmin = 0,					spinmax = 4, 					spin = "YES", 					readonly = "YES"				}		levelButton = iup.button{					title = "GO", --надпись на кнопке					action = function(self) --функция обработки для кнопки, передаём два параметра								cheats["toLevel"](levelSpinArea.spinvalue, levelSpinRound.spinvalue)							end				}					levelLabel = iup.label{ --надпись с пояснением как пользоваться					title = "if (area or round) = 0 then jump to next level"				}		level = iup.frame{ --пространство обведённое рамочкой				title = "To area(1-8)        round(1-4)",				iup.vbox{ --вертикальный контейнер для элементов					iup.hbox{ --внутри горизонтальный контейнер для элементов						levelSpinArea, --пихаем спиннер для area						levelSpinRound, --пихаем спиннер для round						levelButton --кнопку					},					levelLabel --ну и надпись ниже				},				size = "85X20" --размер фрейма			}		dialogs = dialogs + 1 --увеличиваем на 1 диалог для обработки	handles[dialogs] = iup.dialog{ --и создаём его		title="Adventure Island Trainer +1 by A1t0r", --заголовок окна		resize = "NO", --без ресайза		size = "220X50", --размер окна		iup.hbox{			iup.vbox{				level --и вставляем наш level jump			}		}	}		handles[dialogs]:show() --показываем окноendwinDraw() --выполнить функцию вышеwhile (true) do 	FCEU.frameadvance() --нарисовать кадр игрыend

    Теперь скрипт полностью. Когда напишу (если напишу) полный трейнер, выложу в Файлы. Или drs36 напишет для практики)

    --[[Адреса игровых значений:0x0037 - area0x0038 - roundИнтересные места в коде игры:0x815B - увеличение уровня на 10x809A - начало уровня]]--require("auxlib")--таблица обратных вызовов(callback)cheats = {["toLevel"] = function(...)local val, area, round = {...}, nil, nilarea, round = tonumber(val[1]), tonumber(val[2])memory.writebyte(0x003F, 3)memory.writebyte(0x0076, 10)memory.writebyte(0x0528, 10)memory.writebyte(0x0077, 0xFF)if (area == 0) or (round == 0) thenmemory.setregister("pc", 0x815B)print("Jumped to next level")elsememory.writebyte(0x0037, area-1)memory.writebyte(0x0038, round-1)memory.setregister("pc", 0x809A)print("Jumped to area "..area..", round "..round)endend}function winDraw()--ПОДГОТОВКА ЭЛЕМЕНТОВ ИНТЕРФЕЙСА И ЛОГИКИ-------------------------------------------- переход на уровеньlevelSpinArea = iup.text{spinmin = 0,spinmax = 8,spin = "YES",readonly = "YES"}levelSpinRound = iup.text{spinmin = 0,spinmax = 4,spin = "YES",readonly = "YES"}levelButton = iup.button{title = "GO",action = function(self)cheats["toLevel"](levelSpinArea.spinvalue, levelSpinRound.spinvalue)end}levelLabel = iup.label{title = "if (area or round) = 0 then jump to next level"}level = iup.frame{title = "To area(1-8) round(1-4)",iup.vbox{iup.hbox{levelSpinArea,levelSpinRound,levelButton},levelLabel},size = "85X20"}dialogs = dialogs + 1handles[dialogs] = iup.dialog{title="Adventure Island Trainer +1 by A1t0r",resize = "NO",size = "220X50",iup.hbox{iup.vbox{level}}}handles[dialogs]:show()endwinDraw()while (true) doFCEU.frameadvance()end
    • Плюс 4
  2.  

    В общем я решил по настроению сделать пошаговую инструкцию для новичков по взлому игр Dendy, NES и Nintendo. И так приступим...  :sleep:

    1: Скачиваем с интернета эмулятор FCEUX v2.2.2

     

    Осталось научиться писать трейнеры в нём же (на Lua с iup)

    • Плюс 1
  3. В случае с E9 - прыжок записывается как разница между текущим адресом и адресом, куда надо прыгнуть.

    Согласен, только разница между последним байтом инструкции и куда прыгнуть, а длина инструкции прыжка 5 байт. Если вперед, то всё просто, назад - нужно учитывать эти 5 байт. Проверено на себе)

  4. Я пишу трейнер на C#, он должен сделать иньекцию кода, но когда я записываю JMP ( 0xE9 ) и адрес куда прыгнуть ( 0x004121E2 ) , то записывается в MemoryViewer нужный адрес, а на самом деле прыгает в совершенно другой адрес.

    Подскажите как правильно записывать адреса в память.

     

     

     

    Всё зависит от первого байта команды. Ты используешь E9 - это близкий ОТНОСИТЕЛЬНЫЙ переход, смещение 4-байтовое. В этом случае опкоды для перехода на 0x004121E2 такие:

    E9 F6 FF FF FF 

    Если указать смещение 00 00 00 00, то будет произведён переход на след. инструкцию. Смещение считается от последнего байта данной инструкции, т. е. 004121EB. Чтобы перейти на E2 нужно сделать: от последнего байта инструкции до первого 4 шага(будем на E7) + 5 шагов до E2. Смещение FF FF FF FF указывает на последний байт команды (004121EB). 

    Итого: (FF - 4) - 5 = FB - 5 = F6.

     

    Для экономии места лучше использовать короткий прыжок (Short 0xEB) со смещением -128 +127. Опкоды такие

    EB F9

    А если ты хочешь писать абсолютный адрес, тогда прыжок имеет код 0xEA(jmp FAR). Опкод

    EA E2 21 41 00

    Если хочешь почитать, например, здесь, начиная с раздела "Команда безусловного перехода JMP(Переход, прыжок =”JUMP”)"

  5.  

    Дела идут, контора пишет) 

    Нашел адрес очков способностей. Его тип - byte. Я хочу чтобы значение очков способностей было всегда 100 (максимальное значение), но как это сделать с byte?

    P.s. вот так это выглядит:

    originalcode:mov [ecx+000006E1],al

     Самое простое решение выглядит так:

    mov [ecx+000006E1],64

    Но можно поискать в памяти по соседству ячейку со значением 100, если такая имеется, то считывать это значение в al. Смотря как выглядит код считывания значения.

  6. A1t0r, вот.

    Что-то нашел, но пока нет времени разбираться.

     

    Если нужно создавать библиотеки для вставки их в CE, то подобные приблуды от сторонних разработчиков не подойдут. Необходимо собрать динамическую библиотеку из исходников lua версии 5.1, и использовать для своей получившийся файл .lib, как я уже писал в 13 посте. Если всё сделано правильно, то можно сделать файл .def в котором должны будут написаны экспортируемые функции. Скачай обычные исходники вместе с примерами, пройдя по ссылке выше(в конце статьи ссылка на Lua_1Step.rar). В файле lua.pas найдёшь апишные функции, а описание их можно читать на сайте lua.org (инглиш, что поделаешь) или lua.ru (русский).

    • Плюс 1
  7. Во! Работает на 64-битной версии CE, а на 32 - нет.

    Нужен способ реализации такой dllки на Delphi, исходник в студию))

     

    Извиняйте пишу на C. Для 32-битной версии нужно при сборке подключать 32x версию.

    main.cpp:

    main.h:

     

    Но нужен ещё файл для импорта библиотеки lua5.1-32 или lua5.1-64 (.a для gcc, .lib для C компиляторов). Библиотеку нужно собирать из исходников луа соответствующей версии.

    #include "main.h"#include <lua.hpp>int DLL_EXPORT Symma(lua_State* L){    if (lua_gettop(L)>0) {        if (lua_isnumber(L, 1) && lua_isnumber(L, 2)) {            const float a = lua_tonumber(L, 1);            const float b = lua_tonumber(L, 2);            lua_pushnumber (L, lua_Number(a+);            return 1;        }        else            MessageBoxA(0, "Not number!", "DLL Message", MB_OK | MB_ICONINFORMATION);    }    else        MessageBoxA(0, "No arguments!", "DLL Message", MB_OK | MB_ICONINFORMATION);    return 0;}extern "C" BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){    return TRUE;}
    #ifndef __MAIN_H__#define __MAIN_H__#include <windows.h>#include <lua.hpp>#ifdef BUILD_DLL    #define DLL_EXPORT __declspec(dllexport)#else    #define DLL_EXPORT __declspec(dllimport)#endif#ifdef __cplusplusextern "C"{#endifint DLL_EXPORT Symma(lua_State* L);#ifdef __cplusplus}#endif#endif // __MAIN_H__
  8. Ты издеваешься что ли сейчас? Ты мой пост в этой теме читал вообще?

     

    Естественно, но только этого недостаточно. Нужно ещё уметь работать со стеком луа. Простые вызовы сишных функций ни к чему не приведут, ну разве что к ошибке.

     

    Сразу видно, даже не заглядывал в программу. Что-то по той ссылке нету примера с передачей параметра в функцию. Без состояния стека можно только вызывать отдельные функции MessageBox, например, таким образом никак не получит извне строку для вывода.

    Программа сообщает о неопределенной ошибке.

     

    Поясните, что нетак!

     

    Текст неопределённой ошибки можно увидеть?

  9. Поговорил с одним человеком и получилось сделать подключение своей дллки. Использовал Codeblocks, компилятор MinGW. Библиотека собрана для 64-битной версии CE, можно для 32. Внутри архива .dll, .h и .cpp. Реализовал одну функцию printString, выводящую в messagebox'е переданную ей строку.

    Для подключения к скрипту CE нужно написать следующее:

    printString = package.loadlib("D:\\load_my_Lib64.dll", "printString") --загрузка функции из библиотекиprintString("123") --вызов для строкиprintString(123)--вызов для числа

    Путь написал для примера, главное ставить \\ в пути.

     

    Версия CE 6.4. Главное чтобы в корне были библиотеки луа 5.1

     

    Пароль от архива: gamehacklab.ru

     

    Будет больше времени и интерес к теме напишу подробнее.

    DLLka+CPPH.rar

    • Плюс 1
  10. Как минимум

    dd (float)150

    находится в исполняемом коде. Нужно вынести, например так

    newmem:originalcode:fsub dword ptr [subst] fstp dword ptr [eax] push esimov ecx,ediexit:jmp returnheresubst:dd (float)150"Darksiders2.exe"+3B7857:jmp newmemreturnhere:
  11. Прошло 2 года, надо всё-таки поставить точку в теме.

    Вот таблица и трейнер на бессмертие и много бесконечного золота.

    Бессмертие получилось сделать только привязавшись к значению золота - оно не равно 0 только у перса. Найти ID не удалось, но и так работает) Хотя цепочки к значениям золота, опыта и здоровья найти удалось. Если что можно переписать скрипт на бессмертие. чтобы сравнивать значение регистра с содержимым последнего элемента в цепочке указателей.

     

    Версия 2.28 rus

     

    Sacred Underworld v2.28rus by A1t0r(CT and EXE).rar

    • Плюс 1
  12. Привет A1t0r мене не лень анализировать через АНАЛИЗ ДАННОЙ СТРУКТУРЫ просто он бывает без полезен в примом смысле этого слова вот я и прошу вас помочь мене найти это смешение или ID игрока не используя АНАЛИЗ ДАННОЙ СТРУКТУРЫ ведь есть другие способы вот я и прошу их показать на примере пожалуйста

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

    Откопал у себя пример, очень простой. Взлом UnEpic. Цепочка очень маленькая, но принцип будет понятен.

    00492345:fst dword ptr [esi+000003C0] - сохраняется новое значение жизни, используется и для игрока и для противника

    Если лезть и анализировать структуру лень - ищем указатель в статической памяти.

    Когда нашли эту инструкцию при ранении игрока, смотрим чему равно esi и ищем это значение в памяти.

    В данном случае сразу найдётся указатель в статике.

    И получается такой скрипт

    newmem:push eax - сохр.mov eax, [00B6A2C0] - считываем указатель по найденному адресуcmp esi, eax - сравниваем его со значением esipop eaxje exit - если будет запись значения в структуру игрока, то выходимoriginalcode:fst dword ptr [esi+000003C0] - иначе раним противникаexit:jmp returnhere

    Но не всегда бывает так просто.

    Предположим, после поиска значения esi нам выдало несколько адресов не статичных. Тогда берём любой, ставим бряк на доступ и продолжаем игру. Чаще всего достаточно просто зайти и выйти, т.к. доступ производится множество раз, если только указатель не оказался "левым", тогда пробуем другой. Если что-то выскочило, смотрим как инструкция обращается к нашему указателю. Например, пусть будет mov eax,[ecx+24]. Берем значение ecx и ищем дальше, повторяем пока не найдём статичный адрес.

    Для данного случая скрипт будет такой(удлиню нашу цепочку, в 00B6A2C0 будет ecx)

    newmem:push eax - сохр.mov eax, [00B6A2C0]mov eax, [eax+24] - дополнительное звено в нашей цепиcmp esi, eaxpop eaxje exit originalcode:fst dword ptr [esi+000003C0]exit:jmp returnhere
    • Плюс 1
  13. Привет всем все таки придется попросит мене вас что бы вы на примере показали пожалуйста как можно еще найти это смешение или ID игрока для различия свой чужой не используя АНАЛИЗ ДАННОЙ СТРУКТУРЫ по кажите пожалуйста на примере.

    Тут A1t0r говорил можно что ни бут придумать покажите пожалуйста на примере что именно не используя АНАЛИЗ ДАННОЙ СТРУКТУРЫ как без него можно найти смешения или как там еще говорят ID игрока 

    Начнём с того, что "говорил что-нибудь придумать" это относится к анализу структуры и привязке к какому-то значению. Если лень анализировать или не получается привязаться, то можно попробовать вычислить цепочку указателей и проверять фильтром, пытается ли в данный момент инструкция писать, например, в ячейку со здоровьем игрока.

  14. Версия игры 1.0.

     

    Надо бы собрать всё воедино, что было сделано для данной игры, хотя бы в виде ссылок.

    Скрипты на бессмертие и бесконечные вещи.

    Первая версия программы для модификации параметров персонажа CharModer.

     

    Во второй версии немного дополнил список параметров.

    Risen 3 - Titan Lords CharModer v2 by A1t0r (CT and EXE).rar

    • Плюс 1
  15. Бесконечные вещи (использовать на свой страх!!!):


    [ENABLE]
    alloc(newmem,2048)
    label(returnhere)

    newmem:
    lea ecx,[esi+04]
    cmp dword ptr[esi+24],eax
    jg returnhere
    mov [esi+24],eax
    jmp returnhere

    "Risen3.exe"+33FFD8:
    jmp newmem
    nop
    returnhere:

    [DISABLE]
    dealloc(newmem)
    "Risen3.exe"+33FFD8:
    lea ecx,[esi+04]
    mov [esi+24],eax

    • Плюс 1
  16. Спасибо Большое A1t0r и keng

    Еще вопросик объяснити мене дураку я не как понять не могу для меня это очень важно я знаю как писать с крипты зная как делать не сложные фильтры но до сих пор не могу понять вот есть инструкция она отвечает за все и за жизни моего игрока и за жизни врага как сделать фильтр я знаю а вот как найти смешение которое будет различать меня от врага я не могу понять вот я нахожу адрес здоровья моего игрока делаю АНАЛИЗ ДАННОЙ СТРУКТУРЫ ищу значения которые не меняются после перезагрузки игры например у меня 1 значение а у врага 2 это мене понятно вот объясните а если его там нет нет вот просто хоть убейте нет его и все чем я еще могу воспользоватся кроме АНАЛИЗ ДАННОЙ СТРУКТУРЫ что бы найти это смешение или как еще можно найти смещение не используя АНАЛИЗ ДАННОЙ СТРУКТУРЫ мене это учен важно извеняюсь если вопрос не по теме

    Ну чтоб уж так всё серьёзно было, чтобы совсем не за что зацепиться, бывает чертовски редко. Можно цепляться не за конкретное число, а, например, у игрока отлично от 0 у врага 0. Или в структуре игрока указатель ведёт не в пустоту P->00000000. Что-нибудь да можно придумать.

  17. Пожалуйста покажи на примере на каком ни буть скрипте

    Так вот в 8 посте пример

    О_о Risen докачался, ща ломанём)

    Указатель на героя


    [[[Risen3.exe+DD6CC0]+1C]+1С]+X
    X:
    +14 - ближний бой
    +18 - дальний бой
    +1C - проворность
    +20 - влияние
    +24 - выносливость
    +28 - Ловкость
    +2C - магия
    +30 - дух
    +34 - число+20 = макс. здоровье
    +38 - здоровье
    +3C - слава
    +40 - репутация

    Скрипт на бессмертие(вариант с записью 100 здоровья):


    [ENABLE]
    alloc(newmem,2048)
    label(returnhere)
    label(originalcode)

    newmem:
    cmp ebp,0A
    jne originalcode
    mov edi,64
    originalcode:
    mov [esi+ebp*4+10],edi
    mov edx,[esi]
    jmp returnhere

    "Risen3.exe"+2BF4E8:
    jmp newmem
    nop
    returnhere:

    [DISABLE]
    dealloc(newmem)
    "Risen3.exe"+2BF4E8:
    mov [esi+ebp*4+10],edi
    mov edx,[esi]

    • Плюс 1
×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.