HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > ПРОГРАММИРОВАНИЕ > С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 27.04.2024, 15:51
g305noobo
Постоянный
Регистрация: 24.09.2020
Сообщений: 364
С нами: 2966237

Репутация: 148
По умолчанию

Всем привет! Не трудно догадаться, что в этой теме речь будет идти о использовании LUAскриптов в связке с MoonLoader API из под C++.

Вообще это довольно интересная тема, потому что в основном в сампе все ограничиваются использованием одного ЯП (языка программирования), а ведь можно использовать одновременно почти все фичи, благо которых в нашем арсенале очень и очень много.

Например можно реализовать меню на LUA, а функционал на C++: https://www.blast.hk/threads/205273/

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

- C++ Основа [плагин]

- C++Структура проекта / реализация функционала

- LUA Готовые функции, работающие с GTA / SAMP для использовния в реализации функционала в пункте выше

Единственные минусы, которые по-моему мнению есть в подобных решениях это:

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

- излишние зависимости: у этого пункта есть как минусы, так и плюсы. Например, если мы создаем плагин, в котором будем использовать MoonLoader API, то очевидно, что мы зависим от MoonLoader. Однако, как плюс, весь функционал зачастую дублируется; например, функция для регистрации команды может повторяться во многих ASI плагинах. К этому мы добавляем SampFuncs, который экспортирует эту функцию.

Хотелось бы реализовать что-то вроде либы для приятного использования этого всего, если кто-то захочет попробовать, могу отправить часть моей "попытки"

Реализация

Создать плагин, который будет использовать MoonLoader API, довольно просто, и вариантов самой реализации много. Я же буду использовать экспортируемые из lua51.dll, а также хук функции "lua_getfield" из того lua51.dll, эта функция используется в MoonLoader и нужна для того чтобы получить значение по имени ключа из таблицы LUA.

C++:





Код:
using
lua_getfield_t
=
void
(
__cdecl
*
)
(
lua_State
*
L
,
int
index
,
const
char
*
k
)
;


В этой функции мы перехватываем следующее:

- указатель на структуру lua_State(благодаря ей мы будем взаимодействовать)

- индекс на структуру стека (где находится LUAтаблица, из которой нужно получить значение)

- название ключа (из которого нужно получить значение)

Сам хук выглядит так:

C++:





Код:
class
c_hooks
{
public
:
typedef
struct
lua_State
;
using
lua_getfield_t
=
void
(
__cdecl
*
)
(
lua_State
*
L
,
int
index
,
const
char
*
k
)
;
static
lua_getfield_t lua_getfield_p
;
static
void
lua_getfield
(
lua_State
*
L
,
int
index
,
const
char
*
k
)
{
return
lua_getfield_p
(
L
,
index
,
k
)
;
}
}
;
c_hooks
::
lua_getfield_t c_hooks
::
lua_getfield_p
=
nullptr
;
void
install_hook
(
)
{
MH_Initialize
(
)
;
auto
lua_getfield_adr
=
GetProcAddress
(
GetModuleHandleA
(
"lua51.dll"
)
,
"lua_getfield"
)
;
MH_CreateHook
(
reinterpret_cast

(
lua_getfield_adr
)
,
&
c_hooks
::
lua_getfield
,
reinterpret_cast

(
&
c_hooks
::
lua_getfield_p
)
)
;
MH_EnableHook
(
reinterpret_cast

(
lua_getfield_adr
)
)
;
}


Поскольку функция "lua_getfield" вызывается почти постоянно в различных местах, нам необходимо фильтровать эти вызовы и брать указатель на структуру lua_State только из скриптов. Сделать это можно легко, так как при инициализации скрипта MoonLoader обращается к ключу "main", на это мы и будем ориентироваться.

C++:





Код:
static
void
lua_getfield
(
lua_State
*
L
,
int
index
,
const
char
*
k
)
{
if
(
strstr
(
k
,
"main"
)
)
{
// что тут???
}
return
lua_getfield_p
(
L
,
index
,
k
)
;
}


Всё почти готово! Теперь давайте определим парочку функций из lua51.dll, которые понадобятся чуть дальше..

C++:





Код:
typedef
int
(
*
L_loadstring_t
)
(
lua_State
*
,
const
char
*
)
;
typedef
const
char
*
(
*
tolstring_t
)
(
lua_State
*
,
int
,
size_t
*
)
;
L_loadstring_t L_loadstring
=
nullptr
;
tolstring_t tolstring
=
nullptr
;


Получаем эти функции

C++:





Код:
auto
hLua
=
GetModuleHandleA
(
"lua51.dll"
)
;
L_loadstring
=
(
L_loadstring_t
)
GetProcAddress
(
hLua
,
"luaL_loadstring"
)
;
tolstring
=
(
tolstring_t
)
GetProcAddress
(
hLua
,
"lua_tolstring"
)
;


Пример использования

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

Для этого создадим мини-функцию-обёртку

C++:





[CODE]
void
load_string
(
lua_State
*
L
,
const
std
::
string
&
code
)
{
if
(
L
==
nullptr
)
{
std
::
cerr



g_lua это мой мини класс враппер для всего этого

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

Теперь осталось просто вызвать эту функцию в хуке с любым кодом, который вы бы хотели воспроизвести внутри MoonLoader

C++:





Код:
static
void
lua_getfield
(
lua_State
*
L
,
int
index
,
const
char
*
k
)
{
if
(
strstr
(
k
,
"main"
)
)
{
g_lua
.
load_string
(
L
,
"print('Hello, from cpp!')"
)
;
}
return
lua_getfield_p
(
L
,
index
,
k
)
;
}


Итог

Получаем такую картину, в которой каждый скрипт вызвал нужный нам код



 
Ответить с цитированием

  #2  
Старый 27.04.2024, 19:46
xSkateboard
Познающий
Регистрация: 21.05.2021
Сообщений: 39
С нами: 2622585

Репутация: 38
По умолчанию

В WoW так делают lua unlocker'ы protected функций от близзов или на базе этого пишут своих ботов или читы. Интересная тема
 
Ответить с цитированием

  #3  
Старый 28.04.2024, 00:59
вайега52
Флудер
Регистрация: 19.06.2022
Сообщений: 2,997
С нами: 2055431

Репутация: 3


По умолчанию

[QUOTE="g305noobo"]

Всем привет! Не трудно догадаться, что в этой теме речь будет идти о использовании LUAскриптов в связке с MoonLoader API из под C++.
Вообще это довольно интересная тема, потому что в основном в сампе все ограничиваются использованием одного ЯП (языка программирования), а ведь можно использовать одновременно почти все фичи, благо которых в нашем арсенале очень и очень много.

Например можно реализовать меню на LUA, а функционал на C++: https://www.blast.hk/threads/205273/

Помимо использования подобных фишек как реализация меню и функционала на разных ЯП мы можем даже сделать такую конструкцию:
- C++ Основа [плагин]
- C++Структура проекта / реализация функционала
- LUA Готовые функции, работающие с GTA / SAMP для использовния в реализации функционала в пункте выше

Единственные минусы, которые по-моему мнению есть в подобных решениях это:
- другая изначальная задумка: никто ведь не плагировал использовать функции для скриптов в плагинах, в связи с этим возможны какие-то неожиданные проблемы.
- излишние зависимости: у этого пункта есть как минусы, так и плюсы. Например, если мы создаем плагин, в котором будем использовать MoonLoader API, то очевидно, что мы зависим от MoonLoader. Однако, как плюс, весь функционал зачастую дублируется; например, функция для регистрации команды может повторяться во многих ASI плагинах. К этому мы добавляем SampFuncs, который экспортирует эту функцию.

Хотелось бы реализовать что-то вроде либы для приятного использования этого всего, если кто-то захочет попробовать, могу отправить часть моей "попытки"

Реализация
Создать плагин, который будет использовать MoonLoader API, довольно просто, и вариантов самой реализации много. Я же буду использовать экспортируемые из lua51.dll, а также хук функции "lua_getfield" из того lua51.dll, эта функция используется в MoonLoader и нужна для того чтобы получить значение по имени ключа из таблицы LUA.

C++:





Код:
using
lua_getfield_t
=
void
(
__cdecl
*
)
(
lua_State
*
L
,
int
index
,
const
char
*
k
)
;


В этой функции мы перехватываем следующее:
- указатель на структуру lua_State(благодаря ей мы будем взаимодействовать)
- индекс на структуру стека (где находится LUAтаблица, из которой нужно получить значение)
- название ключа (из которого нужно получить значение)

Сам хук выглядит так:

C++:





Код:
class
c_hooks
{
public
:
typedef
struct
lua_State
;
using
lua_getfield_t
=
void
(
__cdecl
*
)
(
lua_State
*
L
,
int
index
,
const
char
*
k
)
;
static
lua_getfield_t lua_getfield_p
;
static
void
lua_getfield
(
lua_State
*
L
,
int
index
,
const
char
*
k
)
{
return
lua_getfield_p
(
L
,
index
,
k
)
;
}
}
;
c_hooks
::
lua_getfield_t c_hooks
::
lua_getfield_p
=
nullptr
;
void
install_hook
(
)
{
MH_Initialize
(
)
;
auto
lua_getfield_adr
=
GetProcAddress
(
GetModuleHandleA
(
"lua51.dll"
)
,
"lua_getfield"
)
;
MH_CreateHook
(
reinterpret_cast

(
lua_getfield_adr
)
,
&
c_hooks
::
lua_getfield
,
reinterpret_cast

(
&
c_hooks
::
lua_getfield_p
)
)
;
MH_EnableHook
(
reinterpret_cast

(
lua_getfield_adr
)
)
;
}


Поскольку функция "lua_getfield" вызывается почти постоянно в различных местах, нам необходимо фильтровать эти вызовы и брать указатель на структуру lua_State только из скриптов. Сделать это можно легко, так как при инициализации скрипта MoonLoader обращается к ключу "main", на это мы и будем ориентироваться.

C++:





Код:
static
void
lua_getfield
(
lua_State
*
L
,
int
index
,
const
char
*
k
)
{
if
(
strstr
(
k
,
"main"
)
)
{
// что тут???
}
return
lua_getfield_p
(
L
,
index
,
k
)
;
}


Всё почти готово! Теперь давайте определим парочку функций из lua51.dll, которые понадобятся чуть дальше..

C++:





Код:
typedef
int
(
*
L_loadstring_t
)
(
lua_State
*
,
const
char
*
)
;
typedef
const
char
*
(
*
tolstring_t
)
(
lua_State
*
,
int
,
size_t
*
)
;
L_loadstring_t L_loadstring
=
nullptr
;
tolstring_t tolstring
=
nullptr
;


Получаем эти функции

C++:





Код:
auto
hLua
=
GetModuleHandleA
(
"lua51.dll"
)
;
L_loadstring
=
(
L_loadstring_t
)
GetProcAddress
(
hLua
,
"luaL_loadstring"
)
;
tolstring
=
(
tolstring_t
)
GetProcAddress
(
hLua
,
"lua_tolstring"
)
;


Пример использования
Все готово для использования, теперь давайте воспользуемся ранее полученными функциями и попробуем воспроизвести какой-нибудь код на LUA.
Для этого создадим мини-функцию-обёртку

C++:





[CODE]
void
load_string
(
lua_State
*
L
,
const
std
::
string
&
code
)
{
if
(
L
==
nullptr
)
{
std
::
cerr

C++:





Код:
LSHook
::
LSHook
(
)
{
auto
luaLibAddress
=
GetModuleHandleA
(
"lua51.dll"
)
;
if
(
!
luaLibAddress
)
return
;
luaL_loadstring
=
reinterpret_cast

(
GetProcAddress
(
luaLibAddress
,
"luaL_loadstring"
)
)
;
lua_pcall
=
reinterpret_cast

(
GetProcAddress
(
luaLibAddress
,
"lua_pcall"
)
)
;
auto
luaL_newstateAddress
=
GetProcAddress
(
luaLibAddress
,
"luaL_newstate"
)
;
luaL_newstateHook
.
set_dest
(
luaL_newstateAddress
)
;
luaL_newstateHook
.
set_cb
(
[
this
]
(
auto
&&
.
.
.
args
)
{
return
luaL_newstateHooked
(
args
.
.
.
)
;
}
)
;
luaL_newstateHook
.
install
(
)
;
}
LSHook
::
~
LSHook
(
)
{
luaL_newstateHook
.
remove
(
)
;
}
std
::
uintptr_t LSHook
::
luaL_newstateHooked
(
const
decltype
(
luaL_newstateHook
)
&
hook
)
{
auto
L
=
hook
.
get_trampoline
(
)
(
)
;
auto
result
=
luaL_loadstring
(
L
,
"print(\"HUY\")"
)
;
if
(
result
==
0
)
lua_pcall
(
L
,
0
,
0
,
0
)
;
return
L
;
}


header:





Код:
#include 
#include "kthook/kthook.hpp"
class
LSHook
{
private
:
using
luaL_newstate_t
=
std
::
uintptr_t
(
*
)
(
)
;
kthook
::
kthook_simple

luaL_newstateHook
;
std
::
uintptr_t
luaL_newstateHooked
(
const
decltype
(
luaL_newstateHook
)
&
hook
)
;
using
luaL_loadstring_t
=
int
(
*
)
(
std
::
uintptr_t
,
const
char
*
)
;
using
lua_pcall_t
=
int
(
*
)
(
std
::
uintptr_t L
,
int
nargs
,
int
nresults
,
int
errfunc
)
;
;
luaL_loadstring_t luaL_loadstring
=
nullptr
;
lua_pcall_t lua_pcall
=
nullptr
;
public
:
LSHook
(
/* args */
)
;
~
LSHook
(
)
;
}
lshook
;
 
Ответить с цитированием

  #4  
Старый 28.04.2024, 19:28
g305noobo
Постоянный
Регистрация: 24.09.2020
Сообщений: 364
С нами: 2966237

Репутация: 148
По умолчанию

Цитата:
Сообщение от why ega  

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

C++:





Код:
LSHook
::
LSHook
(
)
{
auto
luaLibAddress
=
GetModuleHandleA
(
"lua51.dll"
)
;
if
(
!
luaLibAddress
)
return
;
luaL_loadstring
=
reinterpret_cast

(
GetProcAddress
(
luaLibAddress
,
"luaL_loadstring"
)
)
;
lua_pcall
=
reinterpret_cast

(
GetProcAddress
(
luaLibAddress
,
"lua_pcall"
)
)
;
auto
luaL_newstateAddress
=
GetProcAddress
(
luaLibAddress
,
"luaL_newstate"
)
;
luaL_newstateHook
.
set_dest
(
luaL_newstateAddress
)
;
luaL_newstateHook
.
set_cb
(
[
this
]
(
auto
&&
.
.
.
args
)
{
return
luaL_newstateHooked
(
args
.
.
.
)
;
}
)
;
luaL_newstateHook
.
install
(
)
;
}
LSHook
::
~
LSHook
(
)
{
luaL_newstateHook
.
remove
(
)
;
}
std
::
uintptr_t LSHook
::
luaL_newstateHooked
(
const
decltype
(
luaL_newstateHook
)
&
hook
)
{
auto
L
=
hook
.
get_trampoline
(
)
(
)
;
auto
result
=
luaL_loadstring
(
L
,
"print(\"HUY\")"
)
;
if
(
result
==
0
)
lua_pcall
(
L
,
0
,
0
,
0
)
;
return
L
;
}


header:





Код:
#include 
#include "kthook/kthook.hpp"
class
LSHook
{
private
:
using
luaL_newstate_t
=
std
::
uintptr_t
(
*
)
(
)
;
kthook
::
kthook_simple

luaL_newstateHook
;
std
::
uintptr_t
luaL_newstateHooked
(
const
decltype
(
luaL_newstateHook
)
&
hook
)
;
using
luaL_loadstring_t
=
int
(
*
)
(
std
::
uintptr_t
,
const
char
*
)
;
using
lua_pcall_t
=
int
(
*
)
(
std
::
uintptr_t L
,
int
nargs
,
int
nresults
,
int
errfunc
)
;
;
luaL_loadstring_t luaL_loadstring
=
nullptr
;
lua_pcall_t lua_pcall
=
nullptr
;
public
:
LSHook
(
/* args */
)
;
~
LSHook
(
)
;
}
lshook
;

это хорошая идея, но из-за того что мы хукаем самую начальную точку, moonloader не успевает сделать luaL_openlibs, соотвественно в хуке даже print не работает в luaL_loadstring, не говоря уже о функциях муна.

но если просто сохранить эти указатели и использовать попозже, все будет ок
 
Ответить с цитированием

  #5  
Старый 10.05.2024, 22:43
KinderPengui
Познающий
Регистрация: 04.05.2023
Сообщений: 47
С нами: 1596122

Репутация: 8
По умолчанию

Ку-ку, чего с модификацией? Есть обновления - мне для игры требуется скрипт без багов - это эта модификация - скачивать?
 
Ответить с цитированием
Ответ





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.