class Metasm::COFF::OptionalHeader

present in linked files (exe/dll/kmod)

Public Instance Methods

decode(coff) click to toggle source

decodes a COFF optional header from coff.cursection also decodes directories in coff.directory

Calls superclass method Metasm::SerialStruct#decode
# File metasm/exe_format/coff_decode.rb, line 19
def decode(coff)
        return set_default_values(coff) if coff.header.size_opthdr == 0 and not coff.header.characteristics.include?('EXECUTABLE_IMAGE')
        off = coff.curencoded.ptr
        super(coff)
        nrva = (coff.header.size_opthdr - (coff.curencoded.ptr - off)) / 8
        nrva = @numrva if nrva < 0

        if nrva > DIRECTORIES.length or nrva != @numrva
                puts "W: COFF: Weird directories count #{@numrva}" if $VERBOSE
                nrva = DIRECTORIES.length if nrva > DIRECTORIES.length
        end

        coff.directory = {}
        DIRECTORIES[0, nrva].each { |dir|
                rva = coff.decode_word
                sz  = coff.decode_word
                if rva != 0 or sz != 0
                        coff.directory[dir] = [rva, sz]
                end
        }
end
encode(coff) click to toggle source

encodes an Optional header and the directories

Calls superclass method Metasm::SerialStruct#encode
# File metasm/exe_format/coff_encode.rb, line 14
def encode(coff)
        opth = super(coff)

        DIRECTORIES[0, @numrva].each { |d|
                if d = coff.directory[d]
                        d = d.dup
                        d[0] = Expression[d[0], :-, coff.label_at(coff.encoded, 0)] if d[0].kind_of?(::String)
                else
                        d = [0, 0]
                end
                opth << coff.encode_word(d[0]) << coff.encode_word(d[1])
        }

        opth
end
set_default_values(coff) click to toggle source

find good default values for optheader members, based on coff.sections

Calls superclass method Metasm::SerialStruct#set_default_values
# File metasm/exe_format/coff_encode.rb, line 31
def set_default_values(coff)
        @signature    ||= (coff.bitsize == 64 ? 'PE+' : 'PE')
        @link_ver_maj ||= 1
        @link_ver_min ||= 0
        @sect_align   ||= 0x1000
        align = lambda { |sz| EncodedData.align_size(sz, @sect_align) }
        @code_size    ||= coff.sections.find_all { |s| s.characteristics.include? 'CONTAINS_CODE' }.inject(0) { |sum, s| sum + align[s.virtsize] }
        @data_size    ||= coff.sections.find_all { |s| s.characteristics.include? 'CONTAINS_DATA' }.inject(0) { |sum, s| sum + align[s.virtsize] }
        @udata_size   ||= coff.sections.find_all { |s| s.characteristics.include? 'CONTAINS_UDATA' }.inject(0) { |sum, s| sum + align[s.virtsize] }
        @entrypoint = Expression[@entrypoint, :-, coff.label_at(coff.encoded, 0)] if entrypoint and not @entrypoint.kind_of?(::Integer)
        tmp = coff.sections.find { |s| s.characteristics.include? 'CONTAINS_CODE' }
        @base_of_code ||= (tmp ? Expression[coff.label_at(tmp.encoded, 0), :-, coff.label_at(coff.encoded, 0)] : 0)
        tmp = coff.sections.find { |s| s.characteristics.include? 'CONTAINS_DATA' }
        @base_of_data ||= (tmp ? Expression[coff.label_at(tmp.encoded, 0), :-, coff.label_at(coff.encoded, 0)] : 0)
        @file_align   ||= 0x200
        @os_ver_maj   ||= 4
        @subsys_maj   ||= 4
        @stack_reserve||= 0x100000
        @stack_commit ||= 0x1000
        @heap_reserve ||= 0x100000
        @heap_commit  ||= 0x1000
        @numrva       ||= DIRECTORIES.length

        super(coff)
end