Код (Text): const MaxObjects = 32; type TPE = class FMemStr : TMemoryStream; MZ_Header : IMAGE_DOS_HEADER; MZData : Pointer; PE_Header : IMAGE_NT_HEADERS; FSize : Cardinal; Sections : packed array[1..MaxObjects] of TImageSectionHeader; Objects : packed array[1..MaxObjects] of PByteArray; Procedure AddSection(Siz : Cardinal); Procedure Load(FName : String); Procedure Save(FName : String); end; Procedure TPE.AddSection(Siz : Cardinal); var n : Integer; sz : Cardinal; begin Inc(PE_Header.FileHeader.NumberOfSections); n :=PE_Header.FileHeader.NumberOfSections; inc(PE_Header.OptionalHeader.SizeOfImage, Siz); inc(PE_Header.OptionalHeader.SizeOfHeaders, SizeOf(TImageSectionHeader)); ZeroMemory(@Sections[n], SizeOf(TImageSectionHeader)); with Sections[n] do begin Name[0] :=Byte('.'); Name[1] :=Byte('d'); PointerToRawData := (FSize div PE_Header.OptionalHeader.FileAlignment + 1) * PE_Header.OptionalHeader.FileAlignment; Misc.VirtualSize :=Siz; SizeOfRawData := Siz; VirtualAddress:=$20000; Characteristics := $c0000040; end; GetMem(Objects[n], Siz); sz :=SizeOf(TImageSectionHeader) + PE_Header.OptionalHeader.FileAlignment; sz := (sz div PE_Header.OptionalHeader.FileAlignment) * PE_Header.OptionalHeader.FileAlignment; for n := 1 to PE_Header.FileHeader.NumberOfSections do inc(Sections[n].PointerToRawData, sz); end; Procedure TPE.Save(FName : String); Var tmp1 : Word; begin FMemStr := TMemoryStream.Create; FMemStr.WriteBuffer(MZData^, MZ_Header._lfanew); FMemStr.Seek(0, soFromBeginning); FMemStr.WriteBuffer(MZ_Header, sizeof(MZ_Header)); FMemStr.Seek(MZ_Header._lfanew, soFromBeginning); FMemStr.WriteBuffer(PE_Header, SizeOf(PE_Header)); FMemStr.WriteBuffer(Sections, SizeOf(TImageSectionHeader)*PE_Header.FileHeader.NumberOfSections); for tmp1 := 1 to PE_Header.FileHeader.NumberOfSections do begin FMemStr.Seek(Sections[tmp1].PointerToRawData, soFromBeginning); FMemStr.WriteBuffer(Objects[tmp1]^, Sections[tmp1].SizeOfRawData); end; FMemStr.SaveToFile(FName); FMemStr.Free; end; Procedure TPE.Load(FName : String); Var tmp1 : Word; begin FMemStr := TMemoryStream.Create; FMemStr.LoadFromFile(FName); FSize := FMemStr.Size; FMemStr.Seek(0, soFromBeginning); FMemStr.ReadBuffer(MZ_Header, sizeof(MZ_Header)); GetMem(MZData, MZ_Header._lfanew); FMemStr.Seek(0, soFromBeginning); FMemStr.ReadBuffer(MZData^, MZ_Header._lfanew); FMemStr.Seek(MZ_Header._lfanew, soFromBeginning); FMemStr.ReadBuffer(PE_Header, SizeOf(PE_Header)); FMemStr.ReadBuffer(Sections, SizeOf(TImageSectionHeader)*PE_Header.FileHeader.NumberOfSections); for tmp1 := 1 to PE_Header.FileHeader.NumberOfSections do begin GetMem(Objects[tmp1], Max(Sections[tmp1].Misc.VirtualSize, Sections[tmp1].SizeOfRawData)); FMemStr.Seek(Sections[tmp1].PointerToRawData, soFromBeginning); FMemStr.ReadBuffer(Objects[tmp1]^, Min(Sections[tmp1].Misc.VirtualSize, Sections[tmp1].SizeOfRawData)); end; FMemStr.Free; end; procedure TForm3.Button1Click(Sender: TObject); var PE : TPE; begin PE := TPE.Create; PE.Load(FileNameEdit1.Text); PE.AddSection($200); PE.Save(FileNameEdit1.Text + '.exe'); end; end. В результате получаю нерабочий PE, который LordPE влекую фиксит, но где я г-ню, я чет не пойму.
А про SectionAlignment/FileAlignment не забыли? Или именно в этом PE эти значения равны? Потому что к SizeOfImage нужно прибавлять не тоже самое, что и писать в SizeOfRawData. Да и заполнение поля VirtualAddress смущает. Прям таки такое фиксированное число?
Насчет VirtualAddress стоит вычислять: // Поиск максимального RVA MaxRVA := ish[0].VirtualAddress; MaxRVAIndex := 0; for i := 1 to ifh.NumberOfSections-1 do if ish.VirtualAddress > MaxRVA then begin MaxRVA := ish.VirtualAddress; MaxRVAIndex := i; end; В эксперименте я пробую с FASM.EXE, давая знаения чтоб ничего там в оригинале не попортить.
Shooshpanchik Это вопрос или утверждение? Вам виднее, какие там значения SectionAlignment/FileAlignment. Лучше бинарник выложите, хотя бы дамп заголовков.
обычно не нужно, если секция 1(заголовок соответственно тоже 1) то добавить еще одну просто обычно не выйдет, т к придется двигать в файле все остальные секции, если секций больше 1й, то править размер не нужно, т к SizeOfHeaders будет выровнен линкером на FileAlignment и его размер обычно покрывает заголовок новой секции, что не мешало бы? так это добавить проверку есть ли достаточное место, чтобы добавить еще один заголовок секции это что? По идее должно быть что-то вроде PE_Header.OptionalHeader.SizeOfImage, а не $20000 выравнивать необязательно, если у файла нет оверлея (либо подписи) он всегда будет выровнен, а если есть то секцию просто так не добавить новый размер должен быть выровнен на FileAlignment(Section Table (Section Headers)) Код (Text): #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. OptionalHeader.SizeOfInitializedData должен быть изменен на вирт размер секции размер образа должен быть выровнен на SectionAlignment (Optional Header Windows-Specific Fields (Image Only))
Вообщето и сдвигаю все: for n := 1 to PE_Header.FileHeader.NumberOfSections do inc(Sections[n].PointerToRawData, sz); Сейчас чуток изменил с учетом и даже И вроде весь Alignment выровнял,не ну вот все что у меня есть считают подкорректированный файл нормальным, и вот токо винда грит: C:\FASM.EXE.exe не является приложением Win32. Вот до и после: http://file.qb.by/8fdef0deb52e18cc95c6c6965d6fd5aa (66 кб) Разница видна, и вроде все корректно, но токо не запускается он
у вас rva добавленной секции не выровнен. 4 .d 00000200 00018162 <- (должно быть 18000) 00000200 00010600 00000040 остальное у файла в пределах нормы
Это ж VirtualAddress := PE_Header.OptionalHeader.SizeOfImage; Ранее я просто ставил его в $20000, счас, по формуле, с учетом Alignment он становится $19000 Но винда всеравно бракует файл, а остальные утилиты нормально открывают.
Shooshpanchik https://www.wasm.ru/forum/viewtopic.php?pid=389800#p389800 как минимум неверны SizeOfImage образа и VirtualAddress новой секции add вот ваш, исправленный вручную, файл http://www.sendspace.com/file/swt0d6 перечитывайте пост внимательнее, ни одной ошибки вами не исправлено, - выравнивания абсолютно нигде нет (там где заголовок изменен, все поля испорчены) - размер данных в файле расчитан неверно, у вас 0x200, должно быть - 0x400 - размер заголовка с правильного испорчен на неизвестно что - чексумма левая - размер образа левый - вирт адрес секции левый - физ адрес секции левый грубо говоря правильно только то, что NumberOfSections увеличен на 1 вобщем разбирайтесь еще