Uma biblioteca C++ para iniciar e automatizar a conexão de clientes SA-MP e OMP a servidores, via injeção de DLLs.
- Deutsch: README
- English: README
- Español: README
- Français: README
- Italiano: README
- Polski: README
- Русский: README
- Svenska: README
- Türkçe: README
- SA-MP Injector C++
- Idiomas
- Índice
- Visão Geral e Propósito
- Princípios de Design
- Ambiente Necessário
- Início Rápido
- Estrutura da Biblioteca
- O Processo Detalhado de Injeção
- 1. Solicitação de Inicialização
- 2. Preparação do Ambiente
- 3. Verificação de Integridade e Parâmetros
- 4. Preparação dos Argumentos para o Jogo
- 5. Inicialização do Processo do Jogo (Suspenso)
- 6. Injeção da Biblioteca SA-MP (
samp.dll) - 7. Injeção da Biblioteca OMP (
omp-client.dll) - Condicional - 8. Ativação do Jogo
- Diagnóstico de Erros e Falhas
- Licença
O SA-MP Injector C++ é uma biblioteca C++ compacta e de fácil integração, projetada para automatizar o processo de inicialização e conexão a servidores de San Andreas Multiplayer (SA-MP) e Open Multiplayer (OMP). Diferentemente de iniciar o gta_sa.exe diretamente, esta solução carrega programaticamente as bibliotecas samp.dll ou omp-client.dll no processo do jogo Grand Theft Auto: San Andreas de forma controlada.
Seu objetivo principal é capacitar desenvolvedores C++ a criar launchers personalizados, ferramentas de gerenciamento de comunidade ou utilitários que necessitem iniciar o GTA:SA com parâmetros de conexão predefinidos (como nome de usuário, endereço IP, porta e senha), oferecendo uma experiência de usuário fluida e automatizada.
A arquitetura do SA-MP Injector C++ é fundamentada em princípios de design modernos, focando em segurança, eficiência e facilidade de uso.
Esta biblioteca é distribuída exclusivamente através de arquivos de cabeçalho (.hpp). Isso simplifica drasticamente a integração em projetos C++, eliminando a necessidade de compilar bibliotecas separadas, configurar linkers ou gerenciar dependências de binários.
- Integração Instantânea: Basta incluir os
headersrelevantes. - Otimização Profunda: O compilador pode realizar
inliningagressivo e otimizações delink-timeque resultam em um código final mais compacto e veloz.
A biblioteca emprega o padrão RAII (Resource Acquisition Is Initialization) de forma extensiva. Recursos críticos do sistema, como handles de processos e threads do Windows, são encapsulados por std::unique_ptr com deleters personalizados. Isso assegura que, independentemente do fluxo de execução ou da ocorrência de exceções, os recursos sejam sempre liberados corretamente, prevenindo vazamentos e melhorando a estabilidade da aplicação.
Cada etapa crítica da injeção é precedida por validações rigorosas e seguida por verificações de erros da API do Windows. Mensagens de erro detalhadas são fornecidas ao usuário final através de caixas de diálogo, com descrições do sistema (GetLastError()) sempre que possível. Essa abordagem minimiza a chance de comportamentos indefinidos e oferece um diagnóstico claro em caso de falha.
A biblioteca foi construída para ser compatível com diferentes padrões C++, do C++14 ao C++20. Isso é alcançado através de macros condicionais que permitem a utilização de recursos modernos (como std::string_view, std::filesystem e std::optional do C++17+) quando disponíveis, enquanto mantém um fallback para construções equivalentes em C++14. Essa abordagem garante ampla compatibilidade sem sacrificar a modernidade.
- Compilador C++: Compatível com C++14 ou superior.
- Microsoft Visual C++ (Visual Studio 2015, 2017, 2019, 2022)
- GCC (versão 5 ou mais recente)
- Clang (versão 3.6 ou mais recente)
- Sistema Operacional: Windows.
- Windows SDK: Necessário para acesso às APIs do sistema operacional.
- Arquitetura de Compilação: x86 (32-bit). Esta é uma exigência estrita, pois o
gta_sa.exee as DLLs SA-MP/OMP operam exclusivamente nesta arquitetura.
- Sistema Operacional: Qualquer versão moderna do Windows compatível com o binário compilado.
- Grand Theft Auto: San Andreas (GTA:SA): Uma instalação válida do jogo é obrigatória.
- DLLs do Cliente SA-MP ou OMP: Os arquivos
samp.dllouomp-client.dlldevem estar presentes no diretório raiz do jogo, correspondendo ao tipo de injeção desejado.
A natureza header-only da biblioteca facilita sua incorporação em qualquer projeto C++.
- Baixe os Headers: Obtenha os arquivos
.hppda biblioteca (clonando o repositório ou baixando-os diretamente). - Organize os Arquivos: Recomenda-se criar uma subpasta no seu projeto para os
headersda biblioteca, por exemplo,MeuProjeto/libraries/samp-injector/. - Defina a Arquitetura: Configure seu projeto para compilar para a arquitetura x86 (32-bit).
// Exemplo de estrutura de diretórios
MeuProjeto/
├── src/
│ └── main.cpp
├── libraries/
│ └── samp-injector/
│ ├── constants.hpp
│ ├── error_utils.hpp
│ ├── injector.hpp // O cabeçalho principal a ser incluído
│ └── ... (outros cabeçalhos)
└── built/ (seu diretório de saída)Para automatizar a conexão a um servidor, basta invocar a função Initialize_Game e fornecer os detalhes.
#include <iostream>
#include <string>
//
#include "samp-launcher/injector.hpp" // Inclua o cabeçalho principal
int main() {
// Parâmetros para a inicialização do jogo e conexão
std::wstring inject_type = L"samp"; // Ou L"omp" para Open Multiplayer
std::wstring game_folder = L"C:\\Games\\GTA San Andreas"; // Caminho completo da pasta do GTA:SA
std::wstring nickname = L"Nome";
std::wstring ip = L"127.0.0.1";
std::wstring port = L"7777";
std::wstring password = L""; // Deixe vazio se não houver senha
// A chamada principal para iniciar o jogo e injetar a DLL
Initialize_Game(inject_type, game_folder, nickname, ip, port, password);
// Em caso de falha, uma caixa de mensagem de erro do Windows é exibida automaticamente.
return 0;
}A biblioteca é cuidadosamente modularizada em diversos arquivos de cabeçalho, cada um com responsabilidades bem definidas, facilitando a organização, manutenção e reusabilidade.
Este arquivo é o repositório central da biblioteca, servindo como um repositório centralizado de todos os valores fixos e inalteráveis que ditam o comportamento e a interoperabilidade do SA-MP Injector C++. Sua organização por categorias lógicas promove não apenas a clareza e a legibilidade do código, mas também facilita a manutenção e garante uma consistência rigorosa em todo o ecossistema da biblioteca.
Cada constante é definida com CONSTEXPR_VAR, que se expande para inline constexpr (para C++17+) ou static constexpr (para C++14), assegurando que esses valores sejam avaliados em tempo de compilação, otimizando o desempenho e a segurança de tipo.
A organização das constantes por categoria facilita a compreensão de seu propósito:
-
Constantes Relacionadas ao Jogo (
Game Related Constants)MIN_PORT: Umintque define o menor número de porta válido para conexão a um servidor (valor:1).MAX_PORT: Umintque estabelece o maior número de porta válido para conexão a um servidor (valor:65535).MAX_NICKNAME_LENGTH: Umintque especifica o comprimento máximo permitido para o nickname do jogador (valor:23caracteres), um limite imposto pelas especificações do cliente SA-MP/OMP.
-
Nomes de Arquivos Essenciais (
File Names)SAMP_DLL_NAME: Umconst wchar_t*que contém o nome do arquivo da biblioteca principal do cliente SA-MP (valor:L"samp.dll"). Essencial para a injeção do cliente clássico.OMP_DLL_NAME: Umconst wchar_t*que contém o nome do arquivo da biblioteca do cliente Open Multiplayer (valor:L"omp-client.dll"). Utilizado especificamente quando a injeção é do tipo OMP.GAME_EXE_NAME: Umconst wchar_t*que armazena o nome do arquivo executável do jogo base Grand Theft Auto: San Andreas (valor:L"gta_sa.exe"). O alvo principal da injeção.
-
APIs e Funções do Sistema (
System Libraries and Functions)KERNEL32_DLL: Umconst wchar_t*que define o nome da biblioteca de sistema do Windows (L"kernel32.dll"). Esta DLL é vital, pois hospeda as funções de manipulação de processos e memória que o injetor utiliza. O uso dewchar_tgarante compatibilidade com as funções de API que manipulam caracteres largos, comoGetModuleHandleW.LOAD_LIBRARY_FUNC: Umconst char*com o nome da função para carregar uma DLL dinamicamente (valor:"LoadLibraryW"). Embora a biblioteca opere primariamente com caracteres largos, a funçãoGetProcAddressda API do Windows requer um nome de função em formato ANSI (char*).
-
Argumentos de Linha de Comando (
Command Line Arguments)- Estas constantes definem os prefixos para os argumentos que são passados ao
gta_sa.exepara configurar a conexão do cliente. São fornecidas emWide Character(const wchar_t*) para compatibilidade comCreateProcessW.CMD_ARG_CONFIG: Argumento para configurações gerais (valor:L"-c").CMD_ARG_NICKNAME: Argumento para o nickname do jogador (valor:L"-n").CMD_ARG_HOST: Argumento para o endereço IP do servidor (valor:L"-h").CMD_ARG_PORT: Argumento para a porta do servidor (valor:L"-p").CMD_ARG_PASSWORD: Argumento para a senha do servidor (valor:L"-z"). Utilizado apenas se uma senha for fornecida.
- Estas constantes definem os prefixos para os argumentos que são passados ao
-
Identificadores de Tipo de Injeção (
Injection types as strings)INJECT_TYPE_SAMP: Umconst wchar_t*para a representação em string do tipo de injeção SA-MP (valor:L"samp").INJECT_TYPE_OMP: Umconst wchar_t*para a representação em string do tipo de injeção OMP (valor:L"omp").
-
Títulos para Mensagens de Erro (
Error message titles)ERROR_TITLE_SAMP: Umconst wchar_t*que define o título padrão para caixas de diálogo de erro relacionadas a falhas de SA-MP (valor:L"SA-MP Injector Error").ERROR_TITLE_OMP: Umconst wchar_t*que define o título padrão para caixas de diálogo de erro relacionadas a falhas de OMP (valor:L"OMP Injector Error").
-
Flags de Criação de Processo (
Process creation)PROCESS_CREATION_FLAGS: UmDWORDque encapsula as bandeiras passadas paraCreateProcessW. Crucialmente, incluiCREATE_SUSPENDED(0x00000004), que inicia o processo do jogo em um estado pausado, eDETACHED_PROCESS(0x00000008), que desvincula o novo processo do console do processo pai.
-
Tempos Limite (
Timeouts)DLL_INJECTION_TIMEOUT_MS: UmDWORDque especifica o tempo máximo (em milissegundos) que a biblioteca aguardará pela conclusão dathreadremota responsável pela injeção da DLL (valor:10000ms, ou 10 segundos).
-
Flags de Alocação de Memória (
Memory allocation)- Estas constantes são utilizadas para as chamadas de API de manipulação de memória, como
VirtualAllocExeVirtualProtect.MEM_COMMIT: UmDWORDque reserva páginas na memória virtual e as "commita" (aloca memória física) (valor:0x1000).MEM_RESERVE: UmDWORDque apenas reserva um intervalo de espaço de endereço virtual para uso posterior (valor:0x2000).MEM_RELEASE: UmDWORDque descommita e libera uma região de páginas (valor:0x8000).MEMORY_ALLOCATION_TYPE: Uma combinação deMEM_COMMITeMEM_RESERVE, usada para alocar a memória inicial para o caminho da DLL no processo remoto.MEMORY_PROTECTION: UmDWORDque define as permissões de proteção de memória (valor:PAGE_READWRITEou0x04no Windows API), permitindo leitura e escrita na memória alocada.
- Estas constantes são utilizadas para as chamadas de API de manipulação de memória, como
Este arquivo conciso introduz um enum class para tipificar as diferentes modalidades de injeção. A utilização de um tipo enumerado, ao invés de strings literais, eleva a segurança do código, previne erros de digitação e melhora a legibilidade.
Inject_Type: Umenum classcom dois membros:SAMPeOMP, representando os tipos de cliente a serem injetados.
// Exemplo de types.hpp
namespace Types {
enum class Inject_Type {
SAMP, // Indica injeção para o cliente SA-MP
OMP // Indica injeção para o cliente Open Multiplayer
};
}Atuando como um adaptador de compatibilidade, este cabeçalho detecta dinamicamente o padrão C++ em uso pelo compilador. Ele define macros condicionais (SAMP_INJECTOR_CXX_14, SAMP_INJECTOR_CXX_MODERN) que guiam a biblioteca a empregar as funcionalidades mais avançadas do C++ (como std::string_view ou std::filesystem) quando disponíveis, enquanto assegura total funcionalidade em ambientes C++14.
SAMP_INJECTOR_CXX_14: Definida se o padrão C++ for C++14.SAMP_INJECTOR_CXX_MODERN: Definida para C++17 ou superior, habilitando recursos de linguagem mais recentes.SAMP_INJECTOR_NODISCARD: Adapta o atributo[[nodiscard]]para as versões de C++ que o suportam, incentivando a verificação de valores de retorno.
// Exemplo de trecho relevante de version.hpp
#if (defined(_MSC_VER) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L
#define SAMP_INJECTOR_CXX_MODERN // Habilita recursos modernos de C++17+
#endif
#if defined(SAMP_INJECTOR_CXX_MODERN)
#define SAMP_INJECTOR_NODISCARD [[nodiscard]] // Usa o atributo nodiscard de C++17
#elif defined(SAMP_INJECTOR_CXX_14)
#define SAMP_INJECTOR_NODISCARD // Para C++14, o atributo é desativado
#endifEste utilitário é dedicado à gestão e apresentação de feedback de erro. Ele abstrai os mecanismos do Windows para recuperar mensagens de erro do sistema e oferece uma interface unificada para notificar o usuário sobre problemas.
Get_System_Error_Message: Traduz um código de erro do Windows (GetLastError()) em umastd::wstringlegível, crucial para o diagnóstico preciso.Show_Error: Apresenta uma caixa de diálogo (MessageBoxW) contendo a mensagem de erro fornecida, com um título específico para SA-MP ou OMP, garantindo uma comunicação clara com o usuário.
// Exemplo de trecho relevante de error_utils.hpp
namespace Error_Utils {
SAMP_INJECTOR_NODISCARD
inline std::wstring Get_System_Error_Message(DWORD error_code) {
if (error_code == 0)
return L"No error occurred.";
// ... Lógica para formatar a mensagem do sistema ...
}
inline void Show_Error(std::wstring_view message, Types::Inject_Type inject_type) {
const std::wstring title = (inject_type == Types::Inject_Type::SAMP) ? Constants::ERROR_TITLE_SAMP : Constants::ERROR_TITLE_OMP;
MessageBoxW(nullptr, message.data(), title.c_str(), MB_OK | MB_ICONERROR);
}
}Atuando como a linha de frente da robustez da biblioteca, este cabeçalho fornece rotinas rigorosas para verificar a validade dos dados de entrada e a presença dos arquivos necessários. Estas verificações são realizadas antes de qualquer interação de baixo nível com o sistema, mitigando riscos de runtime e fornecendo feedback proativo.
Validate_Port: Valida se a string da porta representa um número inteiro e se este se encontra dentro do intervalo configurado (MIN_PORTaMAX_PORT).Validate_Nickname: Verifica se o nickname não está vazio e se sua extensão não excede oMAX_NICKNAME_LENGTH.Validate_Files: Confirma a existência física degta_sa.exe,samp.dlle, condicionalmente para injeção OMP,omp-client.dll. A implementação se adapta astd::filesystem(C++17+) ouGetFileAttributesW(C++14).
// Exemplo de trecho relevante de validation.hpp
namespace Validation {
inline bool Validate_Nickname(std::wstring_view nickname_str, std::wstring& error_message) {
if (nickname_str.empty())
return (error_message = L"Nickname cannot be empty. Please provide a valid nickname.", false);
if (nickname_str.length() > Constants::MAX_NICKNAME_LENGTH)
return (error_message = L"Nickname length exceeds the maximum allowed of " + std::to_wstring(Constants::MAX_NICKNAME_LENGTH) + L" characters. Please use a shorter nickname.", false);
return true;
}
inline bool Validate_Files(const std::filesystem::path& game_path, const std::filesystem::path& samp_DLL_path, const std::filesystem::path& omp_DLL_path, Types::Inject_Type inject_type) {
if (!std::filesystem::exists(game_path))
return (Error_Utils::Show_Error(L"Game executable not found. Please ensure 'gta_sa.exe' exists at the specified path: " + game_path.wstring(), inject_type), false);
// ... Outras verificações de arquivos ...
return true;
}
}Implementa uma estratégia elegante e segura para o gerenciamento de recursos do sistema operacional, como os HANDLEs do Windows. Utilizando o princípio RAII, garante que todos os recursos alocados sejam devidamente liberados, prevenindo vazamentos e fortalecendo a estabilidade da aplicação.
Unique_Resource: Umalias templateque adaptastd::unique_ptrpara trabalhar comdeleterspersonalizados, permitindo o gerenciamento de qualquer tipo de recurso que necessite de uma função de liberação específica.Make_Unique_Handle: Uma funçãofactoryconveniente que constrói e retorna umUnique_Resourcepré-configurado paraHANDLEs do Windows. Odeleterassociado invocaCloseHandleautomaticamente quando oUnique_Resourcesai de escopo, garantindo a desocupação imediata do recurso.
// Exemplo de trecho relevante de resource_handle.hpp
namespace Resource_Handle {
// Um std::unique_ptr personalizado para gerenciar recursos do sistema.
template<typename T, typename Deleter>
using Unique_Resource = std::unique_ptr<std::remove_pointer_t<T>, Deleter>;
// Cria um Unique_Resource para um HANDLE, com um deleter que chama CloseHandle.
template<typename T>
inline auto Make_Unique_Handle(T handle) {
return Unique_Resource<T, std::function<void(T)>>(handle, [](T h) {
if (h && h != INVALID_HANDLE_VALUE) // Garante que o handle seja válido antes de fechar
CloseHandle(h);
});
}
}Este componente é responsável por configurar o ambiente de segurança do processo da aplicação. Ele contém a funcionalidade para elevar os privilégios, especificamente habilitando o privilégio de depuração (SE_DEBUG_NAME), que é um requisito fundamental para que a biblioteca possa realizar operações de injeção de DLL em processos externos do Windows.
Enable_Debug_Privilege: Esta função tenta adquirir e ativar o privilégioSE_DEBUG_NAMEpara o processo em execução. É uma etapa inicial crucial para conceder à aplicação as permissões necessárias para manipular outros processos, como alocar memória e criarthreadsremotas. Retornatrueem caso de sucesso.
// Exemplo de trecho relevante de privileges.hpp
namespace Privileges {
inline bool Enable_Debug_Privilege() {
HANDLE token_handle;
// Tenta abrir o token do processo atual para ajustar privilégios
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
return false;
auto handle_guard = Resource_Handle::Make_Unique_Handle(token_handle); // Gerenciamento seguro do handle
TOKEN_PRIVILEGES tp;
LUID luid;
// Procura o valor LUID para o privilégio SE_DEBUG_NAME
if (!LookupPrivilegeValue(nullptr, SE_DEBUG_NAME, &luid))
return false;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // Habilita o privilégio
// Ajusta os privilégios do processo
if (!AdjustTokenPrivileges(token_handle, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
return false;
return GetLastError() == ERROR_SUCCESS; // Retorna true se a operação foi bem-sucedida (nenhum erro pendente)
}
}Este é um dos componentes mais críticos da biblioteca, contendo a implementação de baixo nível para interagir com processos do Windows. Ele encapsula as complexas operações de criação do processo do jogo, alocação de memória, escrita de dados e a técnica de injeção de DLL através da criação de threads remotas.
Process_Infostruct: Uma estrutura interna que armazena osUnique_Resources para oHANDLEdo processo (process_handle) e doHANDLEdathreadprincipal (thread_handle) do jogo. Inclui um métodoResume()para reativar athreadprincipal do jogo quando a injeção estiver completa.Injection_Statusenum class: Define uma lista detalhada de resultados possíveis para a operação de injeção de DLL, permitindo um diagnóstico preciso de falhas.Create_Game_Process:- Utiliza a função
CreateProcessWda API do Windows para iniciar o executávelgta_sa.exe. - É fundamental que o processo seja criado com a flag
CREATE_SUSPENDED(incluída emConstants::PROCESS_CREATION_FLAGS). Isso garante que o jogo seja pausado imediatamente após sua criação, antes de qualquer código ser executado, permitindo que a injeção da DLL ocorra em um estado seguro. - Retorna um
std::optional<Process_Info>(para C++17+) ou umstd::unique_ptr<Process_Info>(para C++14), contendo oshandlesencapsulados do processo e dathread.
- Utiliza a função
Inject_DLL:- Implementa a técnica padrão de injeção de DLL via
CreateRemoteThread:- Obtenção do Endereço: Utilizando as constantes de
constants.hpp, localiza o endereço da funçãoLoadLibraryW(dokernel32.dll), que o Windows utiliza para carregar bibliotecas dinamicamente. - Alocação de Memória:
VirtualAllocExé utilizada para reservar um bloco de memória virtual dentro do processo do jogo (gta_sa.exe). Este bloco é dimensionado para conter o caminho completo da DLL a ser injetada. - Escrita do Caminho: O caminho da DLL (e.g.,
L"C:\\caminho\\para\\samp.dll") é então copiado para a memória remotamente alocada no processo do jogo através deWriteProcessMemory. - Criação da Thread Remota:
CreateRemoteThreadinicia uma novathreadno contexto do processo do jogo. O ponto de entrada destathreadé o endereço deLoadLibraryW, e o argumento passado é o endereço da string do caminho da DLL que acabamos de gravar. - Monitoramento: A execução da
threadremota é monitorada porWaitForSingleObjectaté que ela seja concluída ou oDLL_INJECTION_TIMEOUT_MSseja atingido. - Verificação de Sucesso:
GetExitCodeThreadé usada para verificar o valor de retorno dathreadremota. SeLoadLibraryWfoi bem-sucedida, ela retornará o endereço base da DLL carregada (um valor diferente de zero). - Limpeza: A memória alocada no processo remoto é liberada por
VirtualFreeEx.
- Obtenção do Endereço: Utilizando as constantes de
- Retorna um
Injection_Statusindicando o sucesso ou o tipo específico de falha da injeção.
- Implementa a técnica padrão de injeção de DLL via
// Exemplo de trecho relevante de process.hpp
class Process {
public:
struct Process_Info {
Resource_Handle::Unique_Resource<HANDLE, std::function<void(HANDLE)>> process_handle; // Handle do processo com gerenciamento RAII
Resource_Handle::Unique_Resource<HANDLE, std::function<void(HANDLE)>> thread_handle; // Handle da thread com gerenciamento RAII
bool Resume() { // Retoma a execução da thread principal do jogo
return thread_handle && ResumeThread(thread_handle.get()) != static_cast<DWORD>(-1);
}
};
enum class Injection_Status { // Códigos de status detalhados para a injeção de DLL
SUCCESS,
ALLOCATION_FAILED,
WRITE_FAILED,
KERNEL32_HANDLE_FAILED,
LOADLIBRARY_ADDRESS_FAILED,
THREAD_CREATION_FAILED,
THREAD_WAIT_FAILED,
GET_EXIT_CODE_FAILED,
INJECTION_RETURNED_ERROR
};
// Cria o processo do jogo em estado suspenso
std::optional<Process_Info> Create_Game_Process(const std::wstring& game_path, std::wstring& command_args, const std::wstring& working_dir) {
// ... Lógica de CreateProcessW com CREATE_SUSPENDED ...
}
SAMP_INJECTOR_NODISCARD // Garante que o valor de retorno seja utilizado
Injection_Status Inject_DLL(HANDLE process, const std::wstring& DLL_path) {
static const LPVOID load_library_addr = reinterpret_cast<LPVOID>(GetProcAddress(GetModuleHandleW(Constants::KERNEL32_DLL), Constants::LOAD_LIBRARY_FUNC));
if (!load_library_addr)
return Injection_Status::LOADLIBRARY_ADDRESS_FAILED;
LPVOID remote_memory = VirtualAllocEx(process, nullptr, (DLL_path.length() + 1) * sizeof(wchar_t), Constants::MEMORY_ALLOCATION_TYPE, Constants::MEMORY_PROTECTION);
if (!remote_memory)
return Injection_Status::ALLOCATION_FAILED;
auto memory_guard = Resource_Handle::Unique_Resource<LPVOID, std::function<void(LPVOID)>>(remote_memory, [process](LPVOID ptr) {
if (ptr)
VirtualFreeEx(process, ptr, 0, MEM_RELEASE); // Libera a memória no processo remoto
});
if (!WriteProcessMemory(process, remote_memory, DLL_path.c_str(), (DLL_path.length() + 1) * sizeof(wchar_t), nullptr))
return Injection_Status::WRITE_FAILED;
HANDLE remote_thread = CreateRemoteThread(process, nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(load_library_addr), remote_memory, 0, nullptr);
if (!remote_thread)
return Injection_Status::THREAD_CREATION_FAILED;
auto thread_guard = Resource_Handle::Make_Unique_Handle(remote_thread); // Gerenciamento seguro do handle da thread remota
if (WaitForSingleObject(remote_thread, Constants::DLL_INJECTION_TIMEOUT_MS) != WAIT_OBJECT_0)
return Injection_Status::THREAD_WAIT_FAILED;
DWORD exit_code = 0;
if (!GetExitCodeThread(remote_thread, &exit_code))
return Injection_Status::GET_EXIT_CODE_FAILED;
if (exit_code == 0)
return Injection_Status::INJECTION_RETURNED_ERROR;
return Injection_Status::SUCCESS;
}
};Este cabeçalho define a classe Injector_Core, que serve como o centro de comando da biblioteca. Ela orquestra a sequência lógica das operações de injeção, conectando os módulos de validação de entrada, gerenciamento de privilégios e manipulação de processos. É aqui que o fluxo de trabalho completo da injeção é definido.
Injector_Core: O construtor desta classe é o ponto ondePrivileges::Enable_Debug_Privilege()é chamado. Isso garante que o processo da aplicação possua os privilégios necessários para realizar operações de injeção de DLL antes que qualquer outra lógica crítica seja executada.Initialize_Game:- Validação Abrangente: Inicia chamando as funções de validação (
Validation::Validate_Port,Validation::Validate_Nickname,Validation::Validate_Files) para assegurar que todos os parâmetros e recursos essenciais estejam em ordem. Se qualquer validação falhar, um erro é imediatamente reportado. - Preparação de Argumentos: Constrói a linha de comando completa (
std::wstring) que será passada aogta_sa.exe, incorporando o nickname, IP, porta e senha fornecidos. - Criação do Processo Suspenso: Invoca
Process::Create_Game_Processpara iniciar ogta_sa.exeem um estado suspenso, obtendo oshandlesdo processo e dathreadprincipal. - Injeção de
samp.dll: ChamaInject_DLL_With_Status_Checkpara injetar osamp.dllno processo do jogo. Esta função wrapper também é responsável por interpretar oInjection_Statusretornado e exibir mensagens de erro informativas. - Injeção Condicional de
omp-client.dll: Se oinject_typeforTypes::Inject_Type::OMP, oomp-client.dllé então injetada da mesma forma quesamp.dll. - Retomada do Jogo: Após todas as injeções bem-sucedidas,
process_info.Resume()é chamada para permitir que athreadprincipal do jogo continue sua execução. - Tratamento de Erros no Ciclo: Qualquer falha em qualquer uma dessas etapas críticas resultará em uma chamada para
Error_Utils::Show_Error, fornecendo feedback claro ao usuário e garantindo que o processo seja encerrado corretamente (oshandlessão liberados automaticamente pelosUnique_Resources).
- Validação Abrangente: Inicia chamando as funções de validação (
Build_Command_Args: Uma função auxiliar que organiza e concatena os argumentos de linha de comando, adicionando aspas onde necessário para parâmetros que contenham espaços.Inject_DLL_With_Status_Check: Uma função privada que atua como um invólucro paraProcess::Inject_DLL. Ela mapeia os diferentesInjection_Statuspara mensagens de erro compreensíveis, facilitando o tratamento de erros e a comunicação com o usuário.
// Exemplo de trecho relevante de injector_core.hpp
namespace Injector {
class Injector_Core {
public:
Injector_Core() { // O construtor habilita o privilégio de depuração
Privileges::Enable_Debug_Privilege();
}
bool Initialize_Game(Types::Inject_Type inject_type, std::wstring_view folder, std::wstring_view nickname, std::wstring_view ip, std::wstring_view port, std::wstring_view password) {
std::wstring error_message;
// Sequência de validações de entrada
if (!Validation::Validate_Port(port, error_message))
return (Error_Utils::Show_Error(error_message, inject_type), false);
// ... outras validações ...
// Constrói os argumentos da linha de comando
std::wstring args = Build_Command_Args({
Command_Arg{Constants::CMD_ARG_NICKNAME, std::wstring(nickname)},
// ... outros argumentos ...
});
Process process_core;
// Cria o processo do jogo em estado suspenso
auto process_info_opt = process_core.Create_Game_Process(game_path, args, std::wstring(folder));
if (!process_info_opt)
return false;
auto& process_info = *process_info_opt;
// Injeta samp.dll e, condicionalmente, omp-client.dll
if (!Inject_DLL_With_Status_Check(process_core, process_info.process_handle.get(), Constants::SAMP_DLL_NAME, samp_DLL_path.wstring(), inject_type))
return false;
if (inject_type == Types::Inject_Type::OMP) {
if (!Inject_DLL_With_Status_Check(process_core, process_info.process_handle.get(), Constants::OMP_DLL_NAME, omp_DLL_path.wstring(), inject_type))
return false;
}
// Retoma a thread principal do jogo
if (!process_info.Resume())
return (Error_Utils::Show_Error(L"Failed to resume the game process thread: " + Error_Utils::Get_System_Error_Message(GetLastError()), inject_type), false);
return true;
}
};
}Este cabeçalho atua como a fachada (Facade) principal da biblioteca, oferecendo um ponto de entrada simplificado para qualquer aplicação que deseje utilizar a funcionalidade de injeção. Ele abstrai a complexidade interna da Injector_Core em uma única e conveniente função.
Initialize_Game:- Esta função estática é a interface pública da biblioteca.
- Primeiramente, ela valida a
inject_type_str(se éL"samp"ouL"omp") e a converte para oenum class Types::Inject_Type. Em caso de string inválida, exibe um erro e termina. - Em seguida, cria uma instância da
Injector::Injector_Core. - Finalmente, delega a execução da lógica principal para
Injector_Core::Initialize_Game, que é onde todo o processo de validação, criação de processo e injeção de DLL é orquestrado.
// Exemplo de trecho relevante de injector.hpp
// A interface pública para iniciar o jogo
#if defined(SAMP_INJECTOR_CXX_MODERN)
inline bool Initialize_Game(std::wstring_view inject_type, std::wstring_view folder, std::wstring_view nickname, std::wstring_view ip, std::wstring_view port, std::wstring_view password) {
#elif defined(SAMP_INJECTOR_CXX_14)
inline bool Initialize_Game(const std::wstring& inject_type, const std::wstring& folder, const std::wstring& nickname, const std::wstring& ip, const std::wstring& port, const std::wstring& password) {
#endif
Types::Inject_Type type;
// Converte a string de tipo de injeção para o enum correspondente
if (inject_type == Constants::INJECT_TYPE_SAMP)
type = Types::Inject_Type::SAMP;
else if (inject_type == Constants::INJECT_TYPE_OMP)
type = Types::Inject_Type::OMP;
else
// Exibe erro se o tipo de injeção for inválido
return (Error_Utils::Show_Error(L"Modo de injeção inválido. Use 'samp' ou 'omp'.", Types::Inject_Type::SAMP), false);
Injector::Injector_Core injector; // Cria a instância do núcleo do injetor
// Delega a lógica principal para o Injector_Core
return injector.Initialize_Game(type, folder, nickname, ip, port, password);
}A funcionalidade central desta biblioteca é orquestrar uma sequência precisa de operações para injetar as DLLs do cliente SA-MP ou OMP no processo do GTA:SA. Este ciclo é cuidadosamente planejado para garantir estabilidade e compatibilidade.
O processo se inicia com a chamada à função global Initialize_Game (injector.hpp), que atua como o principal ponto de contato para a aplicação que utiliza a biblioteca. Esta função recebe todos os parâmetros cruciais, como o tipo de injeção desejado (SA-MP ou OMP), o diretório do jogo e os dados de conexão ao servidor (nickname, IP, porta, senha).
Ao ser invocada, a função Initialize_Game cria uma instância de Injector::Injector_Core. No construtor desta classe (injector_core.hpp), a primeira e essencial etapa de configuração do ambiente é executada: a elevação de privilégios.
Note
Privileges::Enable_Debug_Privilege(): Esta chamada (privileges.hpp) concede ao processo da aplicação o privilégio SE_DEBUG_NAME. Este privilégio é vital, pois permite que o aplicativo execute operações de baixo nível em outros processos do Windows, como ler e escrever em sua memória e criar threads remotas – ações fundamentais para a técnica de injeção de DLL.
Com os privilégios ajustados, o método Injector_Core::Initialize_Game procede com uma série de validações rigorosas. Esta é uma fase preventiva que minimiza a chance de falhas em etapas posteriores e fornece feedback imediato ao usuário.
- Validação da Porta:
Validation::Validate_Portverifica se o número da porta de conexão está formatado corretamente e se encontra dentro do intervalo de1a65535(constants.hpp). - Validação do nickname:
Validation::Validate_Nicknamegarante que o nickname do jogador não esteja vazio e não exceda o limite de23caracteres. - Verificação de Arquivos Essenciais:
Validation::Validate_Filesinspeciona o diretório do jogo para confirmar a presença degta_sa.exe,samp.dlle, se a injeção for do tipo OMP, tambémomp-client.dll.
Warning
Qualquer falha nesta etapa resulta na exibição imediata de uma MessageBox com uma mensagem de erro detalhada (error_utils.hpp) e a interrupção do processo de injeção. Isso evita tentativas inúteis de prosseguir com uma configuração inválida.
Após a validação bem-sucedida, a função Injector_Core::Build_Command_Args é responsável por construir a linha de comando formatada que será passada ao gta_sa.exe. Esta linha de comando inclui todos os parâmetros necessários para que o cliente SA-MP/OMP se conecte automaticamente a um servidor, como -n "nickname" -h "IP" -p "Porta" -z "Senha".
O componente Process (process.hpp) é então encarregado de iniciar o executável do GTA:SA.
Important
A função Process::Create_Game_Process utiliza a flag CREATE_SUSPENDED (constants.hpp) ao chamar a API CreateProcessW do Windows. Esta é uma medida de design crítica: o jogo é carregado na memória e sua thread principal é criada, mas sua execução é pausada. Isso cria um ambiente controlado e estável, ideal para a injeção de DLLs, antes que o jogo possa inicializar suas próprias defesas ou lógicas internas. Os handles do processo e da thread são obtidos e gerenciados com segurança via Resource_Handle::Unique_Resource.
Com o processo do jogo em estado de suspensão, a injeção do samp.dll pode ser realizada de forma segura. O método Injector_Core::Inject_DLL_With_Status_Check delega esta tarefa ao Process::Inject_DLL, que executa os seguintes passos da técnica de remote thread injection:
- Localização da Função
LoadLibraryW: O endereço da funçãoLoadLibraryWé identificado. Esta operação utiliza as constantesConstants::KERNEL32_DLLeConstants::LOAD_LIBRARY_FUNCpara obter umhandlepara akernel32.dlle, em seguida, localizar o endereço da função de carregamento de bibliotecas dinâmicas. - Alocação de Memória Remota:
VirtualAllocExé utilizada para reservar um bloco de memória no espaço de endereço virtual do processogta_sa.exe(que está suspenso). O tamanho deste bloco é suficiente para armazenar o caminho completo dosamp.dll. - Escrita do Caminho da DLL: O caminho completo do arquivo
samp.dllé gravado nesta memória remota recém-alocada porWriteProcessMemory. - Criação de Thread Remota:
CreateRemoteThreadé chamada para criar uma novathreaddentro do processogta_sa.exe. O ponto de entrada desta novathreadé o endereço deLoadLibraryW, e o argumento que ela recebe é o ponteiro para o caminho da DLL que acabamos de gravar. - Monitoramento da Injeção: A execução da
threadremota é monitorada porWaitForSingleObjectpor um período definido porConstants::DLL_INJECTION_TIMEOUT_MS. - Verificação do Resultado: O código de saída da
threadremota é obtido viaGetExitCodeThread. Um valor de retorno diferente de zero indica queLoadLibraryWfoi bem-sucedida em carregar osamp.dll.
Warning
Em caso de qualquer falha durante a injeção do samp.dll, uma mensagem de erro específica (error_utils.hpp) é exibida, o processo de injeção é abortado, e os recursos são liberados.
Se o tipo de injeção especificado for OMP, as etapas detalhadas no ponto 6 são repetidas para o omp-client.dll.
Tip
A injeção de omp-client.dll sempre ocorre após a injeção bem-sucedida de samp.dll. Isso se deve ao fato de que o cliente Open Multiplayer se baseia na infraestrutura fornecida pelo samp.dll.
Finalmente, se todas as injeções foram concluídas com sucesso, o método process_info.Resume() é invocado. Esta chamada executa ResumeThread na thread principal do gta_sa.exe. Neste momento, o jogo é ativado e inicia sua execução normal, mas já com as DLLs do SA-MP/OMP carregadas em sua memória e com os parâmetros de conexão configurados, permitindo uma conexão automatizada ao servidor.
Warning
Se a retomada da thread do jogo falhar, uma última mensagem de erro é apresentada ao usuário.
A biblioteca é meticulosamente projetada para comunicar claramente qualquer problema que possa surgir durante o processo de inicialização e injeção. Em qualquer ponto de falha, uma MessageBox com uma descrição detalhada é apresentada ao usuário, muitas vezes complementada com mensagens de erro do sistema operacional.
Estes erros são detectados na fase inicial (validation.hpp), antes de qualquer interação de baixo nível com o sistema, e indicam problemas com os dados fornecidos pelo usuário ou com a configuração do ambiente.
- Mensagem de Erro (Exemplo 1):
"Nickname cannot be empty. Please provide a valid nickname." - Mensagem de Erro (Exemplo 2):
"Nickname length exceeds the maximum allowed of 23 characters. Please use a shorter nickname." - Razão: O nome de usuário (
nickname) fornecido está vazio ou ultrapassa o limite máximo de 23 caracteres permitido pelos clientes SA-MP/OMP. - Solução: O usuário deve inserir um nome de usuário válido que respeite os critérios de comprimento.
- Mensagem de Erro (Exemplo 1):
"Invalid port format. The port must be a numeric value. Please provide a valid integer for the port." - Mensagem de Erro (Exemplo 2):
"The specified port number (70000) is outside the valid range of 1 to 65535. Please provide a valid port." - Razão: O valor fornecido para a porta não é um número inteiro ou está fora do intervalo válido (1 a 65535).
- Solução: O usuário precisa fornecer um número de porta válido e dentro do intervalo especificado.
- Mensagem de Erro (Exemplo 1):
"Game executable not found. Please ensure 'gta_sa.exe' exists at the specified path: C:\Games\GTA San Andreas\gta_sa.exe" - Mensagem de Erro (Exemplo 2):
"SA-MP library not found. Please ensure 'samp.dll' exists at the specified path: C:\Games\GTA San Andreas\samp.dll" - Mensagem de Erro (Exemplo 3, para OMP):
"OMP library not found. Please ensure 'omp-client.dll' exists at the specified path for OMP injection: C:\Games\GTA San Andreas\omp-client.dll" - Razão: Um ou mais arquivos cruciais (
gta_sa.exe,samp.dll,omp-client.dll) não foram encontrados no diretório do jogo especificado. - Solução: Verifique o caminho da pasta do jogo e garanta que todos os arquivos necessários estejam presentes e acessíveis.
Estes erros ocorrem quando a biblioteca tenta iniciar o executável do jogo (gta_sa.exe).
- Mensagem de Erro (Exemplo):
"Failed to create game process. Ensure 'gta_sa.exe' is not running and you have sufficient permissions to execute the file. System Error: Access is denied." - Razão:
- Executável em Uso:
gta_sa.exejá pode estar em execução, ou há algum bloqueio do sistema operacional que impede a criação de uma nova instância. - Permissões Insuficientes: A aplicação pode não ter as permissões adequadas para iniciar o
gta_sa.exeou para acessar o arquivo. - Executável Corrompido: Embora a validação básica verifique a existência do arquivo, ele pode estar corrompido ou inacessível.
- Executável em Uso:
- Solução: Certifique-se de que nenhuma instância de
gta_sa.exeesteja ativa. Tente executar sua aplicação como administrador. Verifique a integridade do arquivogta_sa.exe.
Estes são os erros mais críticos e detalhados, ocorrendo durante a tentativa de injetar samp.dll ou omp-client.dll no processo suspenso do jogo. As mensagens de erro geralmente começam com "Failed to inject <DLL_NAME>:\n" e são seguidas por uma descrição específica e um código de erro do sistema.
- Mensagem de Erro (Parte):
"Failed to find the address of LoadLibraryW in kernel32.dll." - Razão: A função
LoadLibraryW, uma API fundamental do Windows para carregamento dinâmico de DLLs, não pôde ser encontrada nakernel32.dll. Este é um problema de baixo nível extremamente raro, que aponta para uma possível corrupção do sistema operacional ou um ambiente de execução altamente incomum. - Solução: Uma reinicialização do sistema pode resolver. Se persistir, pode indicar um problema mais grave na instalação do Windows.
- Mensagem de Erro (Parte):
"Failed to allocate memory in the target process (VirtualAllocEx). System Error: Not enough storage is available to process this command." - Razão: A biblioteca não conseguiu alocar um bloco de memória no espaço de endereço virtual do processo
gta_sa.exe.- Permissões: Sua aplicação pode não ter permissões suficientes para modificar o espaço de memória de outro processo.
- Proteção de Processo: Mecanismos de segurança do sistema operacional ou softwares anti-cheat podem estar bloqueando a alocação de memória em processos externos.
- Solução: Execute sua aplicação como administrador. Verifique se programas de segurança (antivírus, anti-cheat) estão interferindo e, se possível, desative-os temporariamente para testar.
- Mensagem de Erro (Parte):
"Failed to write DLL path to process memory (WriteProcessMemory). System Error: Access is denied." - Razão: Memória foi alocada no processo do jogo, mas a biblioteca não conseguiu gravar o caminho da DLL nesse local.
- Permissões/Proteção: Similar à falha de alocação de memória, pode ser um problema de permissão de escrita ou uma proteção de memória ativa.
- Solução: As mesmas soluções para a falha de alocação de memória se aplicam.
- Mensagem de Erro (Parte):
"Failed to create remote thread (CreateRemoteThread). System Error: The parameter is incorrect." - Razão: A API
CreateRemoteThreadfalhou ao iniciar uma novathreadno processogta_sa.exepara invocarLoadLibraryW.- Segurança: Muitos sistemas anti-cheat e proteções de SO monitoram e bloqueiam a criação de
threadsremotas, pois é uma técnica comum de injeção. - Estado do Processo: O processo do jogo pode estar em um estado instável que impede a criação de
threads.
- Segurança: Muitos sistemas anti-cheat e proteções de SO monitoram e bloqueiam a criação de
- Solução: Desative temporariamente qualquer software anti-cheat ou antivírus. Tente executar a aplicação como administrador.
- Mensagem de Erro (Parte):
"Timeout or error waiting for remote thread (WaitForSingleObject). System Error: The wait operation timed out." - Razão: A
threadremota (que chamaLoadLibraryW) não concluiu sua execução dentro do tempo limite estabelecido (10 segundos).- Congelamento:
LoadLibraryWpode ter travado, demorado excessivamente, ou ter sido interceptada/bloqueada.
- Congelamento:
- Solução: Isso pode indicar que a DLL está com dificuldades para carregar ou que algo a está impedindo. Verificar logs do sistema ou do próprio SA-MP/OMP (se disponíveis) pode oferecer mais pistas.
- Mensagem de Erro (Parte):
"LoadLibraryW call failed in the target process. The DLL might be corrupt, missing dependencies, or blocked by security software." - Razão: A
threadremota foi concluída, mas o valor de retorno deLoadLibraryWfoi0(ouNULL), indicando que a DLL não foi carregada com sucesso.- DLL Corrompida/Inexistente: A DLL pode ter sido movida, excluída ou corrompida após a validação inicial.
- Dependências Ausentes:
samp.dllouomp-client.dllpodem ter dependências (outras DLLs) que não estão presentes no diretório do jogo ou noPATHdo sistema. - Erro Interno da DLL: A própria DLL pode ter um erro interno que impede seu carregamento.
- Solução: Verifique a integridade dos arquivos
samp.dll/omp-client.dll. Certifique-se de que todas as suas dependências estejam presentes.
Este é o último ponto de falha possível no ciclo de injeção.
- Mensagem de Erro (Exemplo):
"Failed to resume the game process thread: Invalid handle." - Razão: A API
ResumeThreadfalhou ao reativar athreadprincipal dogta_sa.exe.- Handle Inválido: O
handledathreadpode ter sido invalidado por algum evento inesperado. - Permissão: A aplicação pode não ter permissão para alterar o estado da
thread.
- Handle Inválido: O
- Solução: Tente executar a aplicação como administrador. Se o problema persistir, pode indicar um problema de estabilidade mais profundo no sistema ou no processo do jogo.
Copyright © AlderGrounds
Este software é licenciado sob os termos da Licença MIT ("Licença"); você pode utilizar este software de acordo com as condições da Licença. Uma cópia da Licença pode ser obtida em: MIT License
A presente licença concede, gratuitamente, a qualquer pessoa que obtenha uma cópia deste software e arquivos de documentação associados, os seguintes direitos:
- Utilizar, copiar, modificar, mesclar, publicar, distribuir, sublicenciar e/ou vender cópias do software sem restrições
- Permitir que pessoas para as quais o software é fornecido façam o mesmo, desde que sujeitas às condições a seguir
Todas as cópias ou partes substanciais do software devem incluir:
- O aviso de direitos autorais acima
- Este aviso de permissão
- O aviso de isenção de responsabilidade abaixo
O software e toda a documentação associada são protegidos por leis de direitos autorais. A AlderGrounds mantém a titularidade dos direitos autorais originais do software.
O SOFTWARE É FORNECIDO "COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM DETERMINADO FIM E NÃO VIOLAÇÃO.
EM NENHUMA CIRCUNSTÂNCIA OS AUTORES OU TITULARES DOS DIREITOS AUTORAIS SERÃO RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM AÇÃO DE CONTRATO, DELITO OU DE OUTRA FORMA, DECORRENTE DE, FORA DE OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTRAS NEGOCIAÇÕES NO SOFTWARE.
Para informações detalhadas sobre a Licença MIT, consulte: https://opensource.org/licenses/MIT