-
Постов
2 999 -
Зарегистрирован
-
Победитель дней
129
Тип контента
Профили
Форумы
Загрузки
Блоги
Сообщения, опубликованные MasterGH
-
-
M4K, надо хакать ромы. Ромы надо хакать
Ты тратишь своё время.
Сделал внутри рома читы и это на век, и больше не паришься насчёт новых эмуляторов.
-
Все языки программирования, которые работают с API Windows могут помочь создать такой же трейнер и даже лучше.
А каким образом и что "обозначить" ты узнаешь, если долго и упорно прочитаешь материалы по языку программирования под Windows. Надеюсь я ответил на твой вопрос.
-
Вот пример
Исполняемый файл игры должен быть назван как FEARXP.exe игра (F.E.A.R. Extra Point). Если он так не назван, то назвать.
AAgen.lua поместить в директорию с Cheat Engine 6.1
Сначала запустить и начать игру.
Затем свернуть игру и дважды кликнуть по F.E.A.R. trainer.CETRAINER
Код трейнера:
require("AAgen")
function Initialize()
bufScript = BeginGenerateAAscriptAggregateMem("allocMem", "2048")
bufScript = GenerateAAscriptAggregateMemWithSignature(bufScript, "InfHealth", "d9xxxxxxxxxx8bxxe8xxxxxxxx2bxx8bxxxx33xx2bxx83xxxx7dxx8axxxxxx84", "+X+C-W", 0, "mov [ebx+00000758],(float)100",true)
bufScript = EndGenerateAAscriptAggregateMem(bufScript)
autoAssemble(bufScript)
end
AAgenINIT("F.E.A.R.XP Ttainer +1, v1.0, {MasterGH}", " FEARXP.exe ", Initialize)У Xipho в статье в игре структура героя другая. У него надо mov [ebx+000006E0],(float)100. Сигнатура у меня и у него одинаковая. Когда модуль AAgen.lua будет усовершенствован - новые функции генерации АА-скрипта по дизассемблерному коду, то даже этот трейнер будет работать. Надо будет только аттач к процессу игры делать не по имени исполняемого файла, а по сигнатурам или иным характеристикам.
-
Вообще я без понятия. Судя по коду он нашёл фильтр "cmp byte ptr [ecx],a0" просматривая структуры памяти в Cheat Engine. Если не знаешь как это делается, то вот пример из другого случая.
-
Примеры скриптов с возможными ошибками пользователей.
1. Случай.
Создание прыжка и разрушение памяти написаны не там где надо, что может привести к вылету из игры с ошибкой при активации по хот-кеям. И не совсем оптимизированный скрипт.
Напоминаю, что сохранять и восстанавливать флаги нужно в тех случаях, когда после вашей инъекцией кода и идёт код использующий регистр флагов. Чаще всего это инструкции инструкции cmp и test. Если будут таки команды, то возможно будет вылет из игры.Ниже скрипт постоянное, здоровье возвращает герою здоровье.
[ENABLE]
alloc(newmem,256)
label(back)
label(code)
019FAB50:
jmp newmem
back:
newmem:
push eax
cmp byte ptr [ecx],a0
jne code
mov eax,[ecx+1a]
mov [ecx+16],eax
code:
pop eax
fld dword ptr [ecx+16]
ret
int 3
jmp back
[DISABLE]
dealloc(newmem)
019FAB50:
fld dword ptr [ecx+16]
ret
int 3Скорее всего, правильнее написать так (без учёта сохранения/восстановления регистра флагов):
alloc(newmem,256)
label(code)
newmem:
cmp byte [ecx],a0
jne code
fld dword [ecx+1a]
ret
code:
fld dword [ecx+16]
ret
019FAB50:
jmp newmem
[DISABLE]
019FAB50:
fld dword ptr [ecx+16]
ret
int 3
dealloc(newmem)[ENABLE]
С восстановлением флагов было бы так:
alloc(newmem,256)
label(code)
newmem:
pushfd
cmp byte [ecx],a0
jne code
fld dword [ecx+1a]
popfd
ret
code:
fld dword [ecx+16]
popfd
ret
019FAB50:
jmp newmem
[DISABLE]
019FAB50:
fld dword ptr [ecx+16]
ret
int 3
dealloc(newmem)[ENABLE]
-
Ниже скрипт постоянное, здоровье возвращает герою здоровье.
[ENABLE]
alloc(newmem,256)
label(back)
label(code)
019FAB50:
jmp newmem
back:
newmem:
push eax
cmp byte ptr [ecx],a0
jne code
mov eax,[ecx+1a]
mov [ecx+16],eax
code:
pop eax
fld dword ptr [ecx+16]
ret
int 3
jmp back
[DISABLE]
dealloc(newmem)
019FAB50:
fld dword ptr [ecx+16]
ret
int 3Скорее всего, правильнее написать так (без учёта сохранения/восстановления регистра флагов):
[ENABLE]
alloc(newmem,256)
label(code)
newmem:
cmp byte [ecx],a0
jne code
fld dword [ecx+1a]
ret
code:
fld dword [ecx+16]
ret
019FAB50:
jmp newmem
[DISABLE]
019FAB50:
fld dword ptr [ecx+16]
ret
int 3
dealloc(newmem) -
Библиотека ещё не доведена до ума, но кое-что она умеет делать.
Для того чтобы создалось это окно и читы работали по горячим клавишам со звуковым сообщением надо написать код LUA в главной таблице CE (это всего лишь пример):
require("TrainerGen")
function Initialize()
AddCheatInCETableFillnopsInstructionWithSignature("NoRecoilHand", "e8xxxxxxxx8bxxxxxx83xxxx33xx80xxxxxx75xx8bxxxxxxf7", 0)
bufScript = BeginGenerateAAscriptAggregateMem("allocMem", "2048")
bufScript = GenerateAAscriptAggregateMemWithSignature(bufScript, "NoRecoilWalk", "d9xxd9xxxxd9xxxxd9xxxxxxxxxxdexxdfxxf6xxxx75xxd9xxxxxxxxxxd9", 8, "fstp st\n fldz", true )
bufScript = GenerateAAscriptAggregateMemWithSignature(bufScript, "NoRecoilShot", "d9xxxxxxxxxx75xxd9xxxxxxxxxxd8xxxxxxd8xxdfxxf6xxxx7axxd9", 0, "fstp st\n fldz", true )
bufScript = GenerateAAscriptAggregateMemWithSignature(bufScript, "NoReload", "83xxxxxxxxxxxxxx74xxf6xxxxxx74xx83xxxx89xxxxxxxxxx39xxxx7dxxf7", 0, "mov [ebp+eax*4+00000334],#100", true )
bufScript = EndGenerateAAscriptAggregateMem(bufScript)
autoAssemble(bufScript)
GroupAA("Complex better weapons", {"NoRecoilHand", "NoRecoilWalk", "NoRecoilShot", "NoReload"} )
end
AAgenINIT("CoD4 Ttainer +1, v1.0, {MasterGH}", "iw3sp.exe", Initialize)Далее сохранить этот код примера как .CETRAINER.
Запустить двойным кликом. Форма CE показываться не будет.
Запустить игру и дождаться когда трейнер будет готов к работе.
Активировать чит нажатием горячих клавиш для группы "Complex better weapons"
Код TrainerGen.lua (который надо поместить в папку с трейнерами типа .CETRAINER или файлами типа .CT; в коде есть мусор в комментариях, если мешает, то убрать самостоятельно)
-- Если скрипт с таким именем уже существует, то он будет перезаписан
function GenerateAAscriptCreatePageMem( cheatName, address, injectInstruction, originalcode )
local addressInjection = address
local adressReturnHere = 0
local originalCodeString = ""
local nopsString = ""
adressReturnHere, originalCodeString, nopsString = GetInfoInjection(address)
if (originalcode) then
script =[[
[ENABLE]
alloc(newmem,2048)
label(originalcode)
label(returnhere)
newmem:
]]..injectInstruction..[[
originalcode:]]..originalCodeString.. [[
jmp returnhere
]]..addressInjection..[[:
jmp newmem
]]..nopsString..[[
returnhere:
[DISABLE]
]]..addressInjection..":"..originalCodeString.. [[
dealloc(newmem)
]]
else
script =[[
[ENABLE]
alloc(newmem,2048)
label(returnhere)
newmem:
]]..injectInstruction..[[
jmp returnhere
]]..addressInjection..[[:
jmp newmem
]]..nopsString..[[
returnhere:
[DISABLE]
]]..addressInjection..":"..originalCodeString.. [[
dealloc(newmem)
]]
end
end
----^^^^^^^^^
-- Функции часто используемые другими функциями
function preSubScript(script, patternWord, newWords) -- return bufferString
local index = string.find(script, patternWord)
local newscript = string.sub(script, 1, index - 1)..newWords.."\n"..string.sub(script, index)
return newscript
end
function SetScriptInEntryCETable(cheatName, script)
local teSlave = getTableEntry(cheatName)
if (teSlave == nil) then
teSlave = addresslist_createMemoryRecord(addresslist)
memoryrecord_setDescription(teSlave, cheatName)
end
memoryrecord_setType(teSlave, vtAutoAssembler)
memoryrecord_setScript(teSlave, script)
end
----^^^^^^^^^
-- Функции для извлечения какой-то информации
function GetInfoInjection(address) --return adressReturnHere, originalCodeString, nopsString
local sumBytes = 0
local originalCodeString = " "
repeat
countBytes = getInstructionSize(address)
extrafield, opcode, bytes, address = splitDisassembledString(disassemble(address))
originalCodeString = originalCodeString.."\n "..opcode
sumBytes = sumBytes + countBytes
until (sumBytes >= 5)
adressReturnHere = string.format("%x", ("0x"..address) + countBytes)
local nopsString = ""
local nopsCount = sumBytes - 5
if (nopsCount>0) then
nopsString = " db"
for i = 1, nopsCount do
nopsString = nopsString.." 90"
end
end
return adressReturnHere, originalCodeString, nopsString
end
function GetSignatureOfCode(address)
--[[
Переписать из кода Дельфи
procedure TfrmAutoInject.Codeinjection1Click(Sender: TObject);
function inttostr(i:int64):string;
begin
if i=0 then result:='' else result:=sysutils.IntToStr(i);
end;
var address: string;
addressdw: dword;
originalcode: array of string;
originalbytes: array of byte;
codesize: integer;
a,b: dword;
x: string;
i,j,k: integer;
prev_usesymbols: boolean;
injectnr: integer;
enablepos: integer;
disablepos: integer;
enablecode: tstringlist;
disablecode: tstringlist;
simbol:boolean;
bofset:byte;
provbyte:string;
begin
{$ifndef standalonetrainerwithassembler}
CheatTablecompliantcodee1.Click; // обрамление
simbol:=symhandler.showmodules; //запоминаем "нужно ли показывать модули"
symhandler.showmodules:=true; //в любом случае показываем модули в метках
a:=memorybrowser.disassemblerview.SelectedAddress;
address:=inttohex(a,8);
{ if inputquery('Code inject template','On what address do you want the jump?',address) then
begin}
try
a:=strtoint('+address);
except
a:=symhandler.getaddressfromname(address);
end;
b:=a;
injectnr:=0;
for i:=0 to assemblescreen.Lines.Count-1 do
begin
j:=pos('alloc(newmem',lowercase(assemblescreen.lines[i]));
if j<>0 then
begin
x:=copy(assemblescreen.Lines[i],j+12,length(assemblescreen.Lines[i]));
x:=copy(x,1,pos(',',x)-1);
try
k:=strtoint(x);
if injectnr<=k then
injectnr:=k+1;
except
inc(injectnr);
end;
end;
end;
//disassemble the old code
setlength(originalcode,0);
codesize:=0;
while codesize<5 do
begin
setlength(originalcode,length(originalcode)+1);
originalcode[length(originalcode)-1]:=disassemble(a,x);
i:=posex('-',originalcode[length(originalcode)-1]);
i:=posex('-',originalcode[length(originalcode)-1],i+1);
originalcode[length(originalcode)-1]:=copy(originalcode[length(originalcode)-1],i+2,length(originalcode[length(originalcode)-1]));
codesize:=a-b;
end;
setlength(originalbytes,codesize);
ReadProcessMemory(processhandle, pointer(, @originalbytes[0], codesize, a);
enablecode:=tstringlist.Create;
disablecode:=tstringlist.Create;
try
with enablecode do
begin
// Необходимое сканирование при активации, когда адрес сместился
//aobscan(_address,d8xxxxxxdfxxf6xxxx0fxxxxxxxxxx8bxxe8xxxxxxxx8bxxe8xxxxxxxxd9xxd8)
provbyte:=getbytes(strtoint('+address));
add(' aobscan(_faddress,'+provbyte+')');
add(' alloc(_newmem'+inttostr(injectnr)+',2048)');
add(' label(_returnhere'+inttostr(injectnr)+')');
add(' label(_originalcode'+inttostr(injectnr)+')');
add('');
add('_newmem'+inttostr(injectnr)+':');
// add(' mov [],eax //mov eax,');
add('');
add('_originalcode'+inttostr(injectnr)+':');
for i:=0 to length(originalcode)-1 do
add(' '+originalcode[i]);
add(' jmp _returnhere'+inttostr(injectnr)+'');
add('');
add('_faddress: // '+address+' = '+symhandler.getNameFromAddress(strtoint('+address)));
// add(symhandler.getnamefromaddress(strtoint('+address))+':');//прыжок после выделения памяти
// add(address+':');
add(' jmp _newmem'+inttostr(injectnr)+'');
bofset:=5;
while codesize>5 do
begin
add(' nop');
dec(codesize);
inc(bofset); // для посторения проверочных байта отмены
end;
add('_returnhere'+inttostr(injectnr)+':');
end;
delete(provbyte,1,bofset*2); // удаляем то чего не надо искать
dec(bofset,5);
for I := 1 to bofset do
provbyte:='90'+provbyte;
with disablecode do
begin
add(' aobscan(_faddress,'+provbyte+')');
add('');
// add(address+':');
add('_faddress-5:');
for i:=0 to length(originalcode)-1 do
add(' '+originalcode[i]);
add('');
add(' dealloc(_newmem'+inttostr(injectnr)+')');
x:='db';
for i:=0 to length(originalbytes)-1 do
x:=x+' '+inttohex(originalbytes[i],2);
add('//Alt: '+x);
end;
getenableanddisablepos(assemblescreen.lines,enablepos,disablepos);
//skip first comment(s)
if enablepos>=0 then
begin
while enablepos<assemblescreen.lines.Count-1 do
begin
if pos('//',trim(assemblescreen.Lines[enablepos+1]))=1 then inc(enablepos) else break;
end;
end;
for i:=enablecode.Count-1 downto 0 do
assemblescreen.Lines.Insert(enablepos+1,enablecode[i]);
getenableanddisablepos(assemblescreen.lines,enablepos,disablepos);
//skip first comment(s)
if disablepos>=0 then
begin
while disablepos<assemblescreen.lines.Count-1 do
begin
if pos('//',trim(assemblescreen.Lines[disablepos+1]))=1 then inc(enablepos) else break;
inc(disablepos);
end;
//only if there actually is a disable section place this code
for i:=disablecode.Count-1 downto 0 do
assemblescreen.Lines.Insert(disablepos+1,disablecode[i]);
end;
finally
enablecode.free;
disablecode.Free;
end;
symhandler.showmodules:=simbol;
//
{$endif}
end;
]]--
-- Количество попыток поиска сигнатуры, на тот случай если поиск окажеться долгим
-- может вмешаться пользователь остановить или продолжить поиск
local numberOfAttemptsForShowPermission = 1000
local CountOfnumberOfAttemptsForShowPermission = 0
local offsetSignature = 0
local lengthSignature = 0
local signature = ""
-- Уникальная сигнатура подбирается по первым байтам машинных инструкций от начала функции до её конца
-- Стремление к тому чтобы сигнатура была меньших размеров и была уникальна по правилу сканирования "+X-C-W"
--1. Получаем строку байт в функции
-- 1.2 Ищем адрес1 начала функции
-- 1.3 Ищем адрес2 конеца функции
-- Если адреса определить невозможно, то выводится сообщение об ошибке
-- 1.4 Дизассемблируя формируем сигнатуру от адреса1 до адреса2
-- 1.4.1 Формирование происходит по первым байтам одной инструкции в том случае
-- если размер инструкции болше 3 байт
-- заполнение не рабочих байт отмечается как "xx"
-- В итоге получаем длинную сигнатуру - строку байт в функции
repeat
--2. Создаются новый настройки поиска сигнатуры
-- 2.1 Поиск сигнатуры ведётся по её длине от 6 байт с места адреса, когда определены более трёх промежутков "xx" до длины сигнатуры
-- если сигнатура не находиться то она расползается в длину сначала вниз по 3 промежутка "xx", а затем вверх увеличивая увеличивая offsetSignature
-- если вся длина сигнатуры была просканирована и не нашлось уникальной, то появляеться сообщение об ошибке.
-- если сканирование очень затягивается больше 10 секунд, то появляеться сообщение "хочет ли пользователь дальше продолжать сканирование"
-- ....
-- Непосредственный поиск сигнатуры
local list = AOBScan(signature, "+X-C-W")
if ((results == nil) or (strings_getCount(list)>1) and stringlist_getString(results, 0)~=address) then
break -- успешный выход из цикла, уникальная сигнатура найдена
end
-- В противном случае засчитывается неудачаная попытка поиска сигнатуры
CountOfnumberOfAttemptsForShowPermission = CountOfnumberOfAttemptsForShowPermission + 1
if(CountOfnumberOfAttemptsForShowPermission > numberOfAttemptsForShowPermission) then
if (messageDialog()~="OK") then
showMessage("Поиск сигнатуры был остановлен пользователем")
--messageDialog("Ошибка. Не найден адрес внедрения.\n\rТрейнер будет закрыт!",1, 2)
return nil
end
end
until true
return signature
--[[ function getbytes():string;
adr:dword -- входящий адрес
var i,j,len,count:byte; frwrdaddr:dword; stlist:TstringList; s,s0,s1,intsr:string;
begin
frwrdaddr:=adr;
repeat
stlist.Add(disassemble(frwrdaddr)); // заполнили список ассемблерных инструкций типа '0061c2d3 - e8 61 c0 ff ff - call 00618339'
// frwrdaddr:=previousopcode(frwrdaddr)-1;
until frwrdaddr>=adr+120;
//После этого берём первые байты, если их количество не меньше 3 на опкод, остальные помечаем как xx
for i := 0 to stlist.Count-1 do
begin // Получаем:
s:=stlist.Strings[i];
s0:=copy(s,1,pos(' - ',s)); // адрес
delete(s,1,pos(' - ',s)+2);
s1:=copy(s,1,pos(' - ',s)); // байты
delete(s,1,pos(' - ',s)+2); // инструкция
intsr:=s;
//Если в строке байт находится больше трёх байт
len:=length(s1);
count:=(len div 3); //количество байт
s:='';
if (count>1)and(pos('push',intsr)=0) then
begin
s1:=copy(s1,1,3); // копируеме первый байт "FA "
for j := 2 to count
do s:=s+'xx '; // остальные затераем "хх хх хх хх "
s1:=s1+s; //s1:= "FA хх хх хх хх "
end
else // если байт меньше трёх то заливаем всё как "хх "
begin
for j := 1 to count
do s:=s+'xx ';
s1:=s; //s1: = "xx хх хх "
end;
result:=result+s1; //=)
end;
delete(result,(32*3),length(result)); //режем первые 32 байта
for I := 32 downto 1 do
delete(result,i*3,1);
while 'xx'=copy(result,length(result)-1,2) do
delete(result,length(result)-1,2);
stlist.Destroy; ]]--
end
function BeginGetLUACheatCode(aggregateMem, cheatName, signatre, newCode, stateOriginalCode )
--[[
]]--
end
function ENDGetLUACheatCode(aggregateMem, cheatName, signatre, newCode, stateOriginalCode )
--[[
]]--
end
function GetLUACheatCode(aggregateMem, cheatName, signatre, newCode, stateOriginalCode )
--[[
]]--
end
----^^^^^^^^^
-- Функции окоторые требуются для главной работы
function BeginGenerateAAscriptAggregateMem(newMemDescription, sizeMem) -- return bufferString
return [[
alloc(]]..newMemDescription..","..sizeMem..[[)
registersymbol(]]..newMemDescription..[[)
->>label]]..newMemDescription..[[:
->>newCode
->>adressessInjected
]]
end
function EndGenerateAAscriptAggregateMem(aggregateMem) -- return bufferString
local endScript = string.gsub(aggregateMem, "->>label", "")
endScript = string.gsub(endScript, "->>newCode", "")
endScript = string.gsub(endScript, "->>adressessInjected", "")
return endScript
end
function GenerateAAscriptAggregateMem(aggregateMem, cheatName, address, newCode, stateOriginalCode) -- return bufferString
local addressInjection = address
local adressReturnHere = 0
local originalCodeString = ""
local nopsString = ""
adressReturnHere, originalCodeString, nopsString = GetInfoInjection(address)
registerSymbol("returnHere_"..cheatName, adressReturnHere)
local script = preSubScript(aggregateMem,"->>label", "label("..cheatName..")")
script = preSubScript(script,"->>label", "registersymbol("..cheatName..")")
if (stateOriginalCode) then
script = preSubScript(script,"->>label", "label(originalcode_"..cheatName..")")
local buf = cheatName..":\n "..newCode.."\noriginalcode_"..cheatName..":"..originalCodeString.."\n jmp returnHere_"..cheatName
script = preSubScript(script,"->>newCode", buf)
else
script = preSubScript(script,"->>newCode", cheatName..":\n"..newCode.."\n jmp returnHere_"..cheatName)
end
local scriptAddMainTable = "[ENABLE]\n-->>address1[DISABLE]\n-->>address2"
scriptAddMainTable = preSubScript(scriptAddMainTable,"-->>address1", addressInjection..":\n jmp "..cheatName.."\n"..nopsString)
scriptAddMainTable = preSubScript(scriptAddMainTable,"-->>address2", addressInjection..":"..originalCodeString)
scriptAddMainTable = string.gsub(scriptAddMainTable, "-->>address1", "")
scriptAddMainTable = string.gsub(scriptAddMainTable, "-->>address2", "")
SetScriptInEntryCETable(cheatName,scriptAddMainTable)
return script
end
function ByteScan(signature) -- return address
local results = AOBScan(signature, "+X-C-W")
if (results == nil) then
messageDialog("Ошибка. Не найден адрес внедрения.\n\rТрейнер будет закрыт!",1, 2)
closeCE()
return
end
local address = stringlist_getString(results, 0)
return address
end
function GenerateAAscriptAggregateMemWithSignature(aggregateMem, cheatName, signature, signatureOffset, newCode, stateOriginalCode )
local workAddress = ByteScan(signature)
if (signatureOffset ~=0) then
workAddress = string.format("%x", ("0x"..workAddress) + signatureOffset)
end
return GenerateAAscriptAggregateMem(aggregateMem, cheatName, workAddress, newCode, stateOriginalCode)
end
function AddCheatInCETableFillnopsInstruction(cheatName, address)
adressReturnHere, originalCodeString, nopsString = GetInfoInjection(address)
local scriptAddMainTable = "[ENABLE]\n-->>address1[DISABLE]\n-->>address2"
local countBytes = getInstructionSize(address)
local nopsString = " db"
for i = 1, countBytes do
nopsString = nopsString.." 90"
end
scriptAddMainTable = preSubScript(scriptAddMainTable,"-->>address1", address..":\n"..nopsString)
scriptAddMainTable = preSubScript(scriptAddMainTable,"-->>address2", address..":"..originalCodeString)
scriptAddMainTable = string.gsub(scriptAddMainTable, "-->>address1", "")
scriptAddMainTable = string.gsub(scriptAddMainTable, "-->>address2", "")
SetScriptInEntryCETable(cheatName,scriptAddMainTable)
end
function AddCheatInCETableFillnopsInstructionWithSignature(cheatName, signature, signatreOffset)
local workAddress = ByteScan(signature)
workAddress = string.format("%x", ("0x"..workAddress) + signatreOffset)
AddCheatInCETableFillnopsInstruction(cheatName, workAddress)
end
----^^^^^^^^^
---------------------------------------------------------
local frmUserTrainer = nil -- форма конструируемого трейнера
local messageLabel = nil
local _InitFunction -- указатель на пользовательскую функцию инициализации читов
local attach = false -- подключен ли процесс
-- Cтрока информации в трейнере
local function SendMessageFrmTrainer(message)
control_setCaption(messageLabel, message)
end
-- Обработчик закрытия главной формы трейнера
local function FormClose(sender)
closeCE()
return caHide
end
-- Создание неготовой формы трейнера
local function CreateFormTrainer(nameTrainer)
frmUserTrainer = createForm(true)
control_setCaption(frmUserTrainer, nameTrainer)
control_setSize(frmUserTrainer, 400, 200)
form_centerScreen(frmUserTrainer)
form_onClose(frmUserTrainer, FormClose)
messageLabel = createLabel(frmUserTrainer)
control_setAlign(messageLabel, alBottom)
SendMessageFrmTrainer("Трейнер НЕ готов к работе")
end
-------------------------------------
local ObjectHotKeys = {}
local countObjectHotKeys = 0 -- countObjectHotKeys равное также кол-ву записей в главной таблице
local adrList = nil
local baseHotKey = "CTRL"
-- Функция группировки АА-скриптов в один (для того чтобы хоткей вешался на один сркипт вместо нескольких)
function GroupAA(nameGRcheat, cheats)
if (adrList == nil) then
adrList = getAddressList()
end
countObjectHotKeys = addresslist_getCount(adrList)
mainGRScript = "[ENABLE]-->>marker1\n[DISABLE]\n-->>marker2"
local delIndexes = {}
local count_delIndexes = 0
local zisetable = table.getn(cheats)
local description = ""
for i = 1,countObjectHotKeys do
local te = addresslist_getMemoryRecord(adrList, i-1)
description = memoryrecord_getDescription(te)
for j=1,zisetable do
if (cheats[j] == description) then
local script = memoryrecord_getScript(te)
local leftPos = 10 -- длина "[ENABLE]\n" 9 символов и плюс переход +1
local rigthPos = string.find(script, "%[DISABLE%]")
mainGRScript = preSubScript(mainGRScript,"-->>marker1",string.sub(script, leftPos, rigthPos-2))
leftPos = rigthPos + 10 + 1
rigthPos = string.len(script)
mainGRScript = preSubScript(mainGRScript,"-->>marker2",string.sub(script, leftPos, rigthPos))
count_delIndexes = count_delIndexes + 1
delIndexes[count_delIndexes] = te
break
end
end
end
for i = 1,count_delIndexes do
memoryrecord_delete(delIndexes[i])
end
mainGRScript = string.gsub(mainGRScript, "-->>marker1", "")
mainGRScript = string.gsub(mainGRScript, "-->>marker2", "")
SetScriptInEntryCETable(nameGRcheat,mainGRScript)
end
local function CheatAction(indexCheat)
local te = addresslist_getMemoryRecord(adrList, indexCheat-1)
if (memoryrecord_isActive(te)) then
memoryrecord_unfreeze(te)
else
memoryrecord_freeze(te, 0)
end
beep()
end
-- Обработчик хот-кеев
function onHotkey1(hotkey)
CheatAction(1)
end
function onHotkey2(hotkey)
CheatAction(2)
end
function onHotkey3(hotkey)
CheatAction(3)
end
function onHotkey4(hotkey)
CheatAction(4)
end
function onHotkey5(hotkey)
CheatAction(5)
end
function onHotkey6(hotkey)
CheatAction(6)
end
function onHotkey7(hotkey)
CheatAction(7)
end
function onHotkey8(hotkey)
CheatAction(8)
end
function onHotkey9(hotkey)
CheatAction(9)
end
local arrayFunction = {}
arrayFunction[1] = onHotkey1
arrayFunction[2] = onHotkey2
arrayFunction[3] = onHotkey3
arrayFunction[4] = onHotkey4
arrayFunction[5] = onHotkey5
arrayFunction[6] = onHotkey6
arrayFunction[7] = onHotkey7
arrayFunction[8] = onHotkey8
arrayFunction[9] = onHotkey9
-- Создание контролов на форме трейнера
local function CreateControlsForTrainer()
--сделать формирование данных
-- todo: сделать слотов больше 9
if (adrList == nil) then
adrList = getAddressList()
end
countObjectHotKeys = addresslist_getCount(adrList)
if (countObjectHotKeys < 1 or countObjectHotKeys > 9) then
showMessage("В этой реализации программы читов не может быть меньше 1 или больше 9. Трейнер будет закрыт")
FormClose(nil)
return nil
end
for i = 1,countObjectHotKeys do
local te = addresslist_getMemoryRecord(adrList, i-1)
local description = memoryrecord_getDescription(te)
--[[
GenericHotkey Class : (Inheritance: Object)
createHotkey(function, key, ...) : returns an initialized GenericHotkey class object. Maximum of 5 keys
generichotkey_setKeys(hotkey, key, ....)
generichotkey_onHotkey(hotkey, function)
]]--
ObjectHotKeys[i] = createHotkey(arrayFunction[i], VK_CONTROL, VK_0 + i) --string.format("%s",i)
generichotkey_setKeys(ObjectHotKeys[i], VK_CONTROL, VK_0 + i)
generichotkey_onHotkey(ObjectHotKeys[i], arrayFunction[i])
CheatLbl = createLabel(frmUserTrainer)
control_setAlign(CheatLbl, alTop)
local stringHotKey = baseHotKey.."+"..i
control_setCaption(CheatLbl, i..") "..description..": "..stringHotKey)
end
CheatLbl = createLabel(frmUserTrainer)
control_setAlign(CheatLbl, alTop)
control_setCaption(CheatLbl, "Cheats:")
SendMessageFrmTrainer("Трейнер готов к работе")
end
-- Событие открытия процесса
function onOpenProcess(processid)
--print("вызов onOpenProcess")
if (attach) then
return
end
attach = true
--openProcess(processid)
_InitFunction()
CreateControlsForTrainer()
end
-- Главная функция иницилазации
function AAgenINIT(nameTrainer, processName, InitFunction)
-- todo: раскомментировать строку ниже когда все функции будут отлажены
--hideAllCEWindows()
aalist = getAutoAttachList()
stringlist_add(aalist, processName);
CreateFormTrainer(nameTrainer)
_InitFunction = InitFunction
end-- Функция создаёт скрипт, который выделит память для отдельного чита. Сам скрипт добавиться в главную таблицу
Хочу прокомментировать недостатки.
Это версия не для 64-разрядных приложений,а только для 32-разрядных.
Пока требуется вручную забивать сигнатуру. Я же пользовался CE 5.6 русская версия с нашего сайта для генерации сигнатур из автоаассемблера.
Групп читов можно сделать только 9,а в группах же может быть любое количество читов.
Дизайн трейнера пока хромает.
Возможны какие-то ошибки...
Достоинства:
1) Читы можно объеденять в группы как было показано в примере выше, они все могут активироваться по одной горячей клавише.
2) Вся нудная разметка Автоассемблерного скрипта скрывается от вас.
3) Читы тела которых должны быть в выделенной памяти формируются только в одном участке памяти, а не в нескольких при каждом alloc(название метки, размер памяти)
4) Поиск адреса внедрения по сигнатурам увеличивает шанс работы трейнера с разными патчами игр на 30%-70% чем если бы вы это делали просто по адресам внедрения. Это в какой-то степени избавляет вас от написания трейнеров к новым патчам. Но этот метод внедрения с увеличением шансов работы трейнера ещё далеко не предел... можно повысить и до %60-%80.
5) Горячие клавиши сами выставляются для слотов от 1 до 9. Конечно, это может быть неудобно, но пока останется так.
-
Не совсем правильное суждение. Когда ты просто идёшь изменяя Z, то работает один или несколько участков кода. Когда ты прыгаешь работает другой один или несколько участков кода. Конечно, участки кода прыжка и перемещения по координатным плоскостям где-то друг с другом сцепляются и могут работать "в общей логике" перемещения. Но все равно есть участки кода работающие отдельно в той или иной ситуации с теми или иными адресами данных о перемещении.
Поэтому очевидно, что для создания супер прыжка именно для твоего героя, надо искать массу твоего героя. Если у всех героев масса одна, то делать фильтр... Если хочешь чтобы все прыгали, то нужно исправить массу всех или же исправить силу гравитации...
-
А как этот брейкпоинт убрать и ваще для чего он?
Сначала поищи и прочитай информацию на форуме и таких вопросов возникать не будет.
-
Количество прерываний на инструкции работающей с адресом (на этот адрес изначально поставили брейкпоинт)
-
У AOBScan могут быть параметры сканирования (ищите описание).
Пример функции возвращающей первый найденный адрес сигнатуры в типе областей памяти с защитой "выполнение кода".
function ByteScan(signature) -- return address
local results = AOBScan(signature, "+X-C-W")
if (results == nil) then
messageDialog("Ошибка. Не найден адрес внедрения.\n\rТрейнер будет закрыт!",1, 2)
closeCE()
return
end
local address = stringlist_getString(results, 0)
return address
endВажно отметить, что можно работать с несколькими возвращаемыми адресами, а не только с первым как это было в автоассемблере.
-
В справке CE 6.0 в разделе Script engine есть такая функция:
generateAPIHookScript (address, addresstojumpto, addresstogetnewcalladdress OPT) : Generates an auto assembler script which will hook the given address when executedЕё задача перехватить выполнение кода, сделать всё необходимое, например, сделать чит-код; сохранить параметры в файлы и т.п. ... и в конце-концов вернуть выполнения кода в прежнее русло. Данный метод работает эффективнее отладки. Т.к. отладка затрачивает больше ресурсов работы процессора чем способ generateAPIHookScript.
Этой функцией можно воспользоваться следующим образом (пример Дакрк Байта):
globalalloc(MyPeekMessageHook,2048)
globalAlloc(OriginalPeekMessageA,4)
label(placeyourbphereifyouliketoseetheresults)
registersymbol(placeyourbphereifyouliketoseetheresults)
MyPeekMessageHook:
//do whatever you want in your hook
//I could just do jmp [OriginalPeekMessageA] if I wanted
//but this way the parameters are more easily readable for me
//and lets me mess with the results
push ebp
mov ebp,esp
//ebp=old ebp
//ebp+4=old return address
//ebp+8=first parameter
//ebp+c=second
//ebp+10=third
//ebp+14=fourth
//ebp+18=fifth
push [ebp+18]
push [ebp+14]
push [ebp+10]
push [ebp+c]
push [ebp+8]
call [OriginalPeekMessageA]
placeyourbphereifyouliketoseetheresults:
//eax now contains the return value.
//and this space gives you room to tamper with the results
pop ebp//restore ebp to what it was
ret 14 //undo the pushed parameters and return
]]
)
myhookscript=generateAPIHookScript("PeekMessageA", "MyPeekMessageHook", "OriginalPeekMessageA");
if (myhookscript~=nil) then
autoAssemble(myhookscript)
endautoAssemble([[
Там где вы увидите двойные квадратные скобки - это автоассемблерный код. Измените его как вам потребуется.
Из примера вы можете видеть, что PeekMessageA перекрывается на MyPeekMessageHook с выполнением OriginalPeekMessageA. Ещё раз обращу внимание, что в данном случае generateAPIHookScript очевидно будет эффективнее работать чем с debug_setBreakpoint(см. тутор2).
Ещё пример:
globalalloc(MyMessageBoxHook,2048)
alloc(message,11)
alloc(caption,3)
globalalloc(OriginalMessageBoxA,4)
message:
db 'blablablaa',0
caption:
db 'XD',0
MyMessageBoxHook:
push ebp
mov ebp,esp
push #0
push caption
push message
push #0
call [OriginalMessageBoxA]
pop ebp
ret 10
]]
)
myhookscript=generateAPIHookScript("MessageBoxA", "MyMessageBoxHook", "OriginalMessageBoxA");
if (myhookscript~=nil) then
autoAssemble(myhookscript)
endautoAssemble([[
-
Результат, которого мы должны добиться в LUA консоли Cheat Engine следующий:
1) 0x003f00b8: 08 00 00 00
2) 0x003f00bc: 00 00 00 00
3) 0x003f00c0: 00 00 00 00
4) 0x003f00c4: 00 00 00 00
... (вырезано)
247) 0x003f0490: 00 00 00 00
248) 0x003f0494: 00 00 00 00
249) 0x003f0498: 00 00 00 00
250) 0x003f049c: 00 00 00 00Сделать это можно так (leftaddr замените на свой адрес):
function onclickBtn(sender)
leftaddr = 0x3f00b8
rigthaddr = leftaddr+1000
count =1
repeat
x1,x2,x3,x4 = readBytes(leftaddr,4)
s = string.format("%3d) 0x%08x: %02x %02x %02x %02x",count,leftaddr,x1,x2,x3,x4 )
print(s)
leftaddr= leftaddr + 4
count = count +1
until(leftaddr >=rigthaddr)
end
frm = createForm()
control_setCaption(frm, "Вывод дампа памяти")
form_centerScreen(frm)
control_setSize(frm, 270,70)
btn=createButton(frm)
control_setCaption(btn, "Вывести дамп")
control_setPosition(btn,20,10)
control_setSize(btn, 230,50)
control_onclick(btn, onclickbtn)В этом примере создали форму с кнопкой. При нажатии кнопки в консоли выводится информация.
-
Требования и информация:
1) Текущая версия Lua-поддержки для Cheat Engine 6.1 и выше, поэтому если у вас нет версии 6.1, то установите с официального сайта Cheat Engine
2) Для просмотра и редактирования Luaкода установите: Notepad++ (найдёте в поисковике)
3) Все поддерживаемые Lua функции, а так же их краткая документация в комментариях находятся в файле "main.lua". Этот файл находится в каталоге с программой Cheat Engine. В справке CE те же описания функций Lua для CE.
4) "main.lua" загружается и выполняется автоматически при запуске CE. Вы можете редактировать этот файл для загрузки ваших собственных модулей Lua.
5) "defines.lua" содержит описания определений тех или иных констант
6) Новые комментарии к Lua функциям вы можете при случае увидеть здесь в SDK а здесь описания
7) Если так случится, что вы не знаете как работает Lua функция, то ответ можно найти в SDK начав свой путь поиска проблемы с этой страницы.
Справочное руководство как писать программы на Lua пока ищите в Интернете.
Напоминаю, что если очень нужно, то последнюю версию CE вы можете скомпилировать из SDK с официального сайта. На нашем форуме есть руководство как это сделать.
Ниже будет располагается информация из того же main.lua, который у вас уже есть только в лучшем виде для понимания. (пока заниматься этим некогда, тема В РАЗРАБОТКЕ)
-
Какая система?
Win7 (64 разрядная)
-
Ну как найти?! Так же как на видео было показано )
-
ANT' date='02 Июнь 2011 - 15:01' timestamp='1307005287' post='3216']
Трейнми для тренеровки.
Я сделал статью по этому трейнми. Кому надо то она находится здесь.
-
Здесь обсуждаем статью "Делаем супер прыжок для Jtrainme.exe"
-
Можно найти. Но ты найдёшь лишь участок кода, а что именно в нём модифицировать может быть разным в других играх. Кстати движок там модифицирован, если не ошибаюсь это было сказано на видео. И если там отдача и полностью снимается, то всё равно выстрелы в одну точку точку не происходят из-за остающегося эффекта кучности при стрельбе. Когда смотришь не в прицел пули не попадают в одну точку.
-
Всех поздравлю с официальным реализом CE 6.1
Добавлю, что в течении недели могут быть различные "патчи" для 6.1. После будет начало 6.2. Об этом писал Dark Byte.
От себя же прокомментирую, что 6.1 финальная версия ещё сыровата. Судя по тому кол-ву багов которое было чуть ли не каждый день отрапортовано разработчику CE их ещё может быть довольно много.
Все скачиваем и пользуемся.
-
Я скачиваю файлы с форума без проблем. ZOCKIR, проблемы явно у только у тебя.
-
У тебя получилось сделать Super Jump? И какими методами в трейнми адрес искать?
там же паузы нет
Ищем адрес координаты X бегая влево или вправо. Затем находим Y рядом с адресом X. На Y ставим бряк на запись... определяем какая инструкция увеличивала Y. Кропотливо ищем "предел увеличения" выраженном в том или ином понятии - например, силы отталкивания (ищем до инструкции которая уменьшает Y). Возможно инструкция которая увеличивает и уменьшает Y одна и таже в этом случае надо исследовать внешние вызовы. Я этот трейнми не ломал, но стоило бы. Возможно игру лучше поставить в оконный режим чтобы спокойно отлаживать при пошаговой отладке. Если выкрою время, то попробую исследовать. У меня какое-то дежавю, я этот трейнми уже где-то видел у нас.
-
Если я правильно понял, что цепочка указателей не работает в сгенеррированом трейнере, то, к сожалению, я не знаю причины. Я таким способом никогда не пользуюсь, поэтому актуальность нахождения причины не вижу. Т.е. я тратить время на это не буду. Указатели можно строить в автоассемблерных скриптах, что я всегда и делаю и советую остальным. Если это явная ошибка можешь её отписать разработчику Cheat Engine.
-
Спасибо за ответ.
Знаешь, просто не понятно, что тебе мешало написать программу на ассемблере по Дельфи коду. Ведь это проблема осталась и никуда не делась... Зато ты для себя выяснил главное, что можно на MASM написать программу написанную на Дельфи. И задать этот вопрос поисковику кстати тоже можно было
Наш модуль TrainerGen.lua для создания .CETRAINER-трейнеров
in Создание трейнеров в специальных студиях
Опубликовано
Новая версия модуля TrainerGen.lua: TrainerGen.rar
Позволяет формировать трейнер вида:
По примеру разметки формата .CETRAINER:
Основные пользовательские функции:
1) TrainerShow(nameTrainer, processName, frmWidth, frmHeigth, initFunction)
2)
BeginGenerateAA(newMemDescription, sizeMem)
-----GenerateAA(aggregateMem, cheatName, address, newCode, stateOriginalCode)
-----GenerateAAWithSignature(aggregateMem, cheatName, signature, typeMem, signatureOffset, newCode, stateOriginalCode )
-----AddRegistersymbols(aggregateMem, tableNewSymbols)
EndGenerateAA(aggregateMem)
3)
FillnopsInstruction_AndAddInCETable(cheatName, address)
FillnopsInstructionWithSignature_AndAddInCETable(cheatName, signature, typeMem, signatreOffset)
4) GroupAA(nameGRcheat, tableCheats)
5) Функция для быстрых тестов из консоли LUA:
GenerateAAscriptPageMem_AndAddInCETable( cheatName, address, injectInstruction, originalcode )
-----
Как пользоваться этими функциями пока описывать не буду,т.к. могут быть новые изменения и придётся описания переделывать...