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

[Shogun 2: Total War] Бесконечный ход


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

Я что-то потерялся в дебрях вызовов и упёрся в аргумент функции "location_manager().update_positions". Эта функция постоянно работает с позициями.... Внизу есть другая функция, которая может вызывать "подставляемые" функции. Одну функцию может вызвать для бота и совершенно другую для пользователя. По какому принципу это делается нет времени разбирать, т.к. похоже это надолго. Всё-таки надо было ставить бряк на изменение курсора или на клик. Но для этого париться с хуками directX, на это тоже надо какое-то время.

Но у меня есть не плохие новости. Есть же уже готовая таблица Recifense - ещё тот Гуру по таким случаям.


===========================================
Total War - Shogun 2
Game Version : 1.00
Script Version: 1.0
CE Version : 6.0
GM, Ammo, Gold, MP, MSO
23-Mar-2011
By Recifense

===========================================
Total War - Shogun 2
Game Version : 1.00
Script Version: 1.0
CE Version : 6.0
GM, Ammo, Gold, MP, MSO
23-Mar-2011
By Recifense
===========================================
1) God Mode: For all Units and Ships
2) Unlimited Ammo (Arrows, Bombs, etc)
3) Unlimited Movement Points (Army on campaign)
4) Recover troop size when Army moves (Army on campaign)
5) Minimum Gold (On campaign)
6) Player's Current Gold (On campaign)
7) Skill points of selected army's general (On Campaign)

}

[ENABLE]
//=========================================
// Check if script is compatible to this game version
// If false the script will not be loaded

assert(Shogun2.dll+00a63e50,55 8b ec 83 e4 f8)
assert(Shogun2.dll+00c7e770,55 8b ec 83 e4 f8)
assert(Shogun2.dll+01199dc3,8b b7 34 01 00 00)
assert(Shogun2.dll+009e7af3,f3 0f 11 86 40 0f 00 00)
assert(Shogun2.dll+00cf54e0,51 8b 8f a0 03 00 00)
assert(Shogun2.dll+011cb77d,89 8e b0 00 00 00)
assert(Shogun2.dll+00b560d7,8b 43 40)
assert(Shogun2.dll+0046df80,?? ?? 6c 04 00 00)
assert(Shogun2.dll+011ad6bc,?? ?? 0c 1c 00 00)

//=========================================
alloc(MyCode,1024)
//=========================================
// Declaration section
label(_GodMode)
label(_GodM00)
label(_GodM01)
label(_BackGM)
label(_ExitGM)
label(_GodMode1)
label(_GodM10)
label(_GodM11)
label(_BackGM1)
label(_ExitGM1)
label(_MonSel)
label(_BackMS)
label(_MonAmmo)
label(_MonA0)
label(_MonA1)
label(_BackMA)
label(_ExitMA)
label(_GodModeS)
label(_BackGMS)
label(_ExitGMS)
label(_MonSelShip)
label(_BackMSS)
label(_ExitMSS)
label(_GodModeSH)
label(_BackGMSH)
label(_ExitGMSH)
label(_MonGold)
label(_BackMG)
label(_ExitMG)
label(_MonMP)
label(_MonM0)
label(_BackMM)
label(_ExitMM)
label(_MonSelOfficer)
label(_BackMSO)
label(_ExitMSO)
label(pSel)
label(pGold)
label(pOfficer)
label(iEnableGM)
label(iEnableGM1)
label(iEnableGM2)
label(iEnableGMS)
label(iEnableMA)
label(iEnableQR)
label(iEnableMG)
label(iEnableMM)
label(iEnableMTS)
label(iPlayerID)
label(iMinGold)
label(iEAX)
label(iCount0)
label(iCount1)
label(iCount2)
label(iCount3)
label(iCountS)

registersymbol(MyCode)
registersymbol(pSel)
registersymbol(pGold)
registersymbol(pOfficer)
registersymbol(iEnableGM)
registersymbol(iEnableGM1)
registersymbol(iEnableGM2)
registersymbol(iEnableGMS)
registersymbol(iEnableMA)
registersymbol(iEnableQR)
registersymbol(iEnableMG)
registersymbol(iEnableMM)
registersymbol(iEnableMTS)
registersymbol(iMinGold)
registersymbol(iPlayerID)
registersymbol(iCount0)
registersymbol(iCount1)
registersymbol(iCount2)
registersymbol(iCount3)
registersymbol(iCountS)

//=========================================
MyCode:
//=========================================
_GodMode:
mov [iEAX],eax // Save EAX

mov eax,[esp+04] // Get Unit

mov eax,[eax+00000204] // Get pTroop
test eax,eax
jnz _GodM00 // Jump if the pointer is null

mov eax,[eax+0000020c] // Get pShip
test eax,eax
jz _ExitGM // Jump if the pointer is null

mov al,[eax+0000111f] // Get pCommon
cmp al,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGM // Jump if false

inc dword ptr [iCount0]

cmp dword ptr [iEnableGM],0
je _ExitGM // Jump if feature is disabled

jmp _GodM01
//=====
_GodM00:
mov eax,[eax+00000294] // Get pPlayerInfo
test eax,eax
jz _ExitGM // Jump if the pointer is null

mov eax,[eax+04] // Get playerID
cmp eax,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGM // Jump if false

inc dword ptr [iCount1]

cmp dword ptr [iEnableGM],0
je _ExitGM // Jump if feature is disabled

_GodM01:
mov eax,[iEAX] // Restore EAX
ret 0004 // Avoid routine
//-----
_ExitGM:
mov eax,[iEAX] // Restore EAX

push ebp // Original code
mov ebp,esp // Original code
and esp,f8 // Original code
jmp _BackGM // Back to main code

//=========================================
_GodMode1:
mov [iEAX],eax // Save EAX

mov eax,[ecx+00000204] // Get pTroop
test eax,eax
jnz _GodM10 // Jump if the pointer is not null

mov eax,[ecx+0000020c] // Get pShip
test eax,eax
jz _ExitGM1 // Jump if the pointer is null
// Ship Crew
mov al,[eax+0000111f] // Get pCommon
cmp al,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGM1 // Jump if false

inc dword ptr [iCount2]

cmp dword ptr [iEnableGM],0
je _ExitGM1 // Jump if feature is disabled
jmp _GodM11
//Land Soldiers
_GodM10:
mov eax,[eax+00000294] // Get pPlayerInfo
test eax,eax
jz _ExitGM1 // Jump if the pointer is null

mov eax,[eax+04] // Get playerID
cmp eax,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGM1 // Jump if false

inc dword ptr [iCount3]

cmp dword ptr [iEnableGM],0
je _ExitGM1 // Jump if feature is disabled

_GodM11:
mov eax,[iEAX] // Restore EAX
ret 0004 // Avoid routine
//-----
_ExitGM1:
mov eax,[iEAX] // Restore EAX

push ebp // Original code
mov ebp,esp // Original code
and esp,f8 // Original code
jmp _BackGM1 // Back to main code

//=========================================
_MonSel:
mov esi,[edi+00000134] // Original code
mov [pSel],esi
jmp _BackMS // Back to main code

//=========================================
_MonAmmo:
mov eax,[esi+00000294] // Get pPlayerInfo
test eax,eax
jz _ExitMA // Jump if the pointer is null

mov eax,[eax+04] // Get playerID
cmp eax,[iPlayerID] // Is it a Player's Troop ?
jne _ExitMA // Jump if false

cmp dword ptr [iEnableMA],0
je _MonA0 // Jump if feature is disabled

cvtsi2ss xmm0,[esi+00000F44] // Get Maximum Ammo

_MonA0:
cmp dword ptr [iEnableQR],0
je _ExitMA // Jump if feature is disabled

cmp dword ptr [esi+00000dbc],#15
jle _MonA1

mov dword ptr [esi+00000dbc],#15

_MonA1:
cmp dword ptr [esi+00000dc0],#15
jle _ExitMA

mov dword ptr [esi+00000dc0],#15

_ExitMA:
comiss xmm1,xmm0 // Update EFLAGS
movss [esi+00000F40],xmm0 // Original code
jmp _BackMA // Back to main code

//=========================================
_GodModeS:
mov [iEAX],eax // Save EAX

mov eax,[edi+0000020c] // Get pShip
test eax,eax
jz _ExitGMS // Jump if the pointer is null

mov al,[eax+0000111f] // Get pCommon
cmp al,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGMS // Jump if false

inc dword ptr [iCountS]

cmp dword ptr [iEnableGM],0
je _ExitGMS // Jump if feature is disabled

mov eax,[iEAX] // Restore EAX
ret // Avoid routine
//-----
_ExitGMS:
mov eax,[iEAX] // Restore EAX

push ecx // Original code
mov ecx,[edi+000003A0] // Original code
jmp _BackGMS // Back to main code

//=========================================
// Card under cursor
_MonSelShip:
mov [pSel],ecx

_ExitMSS:
mov [esi+000000B0],ecx // Original code
jmp _BackMSS // Back to main code

//=========================================
// Ship Hull
_GodModeSH:
mov eax,[ebx+24] // Get pShip
test eax,eax
jz _ExitGMSH // Jump if the pointer is null

mov al,[eax+0000111f] // Get pCommon
cmp al,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGMSH // Jump if false

cmp dword ptr [iEnableGM],0
je _ExitGMSH // Jump if feature is disabled

mov eax,[ebx+1c] // Get max HP
mov [ebx+40],eax // Update cur HP

xor edi,edi // value2decrease = 0

_ExitGMSH:
mov eax,[ebx+40] // Original code
sub eax,edi // Original code
jmp _BackGMSH // Back to main code

//=========================================
// RTS Gold
_MonGold:
mov eax,[ecx+0000048c] // Get pointer to info
test eax,eax
jz _ExitMG // Jump if null pointer

mov eax,[eax+24] // Get pointer to uPlayerID
test eax,eax
jz _ExitMG // Jump if null pointer

mov eax,[eax]
cmp eax,006c0070
jne _ExitMG // Jump if it's an AI

mov eax,[ecx+00000470] // Get pointer to player
mov [pGold],eax

cmp dword ptr [iEnableMG],0
je _ExitMG // Jump if feature is disabled

mov eax,[iMinGold]
cmp eax,[ecx+0000046C]
jle _ExitMG

mov [ecx+0000046C],eax // Update gold

_ExitMG:
mov eax,[ecx+0000046C] // Original code
jmp _BackMG // Back to main code

//=========================================
// RTS Troop Movement Points/Size
_MonMP:
push ecx

mov ecx,[eax+44] // Get pointer to Owner
cmp ecx,[pGold] // Is it a player's troop?
jne _ExitMM

cmp dword ptr [iEnableMM],0
je _MonM0 // Jump if feature is disabled

xor edi,edi // value2decrease = 0

_MonM0:
cmp dword ptr [iEnableMTS],0
je _ExitMM // Jump if feature is disabled

mov ecx,[eax+50] // Get troop maximum size
mov [eax+4c],ecx // Update current size

_ExitMM:
pop ecx

sub edx,edi // Original code
mov [eax+6C],edx // Original code
jmp _BackMM // Back to main code

//=========================================
// RTS Selected Officer
_MonSelOfficer:
mov [pOfficer],eax

_ExitMSO:
cmp [eax+00001C0C],ebx // Original code
jmp _BackMSO // Back to main code

//=========================================
// Variables
iEnableGM:
dd 1
iEnableGM1:
dd 0
iEnableGM2:
dd 1
iEnableMA:
dd 1
iEnableQR:
dd 1
iEnableGMS:
dd 1
iEnableMG:
dd 1
iEnableMM:
dd 1
iEnableMTS:
dd 1
pSel:
dd 0
pGold:
dd 0
pOfficer:
dd 0
iPlayerID:
dd 1
iEAX:
dd 0
iCount0:
dd 0
iCount1:
dd 0
iCount2:
dd 0
iCount3:
dd 0
iCountS:
dd 0
iMinGold:
dd #50000

//=========================================
// Hacking Points
Shogun2.dll+00a63e50:
jmp _GodMode
nop
_BackGM:

Shogun2.dll+00c7e770:
jmp _GodMode1
nop
_BackGM1:

Shogun2.dll+01199dc3:
jmp _MonSel
nop
_BackMS:

Shogun2.dll+009e7af3:
jmp _MonAmmo
nop
nop
nop
_BackMA:

Shogun2.dll+00cf54e0:
jmp _GodModeS
nop
nop
_BackGMS:

Shogun2.dll+011cb77d:
jmp _MonSelShip
nop
_BackMSS:

Shogun2.dll+00b560d7:
jmp _GodModeSH
_BackGMSH:

Shogun2.dll+0046df80:
jmp _MonGold
nop
_BackMG:

Shogun2.dll+0026a5e0:
jmp _MonMP
_BackMM:

Shogun2.dll+011ad6bc:
jmp _MonSelOfficer
nop
_BackMSO:

//=========================================
// Original Codes
[DISABLE]
Shogun2.dll+00a63e50:
push ebp
mov ebp,esp
and esp,f8

Shogun2.dll+00c7e770:
push ebp
mov ebp,esp
and esp,f8

Shogun2.dll+01199dc3:
mov esi,[edi+00000134]

Shogun2.dll+009e7af3:
movss [esi+00000F40],xmm0

Shogun2.dll+00cf54e0:
push ecx
mov ecx,[edi+000003A0]

Shogun2.dll+011cb77d:
mov [esi+000000B0],ecx

Shogun2.dll+00b560d7:
mov eax,[ebx+40]
sub eax,edi

Shogun2.dll+0046df80:
mov eax,[ecx+0000046C]

Shogun2.dll+0026a5e0:
sub edx,edi
mov [eax+6C],edx

Shogun2.dll+011ad6bc:
cmp [eax+00001C0C],ebx

unregistersymbol(MyCode)
unregistersymbol(pSel)
unregistersymbol(pGold)
unregistersymbol(pOfficer)
unregistersymbol(iEnableGM)
unregistersymbol(iEnableGM1)
unregistersymbol(iEnableGM2)
unregistersymbol(iEnableGMS)
unregistersymbol(iEnableMA)
unregistersymbol(iEnableQR)
unregistersymbol(iEnableMG)
unregistersymbol(iEnableMM)
unregistersymbol(iEnableMTS)
unregistersymbol(iMinGold)
unregistersymbol(iPlayerID)
unregistersymbol(iCount0)
unregistersymbol(iCount1)
unregistersymbol(iCount2)
unregistersymbol(iCount3)
unregistersymbol(iCountS)

dealloc(MyCode)

{

Как видно по смещению +0x44, я об этом смещение уже писал почему-то указатель на pGold (вроде как золото) Пользователя является уже критерием принадлежности войскам. Вообще-то странно кажется это корявые названия указателей.


// RTS Troop Movement Points/Size
_MonMP:
push ecx

mov ecx,[eax+44] // Get pointer to Owner
cmp ecx,[pGold] // Is it a player's troop?
jne _ExitMM

cmp dword ptr [iEnableMM],0
je _MonM0 // Jump if feature is disabled

xor edi,edi // value2decrease = 0

_MonM0:
cmp dword ptr [iEnableMTS],0
je _ExitMM // Jump if feature is disabled

mov ecx,[eax+50] // Get troop maximum size
mov [eax+4c],ecx // Update current size

_ExitMM:
pop ecx

sub edx,edi // Original code
mov [eax+6C],edx // Original code
jmp _BackMM // Back to main code

Напоминаю, что это инъекция в эту функцию:


{
int result; // eax@1
char *v3; // ecx@1
int v4; // esi@1
int v5; // eax@2
int v6; // edx@2

v3 = (char *)this + 148;
v4 = *((_DWORD *)v3 + 5);
for ( result = v4 + 4 * *((_DWORD *)v3 + 4); // начальное значения для начала цикла
v4 != result; // условие выполнение цикла пока истино v4 != result
result = *((_DWORD *)v3 + 5) + 4 * *((_DWORD *)v3 + 4) ) // действие при каждой повторении цикла
{

v5 = **(_DWORD **)v4; // v5 = адрес группы (v5 теперь является подгруппой *this)
v6 = *(_DWORD *)(v5 + 0x6C); // v6 = разрешённых шагов для группы v5

if ( v6 <= a2 ) // если разрешённых шагов меньше например 3, когда попытка пойти на 5, то
*(_DWORD *)(v5 + 0x6C) = 0; // присвоить v5 перемещение 0
else // иначе
*(_DWORD *)(v5 + 0x6C) = v6 - a2; // присворить v5 разность между разршенными шагами и "сделанными"

*(_DWORD *)(v5 + 0x898) = -1; // какое-то интересное смещение +0x898, что означает точно не понятно.
// по карайне мере понятно, что оно стаиться в -1, когда v5 было установленно
// кол-во разрешённых шагов

v4 += 4; // перебираем следующую группу
}
return result;
}
int __thiscall sub_10654450(void *this, int a2)

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

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

А можно узнать источник, интересно посмотреть таблици всяких гуру и проанализировать принцип их работы. На момент когда я начал был уже готовый платный трейнер, меня впечатлили возможности трейнера (в промо версии) которые открываются при покупки трейнера, и я решил повторить что смогу. Может и печальная новость что кто то лучше меня или тебя но все же опыт всегда ценен, и я рад что благодаря вам и этой возможности что предоставила нам любезно игра Shogun2 =) мне удалось узнать больше о процессе создания трейнеров.

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

Что то не понятно, у него значение в [iPlayerID] и [pGold] с воздуха берутся? Не вижу чтоб он в них чтонибудь записывал.

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

Ссылка на тему человека Recifense, там же есть файл .CT таблицы.

В [pGold] есть запись, посмотри внимательно. А вот в [iPlayerID] записи нет, потому что это просто переменная для чтения. В этой переменной идентификатор игрока, он всегда равен единице.

По поводу того, что Recifense лучше меня... Скорее всего так и есть, т.к. у него большой опыт в нахождении связей между указателями. Скорее всего, он не работает с декомпиляторами. Это только я так заморачиваюсь. Метод у него, скорее всего, такой. Если он не может сделать один чит, то он делает другой и ищет связи между поинтерами в структурах сделанных читов. Т.е. в его случае из Dessect Data окна он не вылазит вообще и наверняка активно пользуется сканером памяти в поиске адресов и указателей в структурах... так же, скорее всего, он часто ставит бряки на адреса указателей. Указатели эти расположены в структурах, где они характерны только для данной структуры. Мне надо было обратить внимание на смещение +0x44 в структуре "Передвижения" и искать связь этого указателя со структурой где расположен адрес золота моего героя. Ведь и адрес золота, и адрес очков хождения должны обязательно принадлежать герою за которого я играю.

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

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

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

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

Условный бряк на функцию TranslateMessage

остлось понять как запустить трейс чтоб он не заходил в посторонии функции.

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

На счёт бесконечной ходьбы и тд уже давно всё изобретено, вот таблица - изучай...

На счёт остального, я так и не въехал зачем тебе отлавливать функции нажатия клавишь, но если не трудно, то объясни для тех, кто в танке )))

Shogun2_V110_AOB_V21.zip

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

Akama, уже все давно узнали, что есть такая таблица ) И давно решили изучать её или нет...

Отлавливать функции нажатия клавиш надо для работы в отладке, чтобы определить как код игры реагирует на ввод пользователя. Если интересуют подробности, то их нужно искать в отладке...

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

Это зависит от конкретного случая.

Надо подразумевать простую схему. Когда используешь этот способ, то у тебя есть два адреса как минимум одного маршрута выполнения машинного кода. Первая точка это бряк на вводе от пользователя, вторая - бряк на адресе параметра, для которого нужно сделать чит. Соответсвенно, если есть проблемы с созданием чита, то нужно исследовать этот маршрут...

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

Akama, не спешил бы ты с выводами так скоро и при любой возможности. Вот практическое применение.

Как видно на рисунке указатели были исследованы, а вот как сделать "бесконечное обучение заклинаниям" будет описано ниже благодаря способу о котором идёт речь. Этот способ установил рамки до какого адреса вверх стоит подниматься из call-ов.

disciples3intro.gif

Более подробно про то как сделать бесконечное обучение заклинаниям.

1. Вникаем в суть игры и интерфейс, что не мало важно.

Во время изучения заклинания происходят следующие действия.

- В книге заклинаний выбираем заклинание

- Щёлкаем по кнопке выучить заклинания и только после того как отпустили кнопку ,то вычитается мана и заклинания выучено.

2. Раз знаем суть процесса, то находим адрес маны и ставим аппаратный бряк на запись.

3. Ставим бряк на обработку сообщения на WM_MousUp.

Щелкаем на кнопке заклинаний, прерываемся на адресе работы с сообщением.

Снимаем бряк с сообщений и отпускает трейс по ретам.

Возвращаемся в игру.

Происходит прерывание на бряке маны. Снимаем бряк. Отпускаем игру и тут же находимся на развилке кода, это место можно считать верхнем порогом кода. Т.е. выше него мы дальше не полезем.

Итак, определили путь.

disciples3intro.gif

Начало пути - нажали на кнопку:

0040657B . E8 A0D0FFFF CALL Disciple.00403620 - будет началом возможно закрученного пути.

Конец - вычитание маны:

0065AA15 |. 8910 MOV DWORD PTR [EAX],EDX – конечный путь

Вновь ставим бряк на запись маны, прерываемся.

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


006CF6DA |. 75 33 JNZ SHORT Disciple.006CF70F //можно исправить на JMP как это сделал SERGANT
006CF6DC |. 8B01 MOV EAX,DWORD PTR [ECX]
006CF6DE |. 6A 00 PUSH 0
006CF6E0 |. 6A 01 PUSH 1
006CF6E2 |. 68 A8A47F00 PUSH Disciple.007FA4A8 ; ASCII "Msg_SpellTooMuch"
006CF6E7 |. 68 FCA17F00 PUSH Disciple.007FA1FC ; ASCII "Msg_HLIngfo"
006CF6EC |. FF90 58020000 CALL NEAR DWORD PTR [EAX+258]
006CF6F2 |. 8B0D A478C301 MOV ECX,DWORD PTR [1C378A4]
006CF6F8 |. 8B11 MOV EDX,DWORD PTR [ECX]
006CF6FA |. 68 0000803F PUSH 3F800000
006CF6FF |. 6A 18 PUSH 18
006CF701 |. FF92 BC040000 CALL NEAR DWORD PTR [EDX+4BC]
006CF707 |. 5F POP EDI ; 25F89E08
006CF708 |. 32C0 XOR AL,AL
006CF70A |. 5D POP EBP ; 25F89E08
006CF70B |. 83C4 10 ADD ESP,10
006CF70E |. C3 RET
006CF70F |> 8B87 74010000 MOV EAX,DWORD PTR [EDI+174]
006CF715 |. 3B87 30010000 CMP EAX,DWORD PTR [EDI+130]
006CF71B |. 73 0B JNB SHORT Disciple.006CF728
006CF71D |. 8B8F 2C010000 MOV ECX,DWORD PTR [EDI+12C]
006CF723 |. 8D0481 LEA EAX,DWORD PTR [ECX+EAX*4]
006CF726 |. EB 06 JMP SHORT Disciple.006CF72E
006CF728 |> 8D87 3C010000 LEA EAX,DWORD PTR [EDI+13C]
006CF72E |> 8B10 MOV EDX,DWORD PTR [EAX]
006CF730 |. 53 PUSH EBX
006CF731 |. 8B1A MOV EBX,DWORD PTR [EDX]
006CF733 |. E8 18E1FFFF CALL Disciple.006CD850
006CF738 |. 84C0 TEST AL,AL
006CF73A |. 74 09 JE SHORT Disciple.006CF745
006CF73C |. 5B POP EBX ; 25F89E08
006CF73D |. 5F POP EDI ; 25F89E08
006CF73E |. 32C0 XOR AL,AL
006CF740 |. 5D POP EBP ; 25F89E08
006CF741 |. 83C4 10 ADD ESP,10
006CF744 |. C3 RET
006CF745 |> 56 PUSH ESI
006CF746 |. 8BB7 74010000 MOV ESI,DWORD PTR [EDI+174]
006CF74C |. 33C9 XOR ECX,ECX
006CF74E |. 8D5D 04 LEA EBX,DWORD PTR [EBP+4]
006CF751 |> 3BB7 30010000 /CMP ESI,DWORD PTR [EDI+130]
006CF757 |. 73 0B |JNB SHORT Disciple.006CF764
006CF759 |. 8B87 2C010000 |MOV EAX,DWORD PTR [EDI+12C]
006CF75F |. 8D04B0 |LEA EAX,DWORD PTR [EAX+ESI*4]
006CF762 |. EB 06 |JMP SHORT Disciple.006CF76A
006CF764 |> 8D87 3C010000 |LEA EAX,DWORD PTR [EDI+13C]
006CF76A |> 8B10 |MOV EDX,DWORD PTR [EAX]
006CF76C |. 3B4A 24 |CMP ECX,DWORD PTR [EDX+24]
006CF76F |. 0F83 87000000 |JNB Disciple.006CF7FC
006CF775 |. 3BB7 30010000 |CMP ESI,DWORD PTR [EDI+130]
006CF77B |. 73 0B |JNB SHORT Disciple.006CF788
006CF77D |. 8B87 2C010000 |MOV EAX,DWORD PTR [EDI+12C]
006CF783 |. 8D04B0 |LEA EAX,DWORD PTR [EAX+ESI*4]
006CF786 |. EB 06 |JMP SHORT Disciple.006CF78E
006CF788 |> 8D87 3C010000 |LEA EAX,DWORD PTR [EDI+13C]
006CF78E |> 8B00 |MOV EAX,DWORD PTR [EAX]
006CF790 |. 8B50 24 |MOV EDX,DWORD PTR [EAX+24]
006CF793 |. 83C0 20 |ADD EAX,20
006CF796 |. 3BCA |CMP ECX,EDX
006CF798 |. 73 07 |JNB SHORT Disciple.006CF7A1
006CF79A |. 8B10 |MOV EDX,DWORD PTR [EAX]
006CF79C |. 8D048A |LEA EAX,DWORD PTR [EDX+ECX*4]
006CF79F |. EB 03 |JMP SHORT Disciple.006CF7A4
006CF7A1 |> 83C0 10 |ADD EAX,10
006CF7A4 |> 83F9 FF |CMP ECX,-1
006CF7A7 |. 8B00 |MOV EAX,DWORD PTR [EAX]
006CF7A9 |. 74 09 |JE SHORT Disciple.006CF7B4
006CF7AB |. 83F9 08 |CMP ECX,8
006CF7AE |. 7D 04 |JGE SHORT Disciple.006CF7B4
006CF7B0 |. 8B13 |MOV EDX,DWORD PTR [EBX]
006CF7B2 |. EB 03 |JMP SHORT Disciple.006CF7B7
006CF7B4 |> 83CA FF |OR EDX,FFFFFFFF
006CF7B7 |> 3BD0 |CMP EDX,EAX
006CF7B9 |. 7C 06 |JL SHORT Disciple.006CF7C1
006CF7BB |. 41 |INC ECX
006CF7BC |. 83C3 0C |ADD EBX,0C
006CF7BF |.^ EB 90 \JMP SHORT Disciple.006CF751
006CF7C1 |> 8B0D A478C301 MOV ECX,DWORD PTR [1C378A4]
006CF7C7 |. 8B01 MOV EAX,DWORD PTR [ECX]
006CF7C9 |. 6A 00 PUSH 0
006CF7CB |. 6A 01 PUSH 1
006CF7CD |. 68 F0A17F00 PUSH Disciple.007FA1F0 ; ASCII "Msg_NoRes"
006CF7D2 |. 68 FCA17F00 PUSH Disciple.007FA1FC ; ASCII "Msg_HLIngfo"
006CF7D7 |. FF90 58020000 CALL NEAR DWORD PTR [EAX+258]
006CF7DD |. 8B0D A478C301 MOV ECX,DWORD PTR [1C378A4]
006CF7E3 |. 8B11 MOV EDX,DWORD PTR [ECX]
006CF7E5 |. 68 0000803F PUSH 3F800000
006CF7EA |. 6A 18 PUSH 18
006CF7EC |. FF92 BC040000 CALL NEAR DWORD PTR [EDX+4BC]
006CF7F2 |. 5E POP ESI ; 25F89E08
006CF7F3 |. 5B POP EBX ; 25F89E08
006CF7F4 |. 5F POP EDI ; 25F89E08
006CF7F5 |. 32C0 XOR AL,AL
006CF7F7 |. 5D POP EBP ; 25F89E08
006CF7F8 |. 83C4 10 ADD ESP,10
006CF7FB |. C3 RET
006CF7FC |> 8B4424 10 MOV EAX,DWORD PTR [ESP+10]
006CF800 |. 33ED XOR EBP,EBP
006CF802 |. 33DB XOR EBX,EBX
006CF804 |> 8B8F 30010000 /MOV ECX,DWORD PTR [EDI+130]
006CF80A |. 894424 14 |MOV DWORD PTR [ESP+14],EAX
006CF80E |. 8B87 74010000 |MOV EAX,DWORD PTR [EDI+174]
006CF814 |. 3BC1 |CMP EAX,ECX
006CF816 |. 896C24 1C |MOV DWORD PTR [ESP+1C],EBP
006CF81A |. 73 0B |JNB SHORT Disciple.006CF827
006CF81C |. 8B8F 2C010000 |MOV ECX,DWORD PTR [EDI+12C]
006CF822 |. 8D0C81 |LEA ECX,DWORD PTR [ECX+EAX*4]
006CF825 |. EB 06 |JMP SHORT Disciple.006CF82D
006CF827 |> 8D8F 3C010000 |LEA ECX,DWORD PTR [EDI+13C]
006CF82D |> 8B11 |MOV EDX,DWORD PTR [ECX]
006CF82F |. 3B6A 24 |CMP EBP,DWORD PTR [EDX+24]
006CF832 |. 0F83 A7000000 |JNB Disciple.006CF8DF
006CF838 |. 3B87 30010000 |CMP EAX,DWORD PTR [EDI+130]
006CF83E |. 73 0B |JNB SHORT Disciple.006CF84B
006CF840 |. 8B8F 2C010000 |MOV ECX,DWORD PTR [EDI+12C]
006CF846 |. 8D0481 |LEA EAX,DWORD PTR [ECX+EAX*4]
006CF849 |. EB 06 |JMP SHORT Disciple.006CF851
006CF84B |> 8D87 3C010000 |LEA EAX,DWORD PTR [EDI+13C]
006CF851 |> 8B00 |MOV EAX,DWORD PTR [EAX]
006CF853 |. 8B48 24 |MOV ECX,DWORD PTR [EAX+24]
006CF856 |. 83C0 20 |ADD EAX,20
006CF859 |. 3BE9 |CMP EBP,ECX
006CF85B |. 73 06 |JNB SHORT Disciple.006CF863
006CF85D |. 8B00 |MOV EAX,DWORD PTR [EAX]
006CF85F |. 03C3 |ADD EAX,EBX
006CF861 |. EB 03 |JMP SHORT Disciple.006CF866
006CF863 |> 83C0 10 |ADD EAX,10
006CF866 |> 83FB FC |CMP EBX,-4
006CF869 |. 8B00 |MOV EAX,DWORD PTR [EAX]
006CF86B |. 74 62 |JE SHORT Disciple.006CF8CF
006CF86D |. 83FB 20 |CMP EBX,20
006CF870 |. 7F 5D |JG SHORT Disciple.006CF8CF
006CF872 |. 8B5424 14 |MOV EDX,DWORD PTR [ESP+14]
006CF876 |. 8B32 |MOV ESI,DWORD PTR [EDX]
006CF878 |. 8B5424 10 |MOV EDX,DWORD PTR [ESP+10]
006CF87C |. 8D4C24 18 |LEA ECX,DWORD PTR [ESP+18]

006CF880 |. 51 |PUSH ECX
006CF881 |. 6A 00 |PUSH 0
006CF883 |. F7D8 |NEG EAX
006CF885 |. 50 |PUSH EAX
006CF886 |. 56 |PUSH ESI
006CF887 |. 52 |PUSH EDX
006CF888 |. C74424 2C 0000000>|MOV DWORD PTR [ESP+2C],0
006CF890 |. E8 ABB0F8FF |CALL Disciple.0065A940 ; <<<<<<<<<<<<,, + вышли отсюда и смотрим код вверху

006CF895 |. 83C4 14 |ADD ESP,14
006CF898 |. 84C0 |TEST AL,AL
006CF89A |. 74 33 |JE SHORT Disciple.006CF8CF
006CF89C |. 8B4424 18 |MOV EAX,DWORD PTR [ESP+18]
006CF8A0 |. 8B0D A078C301 |MOV ECX,DWORD PTR [1C378A0]
006CF8A6 |. 8B11 |MOV EDX,DWORD PTR [ECX]
006CF8A8 |. 6A 00 |PUSH 0
006CF8AA |. 8D2C40 |LEA EBP,DWORD PTR [EAX+EAX*2]
006CF8AD |. 8B4424 14 |MOV EAX,DWORD PTR [ESP+14]
006CF8B1 |. 8B6CA8 04 |MOV EBP,DWORD PTR [EAX+EBP*4+4]
006CF8B5 |. 8B80 E4000000 |MOV EAX,DWORD PTR [EAX+E4]
006CF8BB |. 6A 00 |PUSH 0
006CF8BD |. 55 |PUSH EBP
006CF8BE |. 56 |PUSH ESI
006CF8BF |. 50 |PUSH EAX
006CF8C0 |. 68 F8027F00 |PUSH Disciple.007F02F8 ; ASCII "GetResource"
006CF8C5 |. FF92 90020000 |CALL NEAR DWORD PTR [EDX+290]
006CF8CB |. 8B6C24 1C |MOV EBP,DWORD PTR [ESP+1C]
006CF8CF |> 8B4424 14 |MOV EAX,DWORD PTR [ESP+14]
006CF8D3 |. 45 |INC EBP
006CF8D4 |. 83C3 04 |ADD EBX,4
006CF8D7 |. 83C0 0C |ADD EAX,0C
006CF8DA |.^ E9 25FFFFFF \JMP Disciple.006CF804
006CF8DF |> 8B4C24 10 MOV ECX,DWORD PTR [ESP+10]
006CF8E3 |. 51 PUSH ECX
006CF8E4 |. 57 PUSH EDI ; Disciple.01C3FF80
006CF8E5 |. E8 B6FCFFFF CALL Disciple.006CF5A0
006CF8EA |. A1 A478C301 MOV EAX,DWORD PTR [1C378A4]
006CF8EF |. 8B90 E0000000 MOV EDX,DWORD PTR [EAX+E0]
006CF8F5 |. 8990 E4000000 MOV DWORD PTR [EAX+E4],EDX
006CF8FB |. 8B8F 78010000 MOV ECX,DWORD PTR [EDI+178]
006CF901 |. 8B97 7C010000 MOV EDX,DWORD PTR [EDI+17C]
006CF907 |. 8B07 MOV EAX,DWORD PTR [EDI] ; Disciple.007FA410
006CF909 |. 8BB7 70010000 MOV ESI,DWORD PTR [EDI+170]
006CF90F |. 8B9F 74010000 MOV EBX,DWORD PTR [EDI+174]
006CF915 |. 83C4 08 ADD ESP,8
006CF918 |. 51 PUSH ECX
006CF919 |. 52 PUSH EDX
006CF91A |. 8BCF MOV ECX,EDI ; Disciple.01C3FF80
006CF91C |. FF50 4C CALL NEAR DWORD PTR [EAX+4C]
006CF91F |. 8B07 MOV EAX,DWORD PTR [EDI] ; Disciple.007FA410
006CF921 |. 53 PUSH EBX
006CF922 |. 8BCF MOV ECX,EDI ; Disciple.01C3FF80
006CF924 |. 89B7 70010000 MOV DWORD PTR [EDI+170],ESI
006CF92A |. FF50 50 CALL NEAR DWORD PTR [EAX+50]
006CF92D |. E8 9E060000 CALL Disciple.006CFFD0
006CF932 |. E8 C9080000 CALL Disciple.006D0200
006CF937 |. 8B0D A478C301 MOV ECX,DWORD PTR [1C378A4]
006CF93D |. 85C9 TEST ECX,ECX
006CF93F |. 74 0F JE SHORT Disciple.006CF950
006CF941 |. 8B11 MOV EDX,DWORD PTR [ECX]
006CF943 |. 68 0000803F PUSH 3F800000
006CF948 |. 6A 06 PUSH 6
006CF94A |. FF92 BC040000 CALL NEAR DWORD PTR [EDX+4BC]
006CF950 |> 5E POP ESI ; 25F89E08
006CF951 |. 5B POP EBX ; 25F89E08
006CF952 |. 5F POP EDI ; 25F89E08
006CF953 |. B0 01 MOV AL,1
006CF955 |. 5D POP EBP ; 25F89E08
006CF956 |. 83C4 10 ADD ESP,10
006CF959 \. C3 RET
006CF6D6  |.  896C24 08 		MOV DWORD PTR [ESP+8],EBP


{
int v1; // ebp@1
int v2; // edi@1
char result; // al@2
signed int v4; // ecx@7
int v5; // ebx@7
unsigned int v6; // esi@7
int v7; // eax@9
int v8; // eax@13
int v9; // eax@15
int v10; // eax@16
signed int v11; // eax@18
signed int v12; // edx@20
int v13; // eax@25
signed int v14; // ebx@25
unsigned int v15; // ebp@25
unsigned int v16; // eax@26
int v17; // ecx@27
int v18; // eax@31
int v19; // eax@33
int v20; // eax@34
int v21; // eax@36
int v22; // esi@38
int v23; // eax@1
char v24; // zf@1
int v25; // eax@15
unsigned int v26; // edx@15
unsigned int v27; // ecx@26
int v28; // eax@33
unsigned int v29; // ecx@33
int v30; // esi@41
int v31; // ebx@41
int v32; // eax@41
int v33; // [sp+14h] [bp-10h]@1
int v34; // [sp+18h] [bp-Ch]@26
unsigned int v35; // [sp+20h] [bp-4h]@26
int v36; // [sp+1Ch] [bp-8h]@38

v2 = a1;
v23 = (*(int (**)(void))(*(_DWORD *)dword_1C378A4 + 0x34))();
v1 = v23;
v24 = *(_DWORD *)(dword_1C378A4 + 0xE4) == *(_DWORD *)(dword_1C378A4 + 0xE0); // ключевое место
v33 = v23;
if ( v24 )
{
(*(int (__stdcall **)(char *, char *, signed int, _DWORD))(*(_DWORD *)dword_1C378A4 + 0x258))(
"Msg_HLIngfo",
"Msg_SpellTooMuch",
1,
0);
(*(int (__stdcall **)(signed int, unsigned int))(*(_DWORD *)dword_1C378A4 + 0x4BC))(24, 0x3F800000u);
result = 0;
}
else
{
*(_DWORD *)(v2 + 372) >= *(_DWORD *)(v2 + 304);
if ( (unsigned __int8)sub_6CD850() )
{
result = 0;
}
else
{
v6 = *(_DWORD *)(v2 + 372);
v4 = 0;
v5 = v1 + 4;
while ( 1 )
{
if ( v6 >= *(_DWORD *)(v2 + 304) )
v7 = v2 + 316;
else
v7 = *(_DWORD *)(v2 + 0x12C) + 4 * v6;
if ( (unsigned int)v4 >= *(_DWORD *)(*(_DWORD *)v7 + 0x24) )
break;
if ( v6 >= *(_DWORD *)(v2 + 304) )
v8 = v2 + 316;
else
v8 = *(_DWORD *)(v2 + 0x12C) + 4 * v6;
v25 = *(_DWORD *)v8;
v26 = *(_DWORD *)(v25 + 0x24);
v9 = v25 + 32;
if ( v4 >= v26 )
v10 = v9 + 16;
else
v10 = *(_DWORD *)v9 + 4 * v4;
v11 = *(_DWORD *)v10;
if ( v4 == -1 || v4 >= 8 )
v12 = -1;
else
v12 = *(_DWORD *)v5;
if ( v12 < v11 )
{
(*(int (__stdcall **)(char *, char *, signed int, _DWORD))(*(_DWORD *)dword_1C378A4 + 600))(
"Msg_HLIngfo",
"Msg_NoRes",
1,
0);
(*(int (__stdcall **)(unsigned int, signed int))(*(_DWORD *)dword_1C378A4 + 0x4BC))(0x18u, 1065353216);
return 0;
}
++v4;
v5 += 12;
}
v13 = v33;
v15 = 0;
v14 = 0;
while ( 1 )
{
v27 = *(_DWORD *)(v2 + 304);
v34 = v13;
v16 = *(_DWORD *)(v2 + 372);
v35 = v15;
if ( v16 >= v27 )
v17 = v2 + 316;
else
v17 = *(_DWORD *)(v2 + 300) + 4 * v16;
if ( v15 >= *(_DWORD *)(*(_DWORD *)v17 + 36) )
break;
if ( v16 >= *(_DWORD *)(v2 + 304) )
v18 = v2 + 316;
else
v18 = *(_DWORD *)(v2 + 300) + 4 * v16;
v28 = *(_DWORD *)v18;
v29 = *(_DWORD *)(v28 + 36);
v19 = v28 + 32;
if ( v15 >= v29 )
v20 = v19 + 16;
else
v20 = v14 + *(_DWORD *)v19;
v21 = *(_DWORD *)v20;
if ( v14 != -4 )
{
if ( v14 <= 32 )
{
v22 = *(_DWORD *)v34;
v36 = 0;
if ( (unsigned __int8)SFChangeResourceNum(v33, v22, -v21, 0, &v36) )
{
(*(int (__stdcall **)(char *, _DWORD, int, _DWORD, _DWORD, _DWORD))(*(_DWORD *)dword_1C378A0 + 656))(
"GetResource",
*(_DWORD *)(v33 + 228),
v22,
*(_DWORD *)(v33 + 12 * v36 + 4),
0,
0);
v15 = v35;
}
}
}
++v15;
v14 += 4;
v13 = v34 + 12;
}
SFSpellStudent(v2, v33);
*(_DWORD *)(dword_1C378A4 + 228) = *(_DWORD *)(dword_1C378A4 + 224);
v30 = *(_DWORD *)(v2 + 368);
v31 = *(_DWORD *)(v2 + 372);
(*(int (__thiscall **)(int, _DWORD, _DWORD))(*(_DWORD *)v2 + 76))(
v2,
*(_DWORD *)(v2 + 380),
*(_DWORD *)(v2 + 376));
v32 = *(_DWORD *)v2;
*(_DWORD *)(v2 + 368) = v30;
(*(int (__thiscall **)(int, int))(v32 + 80))(v2, v31);
sub_6CFFD0();
sub_6D0200();
if ( dword_1C378A4 )
(*(int (__stdcall **)(signed int, unsigned int))(*(_DWORD *)dword_1C378A4 + 1212))(6, 0x3F800000u);
result = 1;
}
}
return result;
}
char __usercall sub_6CF6B0<al>(int a1<eax>)

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

x1= [[1C378A4]+0xE4] – это значение устанавливается равным [[1C378A4]+0xE0] при изучении заклинания

x2= [[1C378A4]+0xE0] – количество игровых ходов, т.е. не игрока, а именно ходов игры.

Если x1 и x2 равны, то нельзя выучить заклинание.

x1 до начала самого первого хода в игре равно мусору. После изучения первого заклинания на пример на 5-ом ходу когда x2=5, то x1 становится равным 5. Делаем ход x2 становится равным 6, а x1 остаётся равным 3. Изучаем заклинание x1 становится равным 6.

Вывод: нельзя найти отсеиванием, т.к. врядли додумаешься до правил поиска )

Про то, как сделать пользование магией будет скоро в следующем посте. Надо делать почти также. Ставить бряк на Ману использовать заклинание и смотреть выше по коду…

Короче что просил Иван Иванови, то сделал.

Берём русскую версию CE.

\"Подсоединяем\" процесс игры

Идём в отладчик, нажимаем на Автоассемблер.

Пишем скрипт ниже.

Связываем, сохраняем таблицу. Активируем и играем.


//Бесконечное изучение заклинания
DisciplesIII.exe+2CF6DA:>E40000008BE83B91E0000000896C2408YYxxxxxxxx006A0168A8A47F0068FC
db eb 33

//Бесконечное использование заклинания
DisciplesIII.exe+27BFD7:>006A01508BCDFF92380600008B5C2418YYxxxxxxxx008B85E0000000898388
db 90 90 90 90 90 90

//Бесконечная постройка зданий
DisciplesIII.exe+2F35E3:>2418508BC78BCDE8xxxxxxxx85F67407YYxxxxxxxx00018B0Dxxxxxxxx85C9
db 90 90 90 90 90 90 90

[DISABLE]
DisciplesIII.exe+2CF6DA:>E40000008BE83B91E0000000896C2408YYxxxxxxxx006A0168A8A47F0068FC
db 75 33

DisciplesIII.exe+27BFD7:>006A01508BCDFF92380600008B5C2418YYxxxxxxxx908B85E0000000898388
inc [ebx+0000008c] //ff 83 8c 00 00 00

DisciplesIII.exe+2F35E3:>2418508BC78BCDE8xxxxxxxx85F67407YYxxxxxxxx90908B0Dxxxxxxxx85C9
mov byte ptr [esi+000000f0],01 //c6 86 f0 00 00 00 01
[ENABLE]

Чит-код на \"Бесконечное использование заклинания\" было сложно найти ) SERGANT, я трейнер делать не буду, так что вся надежда по видимому только на тебя. Если есть вопросы, то я постараюсь помочь.

Ах да, по водову inc [ebx+0000008c]. Эти данные входят в структуру героя. Если кому надо те могут посмотреть рисунок выше и сравнить с этим указателем [[[[DisciplesIII.exe+18378A4]+00122b24]+1*4]+8c], он же и [ebx+0000008c], где ebx был рассчитан, а 8с = 0x22*4

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

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

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

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