class PEdump::NE

from wine’s winnt.h

Constants

DEFAULT_CP

Attributes

io[RW]
offset[RW]

Public Class Methods

cp() click to toggle source
# File lib/pedump/ne.rb, line 39
def self.cp
  @@cp || DEFAULT_CP
end
cp=(cp) click to toggle source
# File lib/pedump/ne.rb, line 43
def self.cp= cp
  @@cp = cp
end
read(io, *args) click to toggle source
Calls superclass method
# File lib/pedump/ne.rb, line 47
def self.read io, *args
  self.cp = DEFAULT_CP
  offset = io.tell
  super.tap do |x|
    x.io, x.offset = io, offset
  end
end

Public Instance Methods

_detect_codepage(a, io=@io) click to toggle source
# File lib/pedump/ne.rb, line 228
def _detect_codepage a, io=@io
  a.find_all{ |res| res.type == 'VERSION' }.each do |res|
    res.parse(io)
    res.data.each do |vi|
      if vi.respond_to?(:Children) && vi.Children.respond_to?(:each)
        # vi is PEdump::NE::VS_VERSIONINFO
        vi.Children.each do |vfi|
          if vfi.is_a?(PEdump::NE::VarFileInfo) && vfi.Children.is_a?(PEdump::NE::Var)
            var = vfi.Children
            # var is PEdump::NE::Var
            if var.respond_to?(:Value) && var.Value.is_a?(Array) && var.Value.size == 2
              return var.Value.last
            end
          end
        end
      end
    end
  end
  nil
end
_id2string(id, io, res_base) click to toggle source
# File lib/pedump/ne.rb, line 186
def _id2string id, io, res_base
  if id & 0x8000 == 0
    # offset to name
    io.seek id + res_base
    namesize = (io.getc || 0.chr).ord
    io.read(namesize)
  else
    # numerical id
    "##{id & 0x7fff}"
  end
end
bundles(io=@io) click to toggle source
# File lib/pedump/ne.rb, line 369
def bundles io=@io
  io.seek @offset+ne_enttab
  bundles = []
  while bundle = Bundle.read(io)
    bundles << bundle
  end
  bundles
end
entrypoints(io=@io) click to toggle source
# File lib/pedump/ne.rb, line 378
def entrypoints io=@io
  @entrypoints ||=
    begin
      r = [0] # entrypoint indexes are 1-based
      bundles(io).each do |b|
        if b.entries.empty?
          b.num_entries.times{ r<<0 }
        else
          b.entries.each do |e|
            if e.is_a?(Bundle::MovableEntry)
              r << (e.seg_idx<<16) + e.offset
            elsif e.is_a?(Bundle::FixedEntry)
              r << (b.seg_idx<<16) + e.offset
            else
              raise "invalid ep #{e.inspect}"
            end
          end
        end
      end
      r
    end
end
exports(io=@io) click to toggle source

first string with ordinal 0 is a module name

# File lib/pedump/ne.rb, line 309
def exports io=@io
  exp_dir = IMAGE_EXPORT_DIRECTORY.new
  exp_dir.functions = []

  io.seek @offset+ne_restab
  while !io.eof && (namelen = io.getc.ord) > 0
    exp_dir.functions << ExportedFunction.new( io.read(namelen), io.read(2).unpack('v').first, 0 )
  end
  exp_dir.name = exp_dir.functions.shift.name if exp_dir.functions.any?

  a = []
  io.seek ne_nrestab
  while !io.eof && (namelen = io.getc.ord) > 0
    a << ExportedFunction.new( io.read(namelen), io.read(2).unpack('v').first, 0 )
  end
  exp_dir.description = a.shift.name if a.any?
  exp_dir.functions += a

  exp_dir.functions.each do |f|
    f.va = entrypoints[f.ord]
  end

  exp_dir
end
imports(io=@io) click to toggle source
# File lib/pedump/ne.rb, line 277
def imports io=@io
  @imports ||=
    begin
      io.seek @offset+ne_modtab
      modules = io.read(2*ne_cmod).unpack('v*')
      modules.map! do |ofs|
        io.seek @offset+ne_imptab+ofs
        namelen = io.getc.ord
        io.read(namelen)
      end

      r = []
      segments(io).each do |seg|
        seg.relocs.each do |rel|
          if rel.type == Reloc::TYPE_IMPORTORDINAL
            r << (f = PEdump::ImportedFunction.new)
            f.module_name = modules[rel.module_idx-1]
            f.ordinal = rel.func_idx
          elsif rel.type == Reloc::TYPE_IMPORTNAME
            r << (f = PEdump::ImportedFunction.new)
            f.module_name = modules[rel.module_idx-1]
            io.seek @offset+ne_imptab+rel.func_idx
            namelen = io.getc.ord
            f.name = io.read(namelen)
          end
        end
      end
      r
    end
end
resource_directory(io=@io) click to toggle source
# File lib/pedump/ne.rb, line 198
def resource_directory io=@io
  @resource_directory ||=
    begin
      res_base = ne_rsrctab+@offset
      io.seek res_base
      res_shift = io.read(2).unpack('v').first
      unless (0..16).include?(res_shift)
        PEdump.logger.error "[!] invalid res_shift = %d" % res_shift
        return []
      end
      PEdump.logger.info "[.] res_shift = %d" % res_shift
      r = []
      while !io.eof? && (g = ResourceGroup.read(io))
        r << g
      end
      r.each do |g|
        g.type = (g.type_id & 0x8000 != 0) && PEdump::ROOT_RES_NAMES[g.type_id & 0x7fff]
        g.type ||= _id2string( g.type_id, io, res_base)
        g.children.each do |res|
          res.name = _id2string(res.name_offset, io, res_base)
          res.offset ||= 0
          res.offset <<= res_shift
          res.size   ||= 0
          res.size   <<= res_shift
        end
      end
      r
    end
end
resources(io=@io) click to toggle source
# File lib/pedump/ne.rb, line 249
def resources io=@io
  a = []
  resource_directory(io).each do |grp|
    grp.children.each do |res|
      a << (r = Resource.new)
      r.id   = (res.name_offset & 0x7fff) if (res.name_offset & 0x8000) != 0
      r.type = grp.type
      r.size = res.size
      r.name = res.name
      r.file_offset = res.offset
      r.reserved = res.reserved
    end
  end

  # try to detect codepage
  cp = _detect_codepage(a, io)
  if cp
    PEdump::NE.cp = cp # XXX HACK
    PEdump.logger.info "[.] detect_codepage: #{cp.inspect}"
  else
    cp = DEFAULT_CP
    PEdump.logger.info "[.] detect_codepage failed, using default #{cp}"
  end

  a.each{ |r| r.parse(io, :cp => cp) }
  a
end
segments(io=@io) click to toggle source
# File lib/pedump/ne.rb, line 108
def segments io=@io
  @segments ||= io &&
    begin
      io.seek ne_segtab+@offset
      ne_cseg.times.map{ Segment.read(io) }.each do |seg|
        seg.file_offset = seg.offset << ne_align
        seg.relocs = []
        if (seg.flags & Segment::FLAG_RELOCINFO) != 0
          io.seek seg.file_offset + seg.size
          nRelocs = io.read(2).unpack('v').first
          seg.relocs = nRelocs.times.map{ Reloc.read(io) }
        end
      end
    end
end