ms check

Сообщения
1,012
Реакции
814
Помог
10 раз(а)
Пилю плагин для чека мониторингов по их хешим, и что-то мне кажется перемудрился =D
В общем хочу советы по коду, может что убрать или улучшить.
Имеет свою отдельную базу, задействует API Речекера.
Ищет неизвестные хеши, туп логирует название файлов и их хеш, затем по дефам можно понять чья контора

C++:
#include < amxmodx >
#include < reapi >

#pragma semicolon 1

#define LOGS_MS_UNKNOWN                                                            // Ведение журналов для сбора неизвестных хешей

new const HASHES_DIRECTORY[ ]                =    "/addons/rechecker/dlls";        // Путь до директории хранилище данных
new const HASHES_FILE_NAME[ ]                =    "ms_hashes.ini";                // Наименование файла хранилище данных

new const LOGS_FOLDER_NAME[ ]                =    "ms_check";                        // Наименование каталога ведение журналов

new const LOGS_FILE_NAME__MS_KNOWN[ ]        =    "ms_log";                        // Наименование журналов для ведение информации известных хешей

#if defined LOGS_MS_UNKNOWN
new const LOGS_FILE_NAME__MS_UNKNOWN[ ]        =    "ms_unknown";                    // Наименование журналов для ведение информации неизвестных хешей
#endif

new const MS_UNKNOWN[ ]                        =    "[UNKNOWN]";                    // МС UNKNOWN
new const MS_STEAM[ ]                        =    "[STEAM]";                        // МС Steam
new const MS_RECLIENT[ ]                    =    "[RECLIENT]";                    // МС ReClient

const MAX_REGISTER_QUERY_FILE                =    32;                                // Максимальное количество зарегистрированных файлов

const ELLIPSES_ARG                            =    4;
const NULLED                                =    0;
const DP_PROTOCOL                            =    48;
const DP_AUTH_REVEMU                        =    4;

const MAX_LENGTH__PATH                        =    64;
const MAX_LENGTH__MS_CONTENT                =    256;
const MAX_LENGTH__MS_FILE                    =    64;
const MAX_LENGTH__MS_HASH                    =    32;
const MAX_LENGTH__MS_NAME                    =    32;
const MAX_LENGTH__AUTHID                    =    64;
const MAX_LENGTH__NAME                        =    32;
const MAX_LENGTH__IP                        =    16;
const MAX_LENGTH__TIME                        =    32;
const MAX_LENGTH__MESSAGE                    =    512;

enum _: MS_KNOWN_DATA
{
    MS_KNOWN__FILE[ MAX_LENGTH__MS_FILE ],
    MS_KNOWN__HASH[ MAX_LENGTH__MS_HASH ],
    MS_KNOWN__NAME[ MAX_LENGTH__MS_NAME ]
}

enum _: MS_UNKNOWN_DATA
{
    MS_UNKNOWN__FILE[ MAX_LENGTH__MS_FILE ],
    MS_UNKNOWN__HASH[ MAX_LENGTH__MS_HASH ]
}

new g_dpProvider;
new g_dpProtocol;

new g_sLogsDir[ MAX_LENGTH__PATH ];
new g_sMsHashesFile[ MAX_LENGTH__PATH + 32 ];

new g_aRegisterQueryFile[ MAX_REGISTER_QUERY_FILE ][ MAX_LENGTH__MS_FILE ];

new g_eMsKnownData[ MAX_PLAYERS + 1 ][ MAX_REGISTER_QUERY_FILE ][ MS_KNOWN_DATA ];
new g_eMsUnknownData[ MAX_PLAYERS + 1 ][ MAX_REGISTER_QUERY_FILE ][ MS_UNKNOWN_DATA ];

new bool: g_bMsKnown[ MAX_PLAYERS + 1 ];
new bool: g_bReClient[ MAX_PLAYERS + 1 ];

new Trie: g_tMsHashes;

public plugin_init( )
{
    register_plugin( "Master Servers Check", "2.1.2", "Javekson" );
    
    RegisterHookChain( RC_FileConsistencyProcess, "FileConsistencyProcess", .post = true );
    RegisterHookChain( RC_FileConsistencyFinal, "FileConsistencyFinal", .post = true );
}

public plugin_cfg( )
{
    formatex( g_sMsHashesFile, charsmax( g_sMsHashesFile ), "%s/%s", HASHES_DIRECTORY, HASHES_FILE_NAME );
    
    get_localinfo( "amxx_logs", g_sLogsDir, charsmax( g_sLogsDir ) );
    
    formatex( g_sLogsDir, charsmax( g_sLogsDir ), "%s/%s", g_sLogsDir, LOGS_FOLDER_NAME );
    
    if( !dir_exists( g_sLogsDir ) )
    {
        mkdir( g_sLogsDir );
    }
    
    g_dpProvider = get_cvar_pointer( "dp_r_id_provider" );
    
    g_dpProtocol = get_cvar_pointer( "dp_r_protocol" );
    
    g_tMsHashes = TrieCreate( );
    
    func_ReadMsHashesFile( );
}

public client_authorized( id )
{
    g_bMsKnown[ id ] = false;
    
    g_bReClient[ id ] = false;
    
    func_ReClientCheck( id );
    
    arrayset( g_eMsKnownData[ id ][ 0 ], NULLED, MAX_REGISTER_QUERY_FILE * MS_UNKNOWN_DATA );
    
    arrayset( g_eMsUnknownData[ id ][ 0 ], NULLED, MAX_REGISTER_QUERY_FILE * MS_UNKNOWN_DATA );
}

public FileConsistencyProcess( const id, const sMsFile[ ], const sCmd[ ], const ResourceType: eType, const iMsHash )
{
    if( iMsHash )
    {
        new iRegisterQueryFileSize = sizeof( g_aRegisterQueryFile );
        for(new i; i < iRegisterQueryFileSize; i++ )
        {
            if( equal( g_aRegisterQueryFile[ i ], sMsFile ) )
            {
                new sMsHash[ MAX_LENGTH__MS_HASH ];
                formatex( sMsHash, charsmax( sMsHash ), "%s", func_ByteToStringLE( iMsHash ) );
                
                strtolower( sMsHash );
                
                if( TrieKeyExists( g_tMsHashes, sMsHash ) )
                {
                    new sMsName[ MAX_LENGTH__MS_NAME ];
                    TrieGetString(g_tMsHashes, sMsHash, sMsName, charsmax( sMsName ) );
                    
                    formatex( g_eMsKnownData[ id ][ i ][ MS_KNOWN__FILE ], sizeof( g_eMsKnownData[ ][ ][ MS_KNOWN__FILE ] ), "%s", sMsFile );
                    formatex( g_eMsKnownData[ id ][ i ][ MS_KNOWN__HASH ], sizeof( g_eMsKnownData[ ][ ][ MS_KNOWN__HASH ] ), "%s", sMsHash );
                    formatex( g_eMsKnownData[ id ][ i ][ MS_KNOWN__NAME ], sizeof( g_eMsKnownData[ ][ ][ MS_KNOWN__NAME ] ), "%s", sMsName );
                    
                    g_bMsKnown[ id ] = true;
                }
                
                #if defined LOGS_MS_UNKNOWN
                else
                {
                    formatex( g_eMsUnknownData[ id ][ i ][ MS_UNKNOWN__FILE ], sizeof( g_eMsUnknownData[ ][ ][ MS_UNKNOWN__FILE ] ), "%s", sMsFile );
                    formatex( g_eMsUnknownData[ id ][ i ][ MS_UNKNOWN__HASH ], sizeof( g_eMsUnknownData[ ][ ][ MS_UNKNOWN__HASH ] ), "%s", sMsHash );
                }
                #endif
                
                break;
            }
        }
    }
}

public FileConsistencyFinal( const id )
{
    new sAuthID[ MAX_LENGTH__AUTHID ];
    get_user_authid( id, sAuthID, charsmax( sAuthID ) );
    
    new sPlayerName[ MAX_LENGTH__NAME ];
    get_user_name( id, sPlayerName, charsmax( sPlayerName ) );
    
    new sPlayerIP[ MAX_LENGTH__IP ];
    get_user_ip( id, sPlayerIP, charsmax( sPlayerIP ), .without_port = true );
    
    if( is_user_steam( id ) )
    {
        func_Logging( g_sLogsDir, LOGS_FILE_NAME__MS_KNOWN, "^"%-24s %-32s %-24s %s^"", MS_STEAM, sAuthID, sPlayerIP, sPlayerName );
        
        return PLUGIN_CONTINUE;
    }
    
    if( !g_bMsKnown[ id ] && is_user_re_client( id ) ) // fungun.net - реклиент, поэтому чекаем сначала g_bMsKnown( хеш ), затем реклиент
    {
        func_Logging( g_sLogsDir, LOGS_FILE_NAME__MS_KNOWN, "^"%-24s %-32s %-24s %s^"", MS_RECLIENT, sAuthID, sPlayerIP, sPlayerName );
        
        return PLUGIN_CONTINUE;
    }
    
    if( g_bMsKnown[ id ] )
    {
        new iMsKnownDataSize = sizeof( g_eMsKnownData[ ] );
        for(new i; i < iMsKnownDataSize; i++ )
        {
            if( g_eMsKnownData[ id ][ i ][ MS_KNOWN__HASH ] )
            {
                new sMsFile[ MAX_LENGTH__MS_FILE ];
                formatex( sMsFile, charsmax( sMsFile ), "%s", g_eMsKnownData[ id ][ i ][ MS_KNOWN__FILE ] );
                
                new sMsHash[ MAX_LENGTH__MS_HASH ];
                formatex( sMsHash, charsmax( sMsHash ), "%s", g_eMsKnownData[ id ][ i ][ MS_KNOWN__HASH ] );
                
                new sMsName[ MAX_LENGTH__MS_NAME ];
                formatex( sMsName, charsmax( sMsName ), "%s", g_eMsKnownData[ id ][ i ][ MS_KNOWN__NAME ] );
                
                func_Logging( g_sLogsDir, LOGS_FILE_NAME__MS_KNOWN, "^"%-24s %-32s %-24s %-32s %-48s %s^"", sMsName, sAuthID, sPlayerIP, sPlayerName, sMsFile, sMsHash );
            }
        }
    }
    else
    {
        #if defined LOGS_MS_UNKNOWN
        new iMsUnknownDataSize = sizeof( g_eMsUnknownData[ ] );
        
        for(new i; i < iMsUnknownDataSize; i++ )
        {
            if( g_eMsUnknownData[ id ][ i ][ MS_UNKNOWN__FILE ] )
            {
                new sMsFile[ MAX_LENGTH__MS_FILE ];
                formatex( sMsFile, charsmax( sMsFile ), "%s", g_eMsUnknownData[ id ][ i ][ MS_UNKNOWN__FILE ] );
                
                new sMsHash[ MAX_LENGTH__MS_HASH ];
                formatex( sMsHash, charsmax( sMsHash ), "%s", g_eMsUnknownData[ id ][ i ][ MS_UNKNOWN__HASH ] );
                
                func_Logging( g_sLogsDir, LOGS_FILE_NAME__MS_UNKNOWN, "^"%-48s %-16s %-32s %-24s %s^"", sMsFile, sMsHash, sAuthID, sPlayerIP, sPlayerName );
            }
        }
        #endif
        
        func_Logging( g_sLogsDir, LOGS_FILE_NAME__MS_KNOWN, "^"%-24s %-32s %-24s %s^"", MS_UNKNOWN, sAuthID, sPlayerIP, sPlayerName );
    }
    
    return PLUGIN_CONTINUE;
}

public handler_MsQueryFile( ) { }

func_ReadMsHashesFile( )
{
    new iFileID = fopen( g_sMsHashesFile, "rt" );
    
    new sMsContent[ MAX_LENGTH__MS_CONTENT ], sMsFile[ MAX_LENGTH__MS_FILE ], sMsHash[ MAX_LENGTH__MS_HASH ], sMsName[ MAX_LENGTH__MS_NAME ];
    
    while( !feof( iFileID ) )
    {
        fgets( iFileID, sMsContent, charsmax( sMsContent ) );
        
        trim( sMsContent );
        
        if( !sMsContent[ 0 ] || sMsContent[ 0 ] == ';' )
        {
            continue;
        }
        
        parse( sMsContent, sMsFile, charsmax( sMsFile ), sMsHash, charsmax( sMsHash ), sMsName, charsmax( sMsName ) );
        
        strtolower( sMsHash );
        
        new iRegisterQueryFileSize = sizeof( g_aRegisterQueryFile );
        for(new i; i < iRegisterQueryFileSize; i++ )
        {
            if( g_aRegisterQueryFile[ i ][ 0 ] )
            {
                if( equal( g_aRegisterQueryFile[ i ], sMsFile ) )
                {
                    TrieSetString( g_tMsHashes, sMsHash, sMsName );
                    
                    break;
                }
            }
            else
            {
                RegisterQueryFile( sMsFile, "handler_MsQueryFile", RES_TYPE_HASH_ANY );
                
                TrieSetString( g_tMsHashes, sMsHash, sMsName );
                
                g_aRegisterQueryFile[ i ] = sMsFile;
                
                break;
            }
        }
    }
    
    fclose( iFileID );
}

func_ReClientCheck( const id )
{
    server_cmd( "dp_clientinfo %d", id );
    server_exec( );
    
    if( get_pcvar_num( g_dpProtocol ) == DP_PROTOCOL )
    {
        if( get_pcvar_num( g_dpProvider ) == DP_AUTH_REVEMU )
        {
            query_client_cvar( id, "voice_quality", "QueryClientCvar_VoiceQuality" );
        }
    }
}

public QueryClientCvar_VoiceQuality( const id, const sCvar[ ], const sValue[ ] )
{
    g_bReClient[ id ] = bool: ( !equali( sValue, "Bad CVAR request" ) );
}

stock bool: is_user_re_client( id )
{
    return g_bReClient[ id ];
}

stock func_ByteToStringLE( iMsHash )
{
    new sMsHash[ MAX_LENGTH__MS_HASH ];
    formatex( sMsHash, charsmax( sMsHash ), "%02X%02X%02X%02X", ( iMsHash ) & 0xff, ( iMsHash >> 8 ) & 0xff, ( iMsHash >> 16 ) & 0xff, ( iMsHash >> 24 ) & 0xff );
    
    return sMsHash;
}

stock func_Logging( const sLogsDir[ ], const sFileName[ ], const sMessage[ ], any:... )
{
    new sFmtMsg[ MAX_LENGTH__MESSAGE ];
    vformat( sFmtMsg, charsmax( sFmtMsg ), sMessage, ELLIPSES_ARG );
    
    new sFileTime[ MAX_LENGTH__TIME ];
    get_time( "%d.%m.%Y", sFileTime, charsmax( sFileTime ) );
    
    new sLogFile[ MAX_LENGTH__PATH + 32 ];
    formatex( sLogFile, charsmax( sLogFile ), "%s/%s_%s.log", sLogsDir, sFileName, sFileTime );
    
    new iFileID = fopen( sLogFile, "at" );
    
    new sRecordTime[ MAX_LENGTH__TIME ];
    get_time( "%d.%m.%Y - %H:%M:%S", sRecordTime, charsmax( sRecordTime ) );
    
    fprintf( iFileID, "^"%s^" %s^n", sRecordTime, sFmtMsg );
    
    fclose( iFileID );
}
У одного админа произошел сбой, причину так и не смог выяснить
Зашел игрок Веня , как видим чекнуло файл voise_speex.dl и хеш 4b5f8a38

cs-booster.ru venya ../voise_speex.dll 4b5f8a38"

Вот только прикол в том, что этот хеш принадлежит файлу, согласно базе данных

"../config/rev_MasterServers.vdf" 4b5f8a38 "cs-booster.ru"

А файл ../voise_speex.dll принадлежит вообще boostcs.ru с другим хешем

"../voise_speex.dll" d79aed5c "boostcs.ru"

Получился такой вот переплет.

В чем прикол я так и не понял, залогировал динамический массив, все хеши там принадлежат правильным конторам, проверил массивые, все вроде верно записывается, так я и не понял в чем мог произойти сбой такой интересный.
 
Сообщения
197
Реакции
16
Помог
1 раз(а)
мб игрок заменил файл, или такого быть не может?
 
Сообщения
1,012
Реакции
814
Помог
10 раз(а)
kucklovod, я к сожалению не смог найти такой клиент, в файле voise_speex.dll содерижтся адрес мс, это тупо текстовый файл, хоть и с расширением dll, а в теории мог и заменить, все что угодно могло произойти
 
Сообщения
35
Реакции
12
Помог
1 раз(а)
Обратите внимание, если вы хотите заключить сделку с этим пользователем, он заблокирован
Сообщения
1,012
Реакции
814
Помог
10 раз(а)
Pokemoshka, просто по коду я не нашел способа лучше чем сейчас, на ум другое не приходит, плюс какая то ошибка вылезла, вот и думаю, то ли клиент кривой попался, то ли код, хотя я его продебажил, вроде все в норме. А клиенты кривые часто попадались, перекачал свыше 300-т клиентов, попался даже один клиент где три хеша от моников, что дало ошибку. Клиент получает сразу три конторы одновременно, в общем в плане раскруток все очень и очень весело, если не считая ворованные уники )
 
Сообщения
1,012
Реакции
814
Помог
10 раз(а)
Может вместо таких массивов
C++:
new g_eMsKnownData[ MAX_PLAYERS + 1 ][ MAX_REGISTER_QUERY_FILE ][ MS_KNOWN_DATA ];
new g_eMsUnknownData[ MAX_PLAYERS + 1 ][ MAX_REGISTER_QUERY_FILE ][ MS_UNKNOWN_DATA ];
Юзать Array ? Или не будет разницы?
 
Сообщения
1,012
Реакции
814
Помог
10 раз(а)
Ну в принципе не удивился, что нету ответа.

Все по тому же плагину вопрос, необходимо слать http запрос на сайт с данными - а сайт будет принимать эти данные и записывать их в бд, через что это вообще делается? через curl или есть еще что то?
 

Ayk

Сообщения
763
Реакции
476
Помог
19 раз(а)
Юзать Array ? Или не будет разницы?
Обычные массивы быстрее. Array обращается к модулю через нативы. Он лучше подходит когда заранее неизвестно число необходимых ячеек, т.к. динамически меняет размер.

необходимо слать http запрос на сайт с данными - а сайт будет принимать эти данные и записывать их в бд,
Если можно сразу обращаться к БД - MySQL.
Если нужен именно http запрос - gRIP (указано такое преимущество: В отличии от других реализаций (например CURL) имеет пул соеденений и может работать с тысячами соеденений в секунду одновременно. )
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу