- Поддерживаемые игры
-
- CS: Source (OrangeBox)
- CS: GO
- Team Fortress 2
- DOD: Source
- L4D 1 & 2
Первое что хотелось бы сказать, что философия данного inc состоит в том, чтобы все манипуляции воспроизводились без создания и нужды дополнительных файлов на сервере.
Данный INC находится в разработке и из-за этого - WINDOWS ONLY. Он был выложен для показа возможностей библиотеки, а так же возможной обратной связи
С версии 2.0 - добавлена поддержка linux
А благодаря этим людям, этот inc был дописан хотя бы до такого состояния:
@Kailo - за помощь в обучении ASM/Отладчиков/Работе с IDA
@komashchenko - За помощь, которая помогла мне разобраться с SDKCall
@Boeing 676 - За помощь, которая помогла адаптировать данную библиотеку под Linux
Данное "оружие" было создано для удобной работы с другими .dll, ведь в функциях SourcePawn можно работать только с 3-мя => server.dll/engine.dll/matchmaking_ds
Что же из этого вышло? - Давайте рассмотрим его структуру =>
С версии 2.0 структура разделена по файлами
MemoryEx/ASM_Instruction.inc - Вспомогающий файл, который позволяет использовать самые частые ASM функции в SP [Подключает за собою MemoryEx/BaseMemory.inc]
3) MemoryEx/DynamicLibrary.inc - Реализует функции для работы с динамическими библиотеками
4) MemoryEx/ServerLibrary.inc - Работа с server[.so]/[.dll] - а именно получения базового адреса [Windows Only] (Для Linux не нужен) / Получение OS сервера
5) MemoryEx/LinuxFunction.inc - Вспомогательные функции для linux => Загрузка списка .so библиотек
6) MemoryEx/WindowsFunction.inc - Функции для Windows => Получения размера DLL из PEB заголовка/Получения версии Windows
1) Bypass -nobots/-nohltv
2) SM Plugins Block [Путем патча самого SourceMod]
Примеры:
1) Внедряем .dll через SourcePawn [GetProcAddress + вызов WINAPI LoadLibraryA]
На ранней стадии создании данного inc он был раскритикован @Kruzya в теме с моим плагином => Bypass -nobots и я действительно был с ним согласен, по этому теперь давайте рассмотрим использование данного inc именно на данном плагине.
Первая претензия была в том, что геймдату нужно изредко обновлять. Теперь мы просто ищем данное слово и "уничтожаем его"
Но если посмотрим на претензию до конца, то видно, что если снять сжатие, было видно строки, что упрощает поимку плагина, что же делать? - Попробуем другой способ - через MemoryEx::FindPattern
С версии 2.0 - добавлена поддержка linux
А благодаря этим людям, этот inc был дописан хотя бы до такого состояния:
@Kailo - за помощь в обучении ASM/Отладчиков/Работе с IDA
@komashchenko - За помощь, которая помогла мне разобраться с SDKCall
@Boeing 676 - За помощь, которая помогла адаптировать данную библиотеку под Linux
Данное "оружие" было создано для удобной работы с другими .dll, ведь в функциях SourcePawn можно работать только с 3-мя => server.dll/engine.dll/matchmaking_ds
Что же из этого вышло? - Давайте рассмотрим его структуру =>
С версии 2.0 структура разделена по файлами
MemoryEx/ASM_Instruction.inc - Вспомогающий файл, который позволяет использовать самые частые ASM функции в SP [Подключает за собою MemoryEx/BaseMemory.inc]
C-подобный:
enum ASMRegister
{
ASMRegister_EAX,
ASMRegister_ECX,
ASMRegister_EDX,
ASMRegister_EBX,
ASMRegister_ESP,
ASMRegister_EBP,
ASMRegister_ESI,
ASMRegister_EDI
}
enum struct ASMInstructions
{
BaseMemory mem;
void Set(Pointer adr)
{
this.mem.pAddrBase = adr;
}
Pointer Get()
{
return this.mem.pAddrBase;
}
void PushRegister(ASMRegister reg)
{
this.mem.WriteByte(0x50 + view_as<int>(reg), _, MemoryEx_AddAfterWrite);
}
void Push(any value)
{
this.mem.WriteByte(0x68, _, MemoryEx_AddAfterWrite);
this.mem.WriteInt(value, _, MemoryEx_AddAfterWrite);
}
void PopRegister(ASMRegister reg)
{
this.mem.WriteByte(0x58 + view_as<int>(reg), _, MemoryEx_AddAfterWrite);
}
void Call (any value)
{
this.mem.WriteWord(0x15FF, _, MemoryEx_AddAfterWrite);
this.mem.WriteInt(value, _, MemoryEx_AddAfterWrite);
}
void Nop()
{
this.mem.WriteByte(0x90, _, MemoryEx_AddAfterWrite);
}
void Xchg(ASMRegister reg)
{
this.mem.WriteByte(0x90 + view_as<int>(reg), _, MemoryEx_AddAfterWrite);
}
void Retn()
{
this.mem.WriteByte(0xC3, _, MemoryEx_AddAfterWrite);
}
}
stock ASMInstructions g_ASM;
#define ASM g_ASM
#define ASMHELP_SET(%0) g_ASM.Set(%0)
#define ASMHELP_GET() g_ASM.Get()
#define PUSH_REGISTER(%0) g_ASM.PushRegister(ASMRegister_%0)
#define PUSH(%0) g_ASM.Push(%0)
#define POP_REGISTER(%0) g_ASM.PopRegister(ASMRegister_%0)
#define CALL(%0) g_ASM.Call(%0)
#define NOP() g_ASM.Nop()
#define XCHG(%0) g_ASM.Xchg(ASMRegister_%0)
#define RETN() g_ASM.Retn()
MemoryEx/BaseMemory.inc | Реализовывает базовые функции для более удобной работы с памятью |
---|---|
void BaseMemory::SetAddr(any address) | |
Pointer BaseMemory::GetAddr() | |
void BaseMemory::Add(any iOffset) | |
int BaseMemory::ReadByte(int iOffset = 0) | |
void BaseMemory::WriteByte(any iByte, int iOffset = 0, int flags = MemoryEx_NoNeedAdd) | |
int BaseMemory::ReadWord(int iOffset = 0) | |
void BaseMemory::WriteWord(any iByte, int iOffset = 0, int flags = MemoryEx_NoNeedAdd) | |
int BaseMemory::ReadInt(int iOffset = 0) | |
void BaseMemory::WriteInt(any iByte, int iOffset = 0, int flags = MemoryEx_NoNeedAdd) | |
void BaseMemory::WriteData(const int[] data, int iSize, int flags = MemoryEx_NoNeedAdd) | |
int BaseMemory::ReadString(char[] sString, int iMaxLength) | Возвращает длину строки |
void BaseMemory::WriteString(const char[] sString, bool bNull = true, int flags = MemoryEx_NoNeedAdd) | |
void BaseMemory::WriteUnicodeString(const char[] sString, bool bNull = true, int flags = MemoryEx_NoNeedAdd) | |
Pointer BaseMemory::FindPattern(Pointer base, any size, const int[] pattern, int iLength, int iOffset = 0) | return address = found address + iOffset |
PHP:
void DynamicLibrary::Init()
Pointer DynamicLibrary::InitModule(const char[] sNameLibrary) - расширение .so/.dll - вы можете опускать. Вместо mem.lib.InitModule("engine.dll") => mem.lib.InitModule("engine") - inc за вас допишет нужное расширение :)
Pointer DynamicLibrary::GetBaseAddress(const char[] sName)
int DynamicLibrary::GetModuleSize(const char[] sName)
Pointer DynamicLibrary::GetEndModule(const char[] sName)
Pointer DynamicLibrary::GetModuleHandle(const char[] name)
Pointer DynamicLibrary::GetProcAddress(const char[] sLibrary, const char[] sName) <<== https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress
Pointer DynamicLibrary::FindPattern(const char[] sModule, const int[] sPattern, int iLength, int iOffset = 0)
Pointer DynamicLibrary::FindString(const char[] sModule, const char[] sString)
Pointer DynamicLibrary::FindUnicodeString(const char[] sModule, const char[] sString)
Pointer DynamicLibrary::FindValue(const char[] sModule, any iValue, int iNextByte = 0x2A ) // iNextByte - to help
5) MemoryEx/LinuxFunction.inc - Вспомогательные функции для linux => Загрузка списка .so библиотек
6) MemoryEx/WindowsFunction.inc - Функции для Windows => Получения размера DLL из PEB заголовка/Получения версии Windows
Плагины работающие с MemoryEx
1) Bypass -nobots/-nohltv
2) SM Plugins Block [Путем патча самого SourceMod]
Pointer GetModuleHandle(const char[] library) - Возвращает Base Address указанного модуля [На основе WINAPI GetModuleHandleW]. "0" - Возвращает адрес srcds.
Pointer InitModule(const char[] library) - Инициализирует Base/End address указанного модуля
Pointer GetBaseAddress(const char[] library) - Возвращает Base Address уже из инициализированного модуля
int GetModuleSize(const char[] library) - Возвращает инициализированный размер библиотеки
Pointer GetEndModule(const char[] library) - Возвращает адресс последнего инициализированного байта библиотеки [MemoryEx::GetBaseAddress + MemoryEx::GetBaseAddres]
Пример всех этих функций:
Результат
Pointer InitModule(const char[] library) - Инициализирует Base/End address указанного модуля
Pointer GetBaseAddress(const char[] library) - Возвращает Base Address уже из инициализированного модуля
int GetModuleSize(const char[] library) - Возвращает инициализированный размер библиотеки
Pointer GetEndModule(const char[] library) - Возвращает адресс последнего инициализированного байта библиотеки [MemoryEx::GetBaseAddress + MemoryEx::GetBaseAddres]
Пример всех этих функций:
C-подобный:
#include <MemoryEx>
public void OnPluginStart()
{
MemoryEx mem;
if(!mem.Init()) return;
Pointer base = mem.GetModuleHandle("kernel32.dll");
Pointer base1 = mem.InitModule("kernel32.dll");
Pointer base2 = mem.GetBaseAddress("kernel32.dll");
Pointer srcds = mem.GetModuleHandle("0");
int size = mem.GetModuleSize("kernel32.dll");
Pointer end1 = base1 + PTR(size);
Pointer end2 = mem.GetEndModule("kernel32.dll");
PrintToServer("base [0x%X] == base1 [0x%X] == base2 [0x%X] size [0x%X] end1 [0x%X] == end2 [0x%X] srcds [0x%X]", base, base1, base2, size, end1, end2, srcds);
}
Результат
base [0x75170000] == base1 [0x75170000] == base2 [0x75170000] size [0xE0000] end1 [0x75250000] == end2 [0x75250000] srcds [0xB10000]
Примеры:
1) Внедряем .dll через SourcePawn [GetProcAddress + вызов WINAPI LoadLibraryA]
C-подобный:
#include <MemoryEx>
public void OnPluginStart()
{
PrintToServer("ServerBase 0x%X size 0x%X kernel base 0x%X size 0x%X",
g_hMem.GetModuleHandle("server"), g_hMem.GetModuleSize("server"), g_hMem.GetModuleHandle("kernel32"), g_hMem.GetModuleSize("kernel32"));
Pointer libAddr = g_hMem.GetProcAddress("kernel32", "LoadLibraryA");
StartPrepSDKCall(SDKCall_Static);
PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer);
PrepSDKCall_SetAddress(libAddr);
PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
Handle h = EndPrepSDKCall();
int baseDLL = SDKCall(h, "D:/CSS_HOOK.dll");
PrintToServer("libaddr = 0x%X Base Address DLL = 0x%X ",libAddr, baseDLL);
delete h;
}
На ранней стадии создании данного inc он был раскритикован @Kruzya в теме с моим плагином => Bypass -nobots и я действительно был с ним согласен, по этому теперь давайте рассмотрим использование данного inc именно на данном плагине.
Первая претензия была в том, что геймдату нужно изредко обновлять. Теперь мы просто ищем данное слово и "уничтожаем его"
C-подобный:
#include <MemoryEx>
public void OnPluginStart()
{
MemoryEx mem;
mem.Init();
mem.lib.InitModule("engine");
Pointer pNoBots = mem.lib.FindString("server", "-nobots");
if(pNoBots != nullptr)
{
mem.mem.SetAddr(pNoBots + PTR(0x01));
for(int y = 0; y < 6; y++) mem.mem.WriteByte(GetRandomInt(0x61, 0x7A), y);
}
}
C-подобный:
#include <MemoryEx>
public void OnPluginStart()
{
static int pattern[8] = {0x2D, 0x6E, 0x6F, 0x62, 0x6F, 0x74, 0x73, 0x00}; // `-nobots`;
MemoryEx mem;
mem.Init();
ModuleInfo server;
server.base = mem.lib.GetBaseAddress("server");
server.size = mem.lib.GetModuleSize("server");
Pointer pStr = mem.mem.FindPattern(server.base, server.size, pattern, sizeof(pattern), 0x01); // bypass `-`
if(pStr != nullptr)
{
mem.mem.SetAddr(pStr);
for(int y = 0; y < 6; y++) mem.mem.WriteByte(GetRandomInt(0x61, 0x7A), y);
}
}
- Требования
-
SourceMod 1.10+