@@ -651,6 +651,54 @@ BlImgUnLoadImage (
651
651
return BlImgUnallocateImageBuffer (ImageBase , ImageSize , ImageFlags );
652
652
}
653
653
654
+ unsigned int BlUtlCheckSum (unsigned int PartialSum , PUCHAR Source , unsigned int Length , unsigned int Flags )
655
+ {
656
+ unsigned int Type ; // eax@1
657
+ int Type1 ; // eax@1
658
+ unsigned int AlignedLength ; // ebx@3
659
+ unsigned int i ; // ebx@21 MAPDST
660
+
661
+ Type = Flags & 3 ;
662
+ Type1 = Type - 1 ;
663
+ if (Type1 )
664
+ {
665
+ if (Type1 == 1 )
666
+ {
667
+ PartialSum = (unsigned __int16 )PartialSum ;
668
+ AlignedLength = Length & ~1 ;
669
+ if (Length & ~1 )
670
+ {
671
+ i = 0 ;
672
+ do
673
+ {
674
+ PartialSum += * (unsigned __int16 * )& Source [i ];
675
+ if (Flags & 0x10000 )
676
+ PartialSum = (unsigned __int16 )((PartialSum >> 16 ) + PartialSum );
677
+ i += 2 ;
678
+ } while (i < AlignedLength );
679
+ }
680
+
681
+ if (Length != AlignedLength )
682
+ {
683
+ PartialSum += (unsigned __int8 )Source [AlignedLength ];
684
+ if (Flags & 0x10000 )
685
+ PartialSum = (unsigned __int16 )((PartialSum >> 16 ) + PartialSum );
686
+ }
687
+ if (Flags & 0x40000 )
688
+ return ~PartialSum ;
689
+ PartialSum = (unsigned __int16 )PartialSum ;
690
+ }
691
+ }
692
+ else
693
+ {
694
+ EfiPrintf (L"checksum type not supported\r\n" );
695
+ }
696
+
697
+ if (Flags & 0x40000 )
698
+ return ~PartialSum ;
699
+ return PartialSum ;
700
+ }
701
+
654
702
NTSTATUS
655
703
ImgpLoadPEImage (
656
704
_In_ PBL_IMG_FILE ImageFile ,
@@ -670,11 +718,28 @@ ImgpLoadPEImage (
670
718
ULONGLONG VirtualSize ;
671
719
PHYSICAL_ADDRESS PhysicalAddress ;
672
720
PIMAGE_NT_HEADERS NtHeaders ;
721
+ USHORT SectionCount ;
722
+ USHORT CheckSum , PartialSum ;
723
+ PIMAGE_SECTION_HEADER Section ;
724
+ ULONG_PTR EndOfHeaders , SectionStart ;
725
+ ULONG i ;
726
+ BOOLEAN First ;
727
+ ULONG_PTR Slack , SectionEnd ;
728
+ ULONG SectionSize , RawSize ;
729
+ ULONG BytesRead , RemainingLength ;
730
+ UCHAR LocalBuffer [1024 ];
731
+ USHORT FinalSum ;
732
+ ULONG Offset ;
733
+ ULONG AlignSize ;
673
734
674
735
/* Initialize locals */
675
736
LocalFile = NULL ;
676
737
ImageBuffer = NULL ;
677
738
FileSize = 0 ;
739
+ First = FALSE;
740
+ VirtualAddress = NULL ;
741
+ Offset = 0 ;
742
+ VirtualSize = 0 ;
678
743
679
744
/* Get the size of the image */
680
745
Status = ImgpGetFileSize (ImageFile , & FileSize );
@@ -846,6 +911,229 @@ ImgpLoadPEImage (
846
911
goto Quickie ;
847
912
}
848
913
914
+ First = FALSE;
915
+
916
+ /* Record how many sections we have */
917
+ SectionCount = NtHeaders -> FileHeader .NumberOfSections ;
918
+
919
+ /* Capture the current checksum and reset it */
920
+ CheckSum = NtHeaders -> OptionalHeader .CheckSum ;
921
+ NtHeaders -> OptionalHeader .CheckSum = 0 ;
922
+
923
+ /* Calculate the checksum of the header, and restore the original one */
924
+ PartialSum = BlUtlCheckSum (0 , VirtualAddress , HeaderSize , 0x10002 );
925
+ NtHeaders -> OptionalHeader .CheckSum = CheckSum ;
926
+
927
+ /* Record our current position (right after the headers) */
928
+ EndOfHeaders = (ULONG_PTR )VirtualAddress + HeaderSize ;
929
+
930
+ /* Get the first section and iterate through each one */
931
+ Section = IMAGE_FIRST_SECTION (NtHeaders );
932
+ for (i = 0 ; i < SectionCount ; i ++ )
933
+ {
934
+ /* Compute where this section starts */
935
+ SectionStart = (ULONG_PTR )VirtualAddress + Section -> VirtualAddress ;
936
+
937
+ /* Make sure that the section fits within the image */
938
+ if ((VirtualSize < Section -> VirtualAddress ) ||
939
+ ((PVOID )SectionStart < VirtualAddress ))
940
+ {
941
+ Status = STATUS_INVALID_IMAGE_FORMAT ;
942
+ goto Quickie ;
943
+ }
944
+
945
+ /* Check if there's slack space between header end and the section */
946
+ if (!(First ) && (EndOfHeaders < SectionStart ))
947
+ {
948
+ /* Zero it out */
949
+ Slack = SectionStart - EndOfHeaders ;
950
+ RtlZeroMemory ((PVOID )EndOfHeaders , Slack );
951
+ }
952
+
953
+ /* Get the section virtual size and the raw size */
954
+ SectionSize = Section -> Misc .VirtualSize ;
955
+ RawSize = Section -> SizeOfRawData ;
956
+
957
+ /* Safely align the raw size by 2 */
958
+ Status = RtlULongAdd (RawSize , 1 , & AlignSize );
959
+ if (!NT_SUCCESS (Status ))
960
+ {
961
+ goto Quickie ;
962
+ }
963
+ AlignSize = ALIGN_DOWN_BY (AlignSize , 2 );
964
+
965
+ /* IF we don't have a virtual size, use the raw size */
966
+ if (!SectionSize )
967
+ {
968
+ SectionSize = RawSize ;
969
+ }
970
+
971
+ /* If we don't have raw data, ignore the raw size */
972
+ if (!Section -> PointerToRawData )
973
+ {
974
+ RawSize = 0 ;
975
+ }
976
+ else if (SectionSize < RawSize )
977
+ {
978
+ /* And if the virtual size is smaller, use it as the final size */
979
+ RawSize = SectionSize ;
980
+ }
981
+
982
+ /* Make sure that the section doesn't overflow in memory */
983
+ Status = RtlULongAdd (Section -> VirtualAddress ,
984
+ SectionSize ,
985
+ & SectionEnd );
986
+ if (!NT_SUCCESS (Status ))
987
+ {
988
+ Status = STATUS_INVALID_IMAGE_FORMAT ;
989
+ goto Quickie ;
990
+ }
991
+
992
+ /* Make sure that it fits within the image */
993
+ if (VirtualSize < SectionEnd )
994
+ {
995
+ Status = STATUS_INVALID_IMAGE_FORMAT ;
996
+ goto Quickie ;
997
+ }
998
+
999
+ /* Make sure it doesn't overflow on disk */
1000
+ Status = RtlULongAdd (Section -> VirtualAddress ,
1001
+ AlignSize ,
1002
+ & SectionEnd );
1003
+ if (!NT_SUCCESS (Status ))
1004
+ {
1005
+ Status = STATUS_INVALID_IMAGE_FORMAT ;
1006
+ goto Quickie ;
1007
+ }
1008
+
1009
+ /* Make sure that it fits within the disk image as well */
1010
+ if (VirtualSize < SectionEnd )
1011
+ {
1012
+ Status = STATUS_INVALID_IMAGE_FORMAT ;
1013
+ goto Quickie ;
1014
+ }
1015
+
1016
+ /* So does this section have a valid size after all? */
1017
+ if (RawSize )
1018
+ {
1019
+ /* Are we in the first iteration? */
1020
+ if (!First )
1021
+ {
1022
+ /* Yes, read the section data */
1023
+ Status = ImgpReadAtFileOffset (LocalFile ,
1024
+ AlignSize ,
1025
+ Section -> PointerToRawData ,
1026
+ (PVOID )SectionStart ,
1027
+ NULL );
1028
+ if (!NT_SUCCESS (Status ))
1029
+ {
1030
+ goto Quickie ;
1031
+ }
1032
+
1033
+ /* Update our current offset */
1034
+ Offset = AlignSize + Section -> PointerToRawData ;
1035
+
1036
+ /* Update the checksum to include this section */
1037
+ PartialSum = BlUtlCheckSum (PartialSum ,
1038
+ (PUCHAR )SectionStart ,
1039
+ AlignSize ,
1040
+ 0x10002 );
1041
+ }
1042
+ }
1043
+
1044
+ /* Are we in the first iteration? */
1045
+ if (!First )
1046
+ {
1047
+ /* Is there space at the end of the section? */
1048
+ if (RawSize < SectionSize )
1049
+ {
1050
+ /* Zero out the slack space that's there */
1051
+ Slack = SectionSize - RawSize ;
1052
+ RtlZeroMemory ((PVOID )(SectionStart + RawSize ), Slack );
1053
+ }
1054
+
1055
+ /* Update our tail offset */
1056
+ EndOfHeaders = SectionStart + SectionSize ;
1057
+ }
1058
+
1059
+ /* Move to the next section */
1060
+ Section ++ ;
1061
+ }
1062
+
1063
+ /* Are we in the first iteration? */
1064
+ if (!First )
1065
+ {
1066
+ /* Go to the end of the file */
1067
+ SectionStart = (ULONG_PTR )VirtualAddress + VirtualSize ;
1068
+
1069
+ /* Is there still some slack space left? */
1070
+ if (EndOfHeaders < SectionStart )
1071
+ {
1072
+ /* Zero it out */
1073
+ Slack = SectionStart - EndOfHeaders ;
1074
+ RtlZeroMemory ((PVOID )EndOfHeaders , Slack );
1075
+ }
1076
+ }
1077
+
1078
+ /* Did the first iteration complete OK? */
1079
+ if ((NT_SUCCESS (Status )) && !(First ))
1080
+ {
1081
+ /* Check how many non-image bytes are left in the file */
1082
+ RemainingLength = FileSize - Offset ;
1083
+ while (RemainingLength )
1084
+ {
1085
+ /* See if the read will fit into our local buffer */
1086
+ if (RemainingLength >= sizeof (LocalBuffer ))
1087
+ {
1088
+ /* Nope, cap it */
1089
+ BytesRead = sizeof (LocalBuffer );
1090
+ }
1091
+ else
1092
+ {
1093
+ /* Yes, but there's less to read */
1094
+ BytesRead = RemainingLength ;
1095
+ }
1096
+
1097
+ /* Read 1024 bytes into the local buffer */
1098
+ Status = ImgpReadAtFileOffset (LocalFile ,
1099
+ BytesRead ,
1100
+ Offset ,
1101
+ LocalBuffer ,
1102
+ & BytesRead );
1103
+ if (!(NT_SUCCESS (Status )) || !(BytesRead ))
1104
+ {
1105
+ Status = STATUS_FILE_INVALID ;
1106
+ goto Quickie ;
1107
+ }
1108
+
1109
+ /* Advance the offset and reduce the length */
1110
+ RemainingLength -= BytesRead ;
1111
+ Offset += BytesRead ;
1112
+
1113
+ /* Compute the checksum of this leftover space */
1114
+ PartialSum = BlUtlCheckSum (PartialSum ,
1115
+ LocalBuffer ,
1116
+ BytesRead ,
1117
+ 0x10002 );
1118
+ }
1119
+
1120
+ /* Finally, calculate the final checksum and compare it */
1121
+ FinalSum = FileSize + PartialSum ;
1122
+ if ((FinalSum != CheckSum ) && (PartialSum == 0xFFFF ))
1123
+ {
1124
+ /* It hit overflow, so set it to the file size */
1125
+ FinalSum = FileSize ;
1126
+ }
1127
+
1128
+ /* If the checksum doesn't match, and caller is enforcing, bail out */
1129
+ EfiPrintf (L"Final checksum: %lx. Original: %lx\r\n" , FinalSum , CheckSum );
1130
+ if ((FinalSum != CheckSum ) && !(Flags & 0x10000 ))
1131
+ {
1132
+ Status = STATUS_IMAGE_CHECKSUM_MISMATCH ;
1133
+ goto Quickie ;
1134
+ }
1135
+ }
1136
+
849
1137
EfiPrintf (L"MORE PE TODO: %lx\r\n" , NtHeaders -> OptionalHeader .AddressOfEntryPoint );
850
1138
EfiStall (100000000 );
851
1139
0 commit comments