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

Заморозка по таймеру


Рекомендуемые сообщения

Есть такая пошаговая стратегия Panzer General. Вот скрипт для максимального числа юнитов:


[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(cycle)
label(returnhere)
label(originalcode)
label(exit)
registersymbol(ZeroAddress)
label(ZeroAddress)
label(cycle)
label(restore)
createthread(newmem)

newmem: //this is allocated memory, you have read,write,execute access
//place your code here
cmp edi,DAA54 //start unit's list
jne originalcode
push edi
push ebx
mov [ZeroAddress],ecx
add edi,1B //1st unit count

cycle:
mov ebx,[ZeroAddress]
add ebx,edi
cmp [ebx],0 //unit exists?
je restore
mov byte ptr [ebx],#30 //max count
add edi,58 //next unit count
push #1000
call sleep
jmp cycle

restore:
pop ebx
pop edi

originalcode:
movzx eax,byte ptr [eax+ecx]
ret

exit:
jmp returnhere

ZeroAddress:
dd 0

"FreeDOCore.dll"+1D4D0:
jmp newmem

returnhere:



[DISABLE]
//code from here till the end of the code will be used to disable the cheat
"FreeDOCore.dll"+1D4D0:
movzx eax,byte ptr [eax+ecx]
ret
dealloc(newmem)
unregistersymbol(ZeroAddress)
//Alt: db 0F B6 04 08 C3

К сожалению данный скрипт срабатывает только один раз при выборе первого юнита в отряде, если писать его без потока. С потоком насколько я понимаю скрипт срабатывает N раз, где N - число юнитов на карте, а потом один хрен работать перестаёт и никакого бессмертия не выходит. И кстати, пока поток повторяется игра зависает... Можно ли как-то переписать скрипт, чтобы он срабатывал без выхода и не завешивал игру?

Ссылка на комментарий
Поделиться на другие сайты

поток пристыковывай не к newmem, ибо туда идет прыжок с оригинальной инструкции, а создай отдельную выделенную память. А еще у тебя получается, игра входит в новую память, и пока всех юнитов не переберет - не успокоится, ибо у тебя цикл выполняется в основном потоке игры, так как прыжок на newmem идет из него. И только потом возвращается в оригинальный код. Точнее по работе с потоками в СЕ тебе Андрей расскажет.

Ссылка на комментарий
Поделиться на другие сайты

1) От потоков, которые работают по циклу даже с задержкой лучше отказываться. Сулит тормозами и вылетами из игры (особенно без проверок адресов есть ли доступ на чтения и запись)

2) Новый поток можно и нужно создавать в отдельной выделенной памяти. Два потока на одном блоке кода выполняться не могут. Они будут ждать друг друга пока один не выйден из блока кода. Тоже самое касается чтения данных в одной области. К сожалению, я не помню размеры этих областей. Эти и другие тонкости должны быть у Рихтера в его мемуарах или MSDN.

Короче.

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

Речь идёт о "Panzer General III - Scorched Earth" (от 2000го года)?

Ссылка на комментарий
Поделиться на другие сайты

Речь вообще шла о первом Панзере, выходившем на приставке Panasonic 3DO в 96 году. Возможно следовало создать тему в разделе о приставках, но вопрос был про потоки, создал тут) Теперь сомнения одолели, возможно в эмуляторе эти потоки работают не так, как в PC-играх? Ну и в эмуле все события в игре обрабатываются одной инструкцией, что в общем то логично для эмулятора...Такой скрипт крашит игру:


[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,256) //2kb should be enough
alloc(thread,256)
createthread(thread)
label(cycle)
label(returnhere)
label(originalcode)
label(exit)
registersymbol(ZeroAddress)
label(ZeroAddress)
label(restore)

newmem: //this is allocated memory, you have read,write,execute access
//place your code here
cmp edi,DAA54 //start unit's list
jne originalcode
push edi
push ebx

thread:
mov [ZeroAddress],ecx
add edi,1B //1st unit count

cycle:
mov ebx,[ZeroAddress]
add ebx,edi
cmp [ebx],0 //unit exists?
je restore
mov byte ptr [ebx],#30 //max count
add edi,58 //next unit count
jmp cycle

restore:
pop ebx
pop edi
push #1000
call sleep
jmp thread

originalcode:
movzx eax,byte ptr [eax+ecx]
ret
exit:
jmp returnhere

ZeroAddress:
dd 0
"FreeDOCore.dll"+1D4D0:
jmp newmem
returnhere:



[DISABLE]
//code from here till the end of the code will be used to disable the cheat
"FreeDOCore.dll"+1D4D0:
movzx eax,byte ptr [eax+ecx]
ret
dealloc(newmem)
dealloc(thread)
unregistersymbol(ZeroAddress)
//Alt: db 0F B6 04 08 C3

Здесь метка cycle никак не влияет на поток thread, не обрывает его?

Ссылка на комментарий
Поделиться на другие сайты

А ещё проще заинжетить DLL.

И там уже сделать поток, и в нём, что типо этого.


for (;;Sleep(50))
{
DWORD* health_addr = .....
DWORD* team_id = ...
if (*team_id == 0) // 0 - id твоей команды
*health_addr = 100;
}

Ссылка на комментарий
Поделиться на другие сайты

Ну да, про DLL тоже была мысль. Но потом решил накатать по быстрому ассемблерный скрипт (как-то им чаще пользуюсь, чем C++) и на удивление с первой попытки без ошибок прописал всем своим юнитам максимум рекрутов. Обрадовался, но радость оказалась преждевременной - чит сработал один раз и никаких значений не заморозил, обидно.. а мне ещё хотелось чит "бесконечный ход", а тут уже одноразовым читом никак не отделаться, нужна заморозка... надо будет попробовать DLL.

Как тут правильно написать? По адресу [[FREEDOCORE.DLL+28370]+0xDAA54] находится имя юнита, а вовсе не указатель на класс. Поэтому в классе поставил char skip[0xDAA54] - а как по другому написать?


DWORD WINAPI Panzer_thread( LPVOID )
{
Unit* localUnit = NULL;
DWORD old_protect = 0;
CreateConsole();
DWORD ZeroAddress = (DWORD)GetModuleHandle(L"FreeDOCore.dll") + 0x28370; // нулевой адрес эмулятора
//DWORD pZeroAddress = *(DWORD*)ZeroAddress;
//DWORD Unit = pZeroAddress + 0xDAA54; // наш класс Unit
if (HIWORD ( ZeroAddress ) )
{
//printf("ZeroAddress = 0x%X\n", pZeroAddress);
//printf("pUnit = 0x%X\n", Unit);
int offsets[1] = { 0x0 };
int* locUnit = ReadPointer(ZeroAddress, offsets, 1);
printf("locUnit = 0x%X\n", locUnit);
localUnit = Unit::Singleton(locUnit); // создаём экземляр игрового класса, но с одним и тем же адресом
printf("UnitName = %s\n", localUnit->UnitName); //вместо имени выводится пустая строка :( ошибочка...

}


class Unit
{
public:
char skip[0xDAA54];
char UnitName[12];
...
};

Ссылка на комментарий
Поделиться на другие сайты

Ну да, про DLL тоже была мысль. Но потом решил накатать по быстрому ассемблерный скрипт (как-то им чаще пользуюсь, чем C++) и на удивление с первой попытки без ошибок прописал всем своим юнитам максимум рекрутов. Обрадовался, но радость оказалась преждевременной - чит сработал один раз и никаких значений не заморозил, обидно.. а мне ещё хотелось чит "бесконечный ход", а тут уже одноразовым читом никак не отделаться, нужна заморозка... надо будет попробовать DLL.

Как тут правильно написать? По адресу [[FREEDOCORE.DLL+28370]+0xDAA54] находится имя юнита, а вовсе не указатель на класс. Поэтому в классе поставил char skip[0xDAA54] - а как по другому написать?


DWORD WINAPI Panzer_thread( LPVOID )
{
Unit* localUnit = NULL;
DWORD old_protect = 0;
CreateConsole();
DWORD ZeroAddress = (DWORD)GetModuleHandle(L"FreeDOCore.dll") + 0x28370; // нулевой адрес эмулятора
//DWORD pZeroAddress = *(DWORD*)ZeroAddress;
//DWORD Unit = pZeroAddress + 0xDAA54; // наш класс Unit
if (HIWORD ( ZeroAddress ) )
{
//printf("ZeroAddress = 0x%X\n", pZeroAddress);
//printf("pUnit = 0x%X\n", Unit);
int offsets[1] = { 0x0 };
int* locUnit = ReadPointer(ZeroAddress, offsets, 1);
printf("locUnit = 0x%X\n", locUnit);
localUnit = Unit::Singleton(locUnit); // создаём экземляр игрового класса, но с одним и тем же адресом
printf("UnitName = %s\n", localUnit->UnitName); //вместо имени выводится пустая строка :(/> ошибочка...

}


class Unit
{
public:
char skip[0xDAA54];
char UnitName[12];
...
};

Смотри мои уроки по реверсингу на C++, их было не мало)

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

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

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