Class: AppInfo::PE

Inherits:
File
  • Object
show all
Extended by:
Forwardable
Includes:
Helper::Archive, Helper::HumanFileSize
Defined in:
lib/app_info/pe.rb

Overview

Windows PE parser

Defined Under Namespace

Classes: VersionInfo

Constant Summary collapse

ARCH =
{
  0x014c => 'x86',
  0x0200 => 'Intel Itanium',
  0x8664 => 'x64',
  0x1c0 => 'arm',
  0xaa64 => 'arm64',
  0x5032 => 'RISC-v 32',
  0x5064 => 'RISC-v 64',
  0x5128 => 'RISC-v 128'
}.freeze

Constants included from Helper::HumanFileSize

Helper::HumanFileSize::FILE_SIZE_UNITS

Instance Attribute Summary

Attributes inherited from File

#file, #logger

Instance Method Summary collapse

Methods included from Helper::Archive

#tempdir, #unarchive

Methods included from Helper::HumanFileSize

#file_to_human_size, #number_to_human_size

Methods inherited from File

#format, #initialize, #not_implemented_error!

Constructor Details

This class inherits a constructor from AppInfo::File

Instance Method Details

#archsString Also known as: architectures



115
116
117
# File 'lib/app_info/pe.rb', line 115

def archs
  ARCH[image_file_header.Machine] || 'unknown'
end

#assembly_versionString



96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks

#binary_fileString



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/app_info/pe.rb', line 189

def binary_file
  @binary_file ||= lambda {
    file_io = ::File.open(@file, 'rb')
    return @file unless file_io.read(100) =~ AppInfo::ZIP_RETGEX

    zip_file = Zip::File.open(@file)
    zip_entry = zip_file.glob('*.exe').first
    raise NotFoundError, 'Not found .exe file in archive file' if zip_entry.nil?

    exe_file = tempdir(zip_entry.name, prefix: 'pe-exe', system: true)
    zip_entry.extract(exe_file)
    zip_file.close

    return exe_file
  }.call
end

#binary_size(human_size: false) ⇒ Object



55
56
57
# File 'lib/app_info/pe.rb', line 55

def binary_size(human_size: false)
  file_to_human_size(binary_file, human_size: human_size)
end

#build_versionString?



110
111
112
# File 'lib/app_info/pe.rb', line 110

def build_version
  special_build || private_build || assembly_version
end

#clear!Object



181
182
183
184
185
186
# File 'lib/app_info/pe.rb', line 181

def clear!
  @io = nil
  @pe = nil
  @icons = nil
  @imports = nil
end

#company_nameString



96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks


96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks

#deviceSymbol



38
39
40
# File 'lib/app_info/pe.rb', line 38

def device
  Device::WINDOWS
end

#file_descriptionString



96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks

#file_versionString



96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks

#iconsArray{String}



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/app_info/pe.rb', line 128

def icons
  @icons ||= lambda {
    # Fetch the largest size icon
    files = []
    pe.resources&.find_all do |res|
      next unless res.type == 'ICON'

      filename = "#{::File.basename(file, '.*')}-#{res.type}-#{res.id}.bmp"
      icon_file = tempdir(filename, prefix: 'pe', system: true)
      mask_icon_file = icon_file.sub('.bmp', '.mask.bmp')

      begin
        ::File.open(icon_file, 'wb') do |f|
          f << res.restore_bitmap(io)
        end

        if res.bitmap_mask(io)
          mask_icon_file = icon_file.sub('.bmp', '.mask.bmp')
          ::File.open(mask_icon_file, 'wb') do |f|
            f << res.bitmap_mask(io)
          end
        end
      rescue StandardError => e
        # ignore pedump throws any exception.
        raise e unless e.backtrace.first.include?('pedump')

        FileUtils.rm_f(icon_file)
      ensure
        next unless ::File.exist?(icon_file)

        mask_file = ::File.exist?(mask_icon_file) ? mask_icon_file : nil
        files << (icon_file, mask_file: mask_file)
      end
    end

    files
  }.call
end

#importsHash{String => String}



121
122
123
124
125
# File 'lib/app_info/pe.rb', line 121

def imports
  @imports ||= pe.imports.each_with_object({}) do |import, obj|
    obj[import.module_name] = import.first_thunk.map(&:name).compact
  end
end

#internal_nameString



96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks


96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks

#manufacturerSymbol



28
29
30
# File 'lib/app_info/pe.rb', line 28

def manufacturer
  Manufacturer::MICROSOFT
end

#original_filenameString



96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks

#pePEdump



168
169
170
171
172
173
174
# File 'lib/app_info/pe.rb', line 168

def pe
  @pe ||= lambda {
    pe = PEdump.new(io)
    pe.logger.level = Logger::FATAL # ignore :warn logger output
    pe
  }.call
end

#platformSymbol



33
34
35
# File 'lib/app_info/pe.rb', line 33

def platform
  Platform::WINDOWS
end

#private_buildString



96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks

#product_nameString Also known as: name



96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks

#product_versionString



96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks

#release_versionString?

Find #product_version then fallback to #file_version



104
105
106
# File 'lib/app_info/pe.rb', line 104

def release_version
  product_version || file_version
end

#size(human_size: false) ⇒ Integer, String

return file size

Examples:

Read file size in integer

aab.size                    # => 3618865

Read file size in human readabale

aab.size(human_size: true)  # => '3.45 MB'


51
52
53
# File 'lib/app_info/pe.rb', line 51

def size(human_size: false)
  file_to_human_size(@file, human_size: human_size)
end

#special_buildString



96
97
98
# File 'lib/app_info/pe.rb', line 96

def_delegators :version_info, :product_name, :product_version, :company_name, :assembly_version,
:file_version, :file_description, :copyright, :special_build, :private_build,
:original_filename, :internal_name, :legal_trademarks

#version_infoVersionInfo



177
178
179
# File 'lib/app_info/pe.rb', line 177

def version_info
  @version_info ||= VersionInfo.new(pe.version_info)
end