memmod: fix protected delayed load the right way

The reason this was failing before is that dloadsup.h's
DloadObtainSection was doing a linear search of sections to find which
header corresponds with the IMAGE_DELAYLOAD_DESCRIPTOR section, and we
were stupidly overwriting the VirtualSize field, so the linear search
wound up matching the .text section, which then it found to not be
marked writable and failed with FAST_FAIL_DLOAD_PROTECTION_FAILURE.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2021-07-29 01:27:40 +02:00
parent c89f5ca665
commit bad6caeb82
2 changed files with 13 additions and 9 deletions

View file

@ -166,6 +166,7 @@ func (module *Module) finalizeSections() error {
sectionData.address = uintptr(sections[0].PhysicalAddress()) | imageOffset sectionData.address = uintptr(sections[0].PhysicalAddress()) | imageOffset
sectionData.alignedAddress = alignDown(sectionData.address, uintptr(module.headers.OptionalHeader.SectionAlignment)) sectionData.alignedAddress = alignDown(sectionData.address, uintptr(module.headers.OptionalHeader.SectionAlignment))
sectionData.size = module.realSectionSize(&sections[0]) sectionData.size = module.realSectionSize(&sections[0])
sections[0].SetVirtualSize(uint32(sectionData.size))
sectionData.characteristics = sections[0].Characteristics sectionData.characteristics = sections[0].Characteristics
// Loop through all sections and change access flags. // Loop through all sections and change access flags.
@ -173,6 +174,7 @@ func (module *Module) finalizeSections() error {
sectionAddress := uintptr(sections[i].PhysicalAddress()) | imageOffset sectionAddress := uintptr(sections[i].PhysicalAddress()) | imageOffset
alignedAddress := alignDown(sectionAddress, uintptr(module.headers.OptionalHeader.SectionAlignment)) alignedAddress := alignDown(sectionAddress, uintptr(module.headers.OptionalHeader.SectionAlignment))
sectionSize := module.realSectionSize(&sections[i]) sectionSize := module.realSectionSize(&sections[i])
sections[i].SetVirtualSize(uint32(sectionSize))
// Combine access flags of all sections that share a page. // Combine access flags of all sections that share a page.
// TODO: We currently share flags of a trailing large section with the page of a first small section. This should be optimized. // TODO: We currently share flags of a trailing large section with the page of a first small section. This should be optimized.
if sectionData.alignedAddress == alignedAddress || sectionData.address+sectionData.size > alignedAddress { if sectionData.alignedAddress == alignedAddress || sectionData.address+sectionData.size > alignedAddress {
@ -491,15 +493,6 @@ func LoadLibrary(data []byte) (module *Module, err error) {
return return
} }
// Disable protected delayed load for now. TODO: We should support this properly at some point.
if IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG < module.headers.OptionalHeader.NumberOfRvaAndSizes {
directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG)
if directory.Size != 0 && directory.VirtualAddress != 0 {
loadConfig := (*IMAGE_LOAD_CONFIG_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
loadConfig.GuardFlags &^= IMAGE_GUARD_PROTECT_DELAYLOAD_IAT
}
}
// Mark memory pages depending on section headers and release sections that are marked as "discardable". // Mark memory pages depending on section headers and release sections that are marked as "discardable".
err = module.finalizeSections() err = module.finalizeSections()
if err != nil { if err != nil {

View file

@ -332,6 +332,17 @@ func (imgimpdesc *IMAGE_IMPORT_DESCRIPTOR) OriginalFirstThunk() uint32 {
return imgimpdesc.characteristicsOrOriginalFirstThunk return imgimpdesc.characteristicsOrOriginalFirstThunk
} }
type IMAGE_DELAYLOAD_DESCRIPTOR struct {
Attributes uint32
DllNameRVA uint32
ModuleHandleRVA uint32
ImportAddressTableRVA uint32
ImportNameTableRVA uint32
BoundImportAddressTableRVA uint32
UnloadInformationTableRVA uint32
TimeDateStamp uint32
}
type IMAGE_LOAD_CONFIG_CODE_INTEGRITY struct { type IMAGE_LOAD_CONFIG_CODE_INTEGRITY struct {
Flags uint16 Flags uint16
Catalog uint16 Catalog uint16