RBOOL collector_18_init ( HbsState* hbsState, rSequence config ) { RBOOL isSuccess = FALSE; rList extensions = NULL; rList patterns = NULL; RPCHAR strA = NULL; RPCHAR tmpA = NULL; RPWCHAR strW = NULL; RPWCHAR tmpW = NULL; RU32 maxSize = 0; RBOOL isCaseInsensitive = FALSE; if( NULL != hbsState ) { #ifdef RPAL_PLATFORM_WINDOWS // On Windows files and paths are not case sensitive. isCaseInsensitive = TRUE; #endif if( NULL == config || rSequence_getLIST( config, RP_TAGS_EXTENSIONS, &extensions ) || rSequence_getLIST( config, RP_TAGS_PATTERNS, &patterns ) ) { if( NULL != ( cacheMutex = rMutex_create() ) && NULL != ( matcherA = obsLib_new( 0, 0 ) ) && NULL != ( matcherW = obsLib_new( 0, 0 ) ) ) { cacheSize = 0; if( NULL != config && rSequence_getRU32( config, RP_TAGS_MAX_SIZE, &maxSize ) ) { cacheMaxSize = maxSize; } else { cacheMaxSize = MAX_CACHE_SIZE; } if( NULL != ( documentCache = HbsRingBuffer_new( 0, cacheMaxSize ) ) ) { if( NULL == config ) { // As a default we'll cache all new files obsLib_addPattern( matcherA, (RPU8)"", sizeof( RCHAR ), NULL ); obsLib_addPattern( matcherW, (RPU8)_WCH(""), sizeof( RWCHAR ), NULL ); } else { // If a config was provided we'll cache only certain extensions // specified. while( rList_getSTRINGA( extensions, RP_TAGS_EXTENSION, &strA ) ) { if( rpal_string_expand( strA, &tmpA ) ) { obsLib_addStringPatternA( matcherA, tmpA, TRUE, isCaseInsensitive, NULL ); rpal_memory_free( tmpA ); } if( NULL != ( strW = rpal_string_atow( strA ) ) ) { if( rpal_string_expandw( strW, &tmpW ) ) { obsLib_addStringPatternW( matcherW, tmpW, TRUE, isCaseInsensitive, NULL ); rpal_memory_free( tmpW ); } rpal_memory_free( strW ); } } while( rList_getSTRINGW( extensions, RP_TAGS_EXTENSION, &strW ) ) { if( rpal_string_expandw( strW, &tmpW ) ) { obsLib_addStringPatternW( matcherW, tmpW, TRUE, isCaseInsensitive, NULL ); rpal_memory_free( tmpW ); } if( NULL != ( strA = rpal_string_wtoa( strW ) ) ) { if( rpal_string_expand( strA, &tmpA ) ) { obsLib_addStringPatternA( matcherA, tmpA, TRUE, isCaseInsensitive, NULL ); rpal_memory_free( tmpA ); } rpal_memory_free( strA ); } } while( rList_getSTRINGA( patterns, RP_TAGS_STRING_PATTERN, &strA ) ) { if( rpal_string_expand( strA, &tmpA ) ) { obsLib_addStringPatternA( matcherA, tmpA, FALSE, isCaseInsensitive, NULL ); rpal_memory_free( tmpA ); } if( NULL != ( strW = rpal_string_atow( strA ) ) ) { if( rpal_string_expandw( strW, &tmpW ) ) { obsLib_addStringPatternW( matcherW, tmpW, FALSE, isCaseInsensitive, NULL ); rpal_memory_free( tmpW ); } rpal_memory_free( strW ); } } while( rList_getSTRINGW( patterns, RP_TAGS_STRING_PATTERN, &strW ) ) { if( rpal_string_expandw( strW, &tmpW ) ) { obsLib_addStringPatternW( matcherW, tmpW, FALSE, isCaseInsensitive, NULL ); rpal_memory_free( tmpW ); } if( NULL != ( strA = rpal_string_wtoa( strW ) ) ) { if( rpal_string_expand( strA, &tmpA ) ) { obsLib_addStringPatternA( matcherA, tmpA, FALSE, isCaseInsensitive, NULL ); rpal_memory_free( tmpA ); } rpal_memory_free( strA ); } } } if( rQueue_create( &createQueue, _freeEvt, 200 ) && notifications_subscribe( RP_TAGS_NOTIFICATION_FILE_CREATE, NULL, 0, createQueue, NULL ) && notifications_subscribe( RP_TAGS_NOTIFICATION_GET_DOCUMENT_REQ, NULL, 0, NULL, getDocument ) && rThreadPool_task( hbsState->hThreadPool, parseDocuments, NULL ) ) { isSuccess = TRUE; } } } if( !isSuccess ) { notifications_unsubscribe( RP_TAGS_NOTIFICATION_FILE_CREATE, createQueue, NULL ); notifications_unsubscribe( RP_TAGS_NOTIFICATION_GET_DOCUMENT_REQ, NULL, getDocument ); rQueue_free( createQueue ); createQueue = NULL; obsLib_free( matcherA ); obsLib_free( matcherW ); HbsRingBuffer_free( documentCache ); matcherA = NULL; matcherW = NULL; documentCache = NULL; rMutex_free( cacheMutex ); cacheMutex = NULL; } } } return isSuccess; }
RPRIVATE RVOID _searchForStrings ( rList stringsFound, rList searchStrings, RPU8 pBuff, RU64 size, RU64 baseAddr, RU32 minLength, RU32 maxLength ) { RPU8 pCurr; RPU8 pEnd; RPCHAR pStartStr = NULL; RBOOL isChar; RPU16 pwCurr; RPU16 pwEnd; RBOOL isWChar; RPWCHAR pwStartStr = NULL; RPWCHAR thisStrW = NULL; rSequence newFoundStr; pCurr = pBuff; pEnd = pBuff + size; // currently we only deal with NULL terminated strings // start with ascii strings... while( pCurr < pEnd ) { isChar = rpal_string_isprint( *pCurr ); if( NULL == pStartStr && isChar ) // found the begining of a string { pStartStr = (RPCHAR)pCurr; } else if( NULL != pStartStr && ( !isChar || 0 == *pCurr ) ) // found the end of a string { // is string NULL or Non-Ascii terminated if( 0 == *pCurr || !rpal_string_charIsAscii( *pCurr ) ) { // Null terminate it so we can use it like a normal string *pCurr = 0; // strlen is really pCurr - pStartStr if( (RU32)( (RPCHAR)pCurr - pStartStr ) >= minLength && (RU32)( (RPCHAR)pCurr - pStartStr ) <= maxLength ) // is string long enough { // convert string to wide char for comparision if( NULL != ( thisStrW = rpal_string_atow( pStartStr ) ) ) { if( _isStringInList( searchStrings, thisStrW ) && NULL != ( newFoundStr = rSequence_new() ) ) { rSequence_addSTRINGW( newFoundStr, RP_TAGS_STRING, thisStrW ); rSequence_addRU64( newFoundStr, RP_TAGS_MEMORY_ADDRESS, baseAddr + ( (RPU8)pStartStr - pBuff ) ); if( !rList_addSEQUENCE( stringsFound, newFoundStr ) ) { rSequence_free( newFoundStr ); } } rpal_memory_free( thisStrW ); } } } pStartStr = NULL; } pCurr++; } // Now look for Unicode strings pwCurr = (RPU16)pBuff; pwEnd = pwCurr + ( size / 2 ); while( pwCurr < pwEnd ) { isWChar = rpal_string_isprintW( *pwCurr ); if( NULL == pwStartStr && isWChar ) // found the begining of a string { pwStartStr = (RPWCHAR)pwCurr; } else if( NULL != pwStartStr && ( !isWChar || 0 == *pwCurr ) ) // found the end of a string { // is string NULL terminated if( 0 == *pwCurr ) { // wcslen is really pCurr - pStartStr if( (RU32)( (RPWCHAR)pwCurr - pwStartStr ) >= minLength && (RU32)( (RPWCHAR)pwCurr - pwStartStr ) <= maxLength ) // is string long enough { if( _isStringInList( searchStrings, pwStartStr ) && NULL != ( newFoundStr = rSequence_new() ) ) { rSequence_addSTRINGW( newFoundStr, RP_TAGS_STRING, pwStartStr ); rSequence_addRU64( newFoundStr, RP_TAGS_MEMORY_ADDRESS, baseAddr + ( (RPU8)pwStartStr - pBuff ) ); if( !rList_addSEQUENCE( stringsFound, newFoundStr ) ) { rSequence_free( newFoundStr ); } } } } pwStartStr = NULL; } pwCurr++; } }
static RVOID getDocument ( rpcm_tag notifId, rSequence notif ) { rSequence tmp = NULL; DocSearchContext ctx = { 0 }; RU32 hashSize = 0; rList foundDocs = NULL; RBOOL isAAlloced = FALSE; RBOOL isWAlloced = FALSE; UNREFERENCED_PARAMETER( notifId ); if( NULL != notif ) { if( !rSequence_getSTRINGA( notif, RP_TAGS_STRING_PATTERN, &ctx.exprA ) ) { ctx.exprA = NULL; } if( !rSequence_getSTRINGW( notif, RP_TAGS_STRING_PATTERN, &ctx.exprW ) ) { ctx.exprW = NULL; } if( NULL != ctx.exprA && NULL == ctx.exprW ) { ctx.exprW = rpal_string_atow( ctx.exprA ); isWAlloced = TRUE; } if( NULL != ctx.exprW && NULL == ctx.exprA ) { ctx.exprA = rpal_string_wtoa( ctx.exprW ); isAAlloced = TRUE; } if( !rSequence_getBUFFER( notif, RP_TAGS_HASH, (RPU8*)&ctx.pHash, &hashSize ) || sizeof( *ctx.pHash ) != hashSize ) { // Unexpected hash size, let's not gamble ctx.pHash = NULL; } } if( rMutex_lock( cacheMutex ) ) { if( NULL != ( foundDocs = rList_new( RP_TAGS_FILE_INFO, RPCM_SEQUENCE ) ) ) { while( HbsRingBuffer_find( documentCache, (HbsRingBufferCompareFunc)findDoc, &ctx, &tmp ) ) { // TODO: optimize this since if we're dealing with large files // we will be temporarily using large amounts of duplicate memory. // We just need to do some shallow free of the datastructures // somehow. if( NULL != ( tmp = rSequence_duplicate( tmp ) ) ) { if( !rList_addSEQUENCE( foundDocs, tmp ) ) { rSequence_free( tmp ); } } } if( !rSequence_addLIST( notif, RP_TAGS_FILES, foundDocs ) ) { rList_free( foundDocs ); } } rMutex_unlock( cacheMutex ); notifications_publish( RP_TAGS_NOTIFICATION_GET_DOCUMENT_REP, notif ); } if( isAAlloced ) { rpal_memory_free( ctx.exprA ); } if( isWAlloced ) { rpal_memory_free( ctx.exprW ); } }
static RVOID processCodeIdentA ( RPCHAR name, CryptoLib_Hash* pFileHash, RU64 codeSize, rSequence originalEvent ) { CodeIdent ident = { 0 }; rSequence notif = NULL; rSequence sig = NULL; RPWCHAR wPath = NULL; RPWCHAR cleanPath = NULL; ident.codeSize = codeSize; if( NULL != name ) { CryptoLib_hash( name, rpal_string_strlen( name ) * sizeof( RCHAR ), &ident.nameHash ); } if( NULL != pFileHash ) { rpal_memory_memcpy( &ident.fileHash, pFileHash, sizeof( *pFileHash ) ); } if( rMutex_lock( g_mutex ) ) { if( rpal_bloom_addIfNew( g_knownCode, &ident, sizeof( ident ) ) ) { rMutex_unlock( g_mutex ); if( NULL != ( notif = rSequence_new() ) ) { hbs_markAsRelated( originalEvent, notif ); if( ( rSequence_addSTRINGA( notif, RP_TAGS_FILE_PATH, name ) || rSequence_addSTRINGA( notif, RP_TAGS_DLL, name ) || rSequence_addSTRINGA( notif, RP_TAGS_EXECUTABLE, name ) ) && rSequence_addRU32( notif, RP_TAGS_MEMORY_SIZE, (RU32)codeSize ) && rSequence_addTIMESTAMP( notif, RP_TAGS_TIMESTAMP, rpal_time_getGlobal() ) ) { if( NULL != pFileHash ) { rSequence_addBUFFER( notif, RP_TAGS_HASH, (RPU8)pFileHash, sizeof( *pFileHash ) ); } if( NULL != ( wPath = rpal_string_atow( name ) ) ) { cleanPath = rpal_file_cleanw( wPath ); if( libOs_getSignature( cleanPath ? cleanPath : wPath, &sig, OSLIB_SIGNCHECK_NO_NETWORK, NULL, NULL, NULL ) ) { if( !rSequence_addSEQUENCE( notif, RP_TAGS_SIGNATURE, sig ) ) { rSequence_free( sig ); } } if( NULL != cleanPath ) { rpal_memory_free( cleanPath ); } rpal_memory_free( wPath ); } notifications_publish( RP_TAGS_NOTIFICATION_CODE_IDENTITY, notif ); } rSequence_free( notif ); } } else { rMutex_unlock( g_mutex ); } } }