@@ -329,7 +329,7 @@ namespace RC
329329 {
330330 std::vector<int > bytes;
331331 char * const start = const_cast <char *>(signature.data ());
332- char * const end = const_cast <char *>(signature.data ()) + strlen ( signature.data () );
332+ char * const end = const_cast <char *>(signature.data ()) + signature.size ( );
333333
334334 for (char * current = start; current < end; current++)
335335 {
@@ -367,11 +367,11 @@ namespace RC
367367 auto end_address = static_cast <uint8_t *>(module .lpBaseOfDll ) + module .SizeOfImage ;
368368
369369 MEMORY_BASIC_INFORMATION memory_info{};
370- DWORD protect_flags = PAGE_GUARD | PAGE_NOCACHE | PAGE_NOACCESS;
370+ DWORD protect_flags = PAGE_GUARD | PAGE_NOACCESS;
371371
372372 void * address_found{};
373373
374- for (uint8_t * i = start_address; i < end_address; ++i )
374+ for (uint8_t * i = start_address; i < end_address;)
375375 {
376376 if (VirtualQuery (i, &memory_info, sizeof (memory_info)))
377377 {
@@ -385,12 +385,16 @@ namespace RC
385385
386386 for (uint8_t * region_start = static_cast <uint8_t *>(memory_info.BaseAddress ); region_start < region_end; ++region_start)
387387 {
388- if (region_start > end_address || region_start + string_to_scan_for.size () > end_address)
388+ // Check boundaries - string_to_scan_for.size() is character count, need to multiply by sizeof(wchar_t) for bytes
389+ size_t string_size_bytes = string_to_scan_for.size () * sizeof (wchar_t );
390+ if (region_start > end_address ||
391+ region_start + string_size_bytes > end_address ||
392+ region_start + string_size_bytes > region_end)
389393 {
390394 break ;
391395 }
392396
393- std::wstring_view maybe_string = std::wstring_view (( const wchar_t *) region_start, string_to_scan_for.size ());
397+ std::wstring_view maybe_string = std::wstring_view (reinterpret_cast < const wchar_t *>( region_start) , string_to_scan_for.size ());
394398 if (maybe_string == string_to_scan_for)
395399 {
396400 address_found = region_start;
@@ -404,6 +408,10 @@ namespace RC
404408 }
405409 i = static_cast <uint8_t *>(memory_info.BaseAddress ) + memory_info.RegionSize ;
406410 }
411+ else
412+ {
413+ ++i;
414+ }
407415 }
408416
409417 return address_found;
@@ -436,7 +444,7 @@ namespace RC
436444 }
437445 }
438446
439- static auto make_mask (std::string_view pattern, SignatureContainer& signature_container, const size_t data_size ) -> PatternData
447+ static auto make_mask (std::string_view pattern, SignatureContainer& signature_container) -> PatternData
440448 {
441449 PatternData pattern_data{};
442450
@@ -474,16 +482,6 @@ namespace RC
474482 ++i;
475483 }
476484
477- static constexpr size_t Alignment = 32 ;
478- size_t count = (size_t )std::ceil ((float )data_size / Alignment);
479- size_t padding_size = count * Alignment - data_size;
480-
481- for (size_t i = 0 ; i < padding_size; i++)
482- {
483- pattern_data.pattern .push_back (0x00 );
484- pattern_data.mask .push_back (0x00 );
485- }
486-
487485 pattern_data.signature_container = &signature_container;
488486 return pattern_data;
489487 }
@@ -519,11 +517,11 @@ namespace RC
519517 }
520518 if (!end_address)
521519 {
522- start_address = static_cast <uint8_t *>(info.lpMaximumApplicationAddress );
520+ end_address = static_cast <uint8_t *>(info.lpMaximumApplicationAddress );
523521 }
524522
525523 MEMORY_BASIC_INFORMATION memory_info{};
526- DWORD protect_flags = PAGE_GUARD | PAGE_NOCACHE | PAGE_NOACCESS;
524+ DWORD protect_flags = PAGE_GUARD | PAGE_NOACCESS;
527525
528526 // TODO: Nasty nasty nasty. Come up with a better solution... wtf
529527 // It should ideally be able to work with the char* directly instead of converting to to vectors of ints
@@ -557,7 +555,7 @@ namespace RC
557555 }
558556
559557 // Loop everything
560- for (uint8_t * i = start_address; i < end_address; ++i )
558+ for (uint8_t * i = start_address; i < end_address;)
561559 {
562560 // Populate memory_info if VirtualQuery doesn't fail
563561 if (VirtualQuery (i, &memory_info, sizeof (memory_info)))
@@ -591,7 +589,13 @@ namespace RC
591589 }
592590
593591 // Skip if we're about to dereference uninitialized memory
594- if (region_start + sig.size () > region_end)
592+ if (region_start >= end_address)
593+ {
594+ break ;
595+ }
596+
597+ // Skip if signature would extend past boundaries
598+ if (region_start + (sig.size () / 2 ) > region_end || region_start + (sig.size () / 2 ) > end_address)
595599 {
596600 break ;
597601 }
@@ -652,6 +656,10 @@ namespace RC
652656
653657 i = static_cast <uint8_t *>(memory_info.BaseAddress ) + memory_info.RegionSize ;
654658 }
659+ else
660+ {
661+ ++i;
662+ }
655663 }
656664 }
657665
@@ -700,91 +708,119 @@ namespace RC
700708 }
701709 if (!end_address)
702710 {
703- start_address = static_cast <uint8_t *>(info.lpMaximumApplicationAddress );
711+ end_address = static_cast <uint8_t *>(info.lpMaximumApplicationAddress );
704712 }
705713
706- format_aob_strings (signature_containers);
707-
708714 std::vector<std::vector<PatternData>> pattern_datas{};
709715 for (auto & signature_container : signature_containers)
710716 {
711717 auto & pattern_data = pattern_datas.emplace_back ();
712718 for (auto & signature : signature_container.signatures )
713719 {
714- pattern_data.emplace_back (make_mask (signature.signature , signature_container, end_address - start_address ));
720+ pattern_data.emplace_back (make_mask (signature.signature , signature_container));
715721 }
716722 }
717723
718- // Loop everything
719- for (size_t container_index = 0 ; const auto & patterns : pattern_datas)
724+ MEMORY_BASIC_INFORMATION memory_info{};
725+ DWORD readable_flags = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY |
726+ PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
727+
728+ for (uint8_t * i = start_address; i < end_address;)
720729 {
721- for ( size_t signature_index = 0 ; const auto & pattern_data : patterns )
730+ if (! VirtualQuery (i, &memory_info, sizeof (memory_info)) )
722731 {
723- // If the container is refusing more calls then skip to the next container
724- if (pattern_data.signature_container ->ignore )
725- {
726- break ;
727- }
732+ ++i;
733+ continue ;
734+ }
728735
729- auto it = start_address;
730- auto end = it + (end_address - start_address) - (pattern_data.pattern .size ()) + 1 ;
731- uint8_t needle = pattern_data.pattern [0 ];
736+ if (!(memory_info.Protect & readable_flags) || !(memory_info.State & MEM_COMMIT) || (memory_info.Protect & PAGE_GUARD))
737+ {
738+ i += memory_info.RegionSize ;
739+ continue ;
740+ }
732741
733- bool skip_to_next_container{};
734- while (end != (it = std::find (it, end, needle)))
742+ uint8_t * region_start = static_cast <uint8_t *>(memory_info.BaseAddress );
743+ uint8_t * region_end = region_start + memory_info.RegionSize ;
744+
745+ auto scan_start = (region_start > start_address) ? region_start : start_address;
746+ auto scan_end = (region_end < end_address) ? region_end : end_address;
747+
748+ // Loop everything
749+ for (size_t container_index = 0 ; const auto & patterns : pattern_datas)
750+ {
751+ for (size_t signature_index = 0 ; const auto & pattern_data : patterns)
735752 {
736- bool found = true ;
737- for ( size_t pattern_offset = 0 ; pattern_offset < pattern_data.pattern . size (); ++pattern_offset )
753+ // If the container is refusing more calls then skip to the next container
754+ if ( pattern_data.signature_container -> ignore )
738755 {
739- if ((it[pattern_offset] & pattern_data.mask [pattern_offset]) != pattern_data.pattern [pattern_offset])
740- {
741- found = false ;
742- break ;
743- }
756+ break ;
744757 }
745758
746- if (found)
759+ auto it = scan_start;
760+ if (static_cast <size_t >(scan_end - scan_start) < pattern_data.pattern .size ())
747761 {
748- {
749- std::lock_guard<std::mutex> safe_scope (m_scanner_mutex);
762+ continue ; // Skip if pattern is larger than region
763+ }
764+ auto end = scan_end - pattern_data.pattern .size () + 1 ;
765+ uint8_t needle = pattern_data.pattern [0 ];
750766
751- // Checking for the second time if the container is refusing more calls
752- // This is required when multi-threading is enabled
753- if (pattern_data.signature_container ->ignore )
767+ bool skip_to_next_container{};
768+ while (end != (it = std::find (it, end, needle)))
769+ {
770+ bool found = true ;
771+ for (size_t pattern_offset = 0 ; pattern_offset < pattern_data.pattern .size (); ++pattern_offset)
772+ {
773+ if ((it[pattern_offset] & pattern_data.mask [pattern_offset]) != pattern_data.pattern [pattern_offset])
754774 {
755- skip_to_next_container = true ;
775+ found = false ;
756776 break ;
757777 }
778+ }
758779
759- // One of the signatures have found a full match so lets forward the details to the callable
760- pattern_data. signature_container -> index_into_signatures = signature_index;
761- pattern_data. signature_container -> match_address = it;
762- pattern_data. signature_container -> match_signature_size = pattern_data. pattern . size ( );
780+ if ( found)
781+ {
782+ {
783+ std::lock_guard<std::mutex> safe_scope (m_scanner_mutex );
763784
764- skip_to_next_container = pattern_data.signature_container ->on_match_found (*pattern_data.signature_container );
765- pattern_data.signature_container ->ignore = skip_to_next_container;
785+ // Checking for the second time if the container is refusing more calls
786+ // This is required when multi-threading is enabled
787+ if (pattern_data.signature_container ->ignore )
788+ {
789+ skip_to_next_container = true ;
790+ break ;
791+ }
766792
767- // Store results if the container at the containers request
768- if (pattern_data.signature_container ->store_results )
769- {
770- pattern_data.signature_container ->result_store .emplace_back (
771- SignatureContainerLight{.index_into_signatures = signature_index, .match_address = it});
793+ // One of the signatures have found a full match so lets forward the details to the callable
794+ pattern_data.signature_container ->index_into_signatures = signature_index;
795+ pattern_data.signature_container ->match_address = it;
796+ pattern_data.signature_container ->match_signature_size = pattern_data.pattern .size ();
797+
798+ skip_to_next_container = pattern_data.signature_container ->on_match_found (*pattern_data.signature_container );
799+ pattern_data.signature_container ->ignore = skip_to_next_container;
800+
801+ // Store results if the container at the containers request
802+ if (pattern_data.signature_container ->store_results )
803+ {
804+ pattern_data.signature_container ->result_store .emplace_back (
805+ SignatureContainerLight{.index_into_signatures = signature_index, .match_address = it});
806+ }
772807 }
773808 }
809+
810+ it++;
774811 }
775812
776- it++;
777- }
813+ if (skip_to_next_container)
814+ {
815+ // A match was found and signaled to skip to the next container
816+ break ;
817+ }
778818
779- if (skip_to_next_container)
780- {
781- // A match was found and signaled to skip to the next container
782- break ;
819+ ++signature_index;
783820 }
784-
785- ++signature_index;
821+ ++container_index;
786822 }
787- ++container_index ;
823+ i = region_end ;
788824 }
789825 }
790826
@@ -818,6 +854,11 @@ namespace RC
818854 return ;
819855 }
820856
857+ if (m_scan_method == ScanMethod::StdFind)
858+ {
859+ format_aob_strings (merged_containers);
860+ }
861+
821862 uint8_t * module_start_address = static_cast <uint8_t *>(merged_module_info.lpBaseOfDll );
822863
823864 if (merged_module_info.SizeOfImage >= m_multithreading_module_size_threshold)
@@ -867,6 +908,11 @@ namespace RC
867908 // Right now it can't be auto& or const auto& because the do_scan function takes a non-const since it needs to mutate the values inside the vector
868909 for (auto & [scan_target, signature_container] : signature_containers)
869910 {
911+ if (m_scan_method == ScanMethod::StdFind)
912+ {
913+ format_aob_strings (signature_container);
914+ }
915+
870916 uint8_t * module_start_address = static_cast <uint8_t *>(SigScannerStaticData::m_modules_info[scan_target].lpBaseOfDll );
871917 uint8_t * module_end_address = static_cast <uint8_t *>(module_start_address + SigScannerStaticData::m_modules_info[scan_target].SizeOfImage );
872918
0 commit comments