Да, привет!
Ты всё понял верно, шаги у тебя правильные.
На самом деле, нужно понять на каком моменте что-то ломается.
Сообщение от
UnknownPerson
Код успешно регистрирует клиентскую команду и при использовании ее в игре краша нет, но и хандлер ничего не выполняет, а служит обычной "заглушкой"
Шаг первый. Нужно проверить, работает ли твоя заглушка. В консоль твоей программы выпиши адрес области, которая выделяется VirtualAllocEx (эта же функция и возвращает этот адрес). После инъекции, уже при работе программы, открываешь Cheat Engine (CE), дальше Memory Viewer, дальше Ctrl + G и вставляй этот адрес. У тебя должна открыться твоя же функция (те байты, которые ты написал). Выбираешь любой из них (любую строку) и нажимаешь F5 (либо ПКМ и «Break and trace instructions»). А теперь попробуй ввести в чат команду, которую ты зарегистрировал. CE должен будет остановить твою игру, а в меню Memory Viewer появится активная кнопка «Продолжить» (как при паузе). Если так, то это оно! Значит игра проходит через твою заглушку.
Сообщение от
UnknownPerson
Но игра вызывает краш после ввода команды и попытки выполнить этот код. Хочу также подметить, что в ассемблере я не силен от слова совсем
Шаг второй. Я думаю, что в ASM коде мало кто силён. Если шаг первый успешно выполнен, то единственная задача — правильно написать функцию, не сломав при этом значения регистров и программный стек. Прототип твоей функции следующий:
C++:
Код:
void
__cdecl
handler
(
const
char
*
)
;
И никто не мешает тебе в отдельной программе (не основной!) написать на C++ ту функцию, которая тебе нужна:
C++:
Код:
// создаёшь прототипы своих функций (я не знаю какие аргументы там)
typedef
void
(
__thiscall
*
AddEntry
)
(
int
,
int
,
const
char
*
,
int
,
int
,
int
)
;
int
SampDll
;
// получаешь адрес модуля samp.dll
void
__cdecl
handler
(
const
char
*
arg
)
{
if
(
strlen
(
arg
)
==
0
)
reinterpret_cast
(
SampDll
+
0x67460
)
(
SampDll
+
0x26E8C8
,
8
,
"text"
,
0x0
,
0xFFFFFF
,
0xFFFFFF
)
;
.
.
.
}
А дальше компилируешь это всё дело в x32. Можешь в коде где-то в
написать
[CODE]
std::cout Only Bytes») и вставить в массив. Всю неприятную работу по созданию ASM кода выполнит компилятор. Если изначальные прототипы функци
й (не только твоей, но и тех, что ты вызываешь внутри) верны, то краша быть не должно.
Сообщение от
Спойлер
Даже при краше пишет адрес краша («Exception at address ...»), так ты можешь посмотреть, где и что конкретно вызывает краш.
upd.
Чтобы получить адрес модуля
воспользуйся этой функцией (это можно делать как внутри твоего вызова каждый раз, так и один раз при запуске):
C++:
Код:
DWORD
GetProcId
(
const
char
*
procname
)
{
PROCESSENTRY32 pe
;
HANDLE hSnap
;
pe
.
dwSize
=
sizeof
(
PROCESSENTRY32
)
;
hSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
NULL
)
;
if
(
Process32First
(
hSnap
,
&
pe
)
)
{
do
{
if
(
strcmp
(
pe
.
szExeFile
,
procname
)
==
0
)
break
;
}
while
(
Process32Next
(
hSnap
,
&
pe
)
)
;
}
return
pe
.
th32ProcessID
;
}
HMODULE
GetModuleHandleExtern
(
const
char
*
szModuleName
,
DWORD dwProcessId
)
{
if
(
!
szModuleName
||
!
dwProcessId
)
{
return
NULL
;
}
HANDLE hSnap
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPMODULE
,
dwProcessId
)
;
if
(
hSnap
==
INVALID_HANDLE_VALUE
)
{
return
NULL
;
}
MODULEENTRY32 me
;
me
.
dwSize
=
sizeof
(
MODULEENTRY32
)
;
if
(
Module32First
(
hSnap
,
&
me
)
)
{
while
(
Module32Next
(
hSnap
,
&
me
)
)
{
if
(
!
strcmp
(
me
.
szModule
,
szModuleName
)
)
{
CloseHandle
(
hSnap
)
;
return
me
.
hModule
;
}
}
}
CloseHandle
(
hSnap
)
;
return
NULL
;
}
Использование:
Код:
HMODULE SampDll
=
GetModuleHandleExtern
(
"samp.dll"
,
GetProcId
(
"gta_sa.exe"
)
)
;
// HMODULE — это обычный указатель, который занимает 4 байта в x32. Поэтому можешь использовать C-cast: (unsigned int)SampDll
Будут еще вопросы — пиши.