diff --git a/README.md b/README.md index b93769a..42bebb3 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ pedump [![Build Status](https://travis-ci.org/zed-0xff/pedump.png?branch=mast News ---- ``` +2024.01.15 - add "--set-os-version VER" cmdline option for patching OS version in PE header 2023.12.04 - workaround IO.pread() not available on windows 2021.02.18 - updated gems; changed open-uri to URI.open; enabled SSL on https://pedump.me/ 2020.08.09 - CLI: added resource extracting with --extract ID @@ -89,6 +90,7 @@ Usage ID: section:rva/0x1000 - section by RVA ID: section:raw/0x400 - section by RAW_PTR --va2file VA Convert RVA to file offset + --set-os-version VER Patch OS version in PE header -W, --web Uploads files to a https://pedump.me for a nice HTML tables with image previews, diff --git a/README.md.tpl b/README.md.tpl index 6a540f7..b274b21 100644 --- a/README.md.tpl +++ b/README.md.tpl @@ -4,6 +4,8 @@ pedump [![Build Status](https://travis-ci.org/zed-0xff/pedump.png?branch=mast News ---- ``` +2024.01.15 - add "--set-os-version VER" cmdline option for patching OS version in PE header +2023.12.04 - workaround IO.pread() not available on windows 2021.02.18 - updated gems; changed open-uri to URI.open; enabled SSL on https://pedump.me/ 2020.08.09 - CLI: added resource extracting with --extract ID 2020.07.28 - 0.6.1; better RICH HDR parsing/output diff --git a/lib/pedump/cli.rb b/lib/pedump/cli.rb index ac4af85..151cb93 100644 --- a/lib/pedump/cli.rb +++ b/lib/pedump/cli.rb @@ -118,6 +118,10 @@ def run @actions << [:va2file, va] end + opts.on "--set-os-version VER", "Patch OS version in PE header" do |ver| + @actions << [:set_os_version, ver] + end + opts.separator '' opts.on "-W", "--web", "Uploads files to a #{URL_BASE}","for a nice HTML tables with image previews,","candies & stuff" do @@ -337,6 +341,8 @@ def dump_action action, f return when :extract return extract action[1] + when :set_os_version + return set_os_version action[1] when :va2file @pedump.sections(f) va = action[1] =~ /(^0x)|(h$)/i ? action[1].to_i(16) : action[1].to_i @@ -914,6 +920,40 @@ def extract_section id _copy_stream @pedump.io, $stdout, section.SizeOfRawData, section.PointerToRawData end + def set_os_version ver + raise "[!] invalid version #{ver.inspect}" unless ver =~ /\A(\d+)\.(\d+)\Z/ + raise "[!] no IMAGE_OPTIONAL_HEADER" if @pedump.pe.ifh.SizeOfOptionalHeader.to_i == 0 + major = $1.to_i + minor = $2.to_i + ver = "#{major}.#{minor}" + ioh = @pedump.pe.image_optional_header + + prev_os_ver = "#{ioh.MajorOperatingSystemVersion}.#{ioh.MinorOperatingSystemVersion}" + prev_ss_ver = "#{ioh.MajorSubsystemVersion}.#{ioh.MinorSubsystemVersion}" + + if prev_os_ver == ver && prev_ss_ver == ver + @pedump.logger.warn "[?] already has #{ver}" + return + end + + if prev_os_ver != ver + ioh.MajorOperatingSystemVersion = major + ioh.MinorOperatingSystemVersion = minor + @pedump.logger.warn "[.] MajorOperatingSystemVersion: #{prev_os_ver} -> #{ver}" + end + + if prev_ss_ver != ver + ioh.MajorSubsystemVersion = major + ioh.MinorSubsystemVersion = minor + @pedump.logger.warn "[.] MajorSubsystemVersion: #{prev_ss_ver} -> #{ver}" + end + + io = @pedump.io.reopen(@file_name,'rb+') + io.seek @pedump.pe.ioh_offset + io.write ioh.pack + io.close + end + private # https://github.com/zed-0xff/pedump/issues/44 diff --git a/lib/pedump/pe.rb b/lib/pedump/pe.rb index 4914c55..aae4132 100644 --- a/lib/pedump/pe.rb +++ b/lib/pedump/pe.rb @@ -7,6 +7,8 @@ class PE < Struct.new( :image_optional_header, # includes data directory :section_table ) + attr_accessor :ioh_offset + alias :ifh :image_file_header alias :ifh= :image_file_header= alias :ioh :image_optional_header @@ -68,7 +70,7 @@ def self.read f, args = {} end pe = PE.new(pe_sig) pe.image_file_header = IMAGE_FILE_HEADER.read(f) - ioh_offset = f.tell # offset to IMAGE_OPTIONAL_HEADER + pe.ioh_offset = f.tell # offset to IMAGE_OPTIONAL_HEADER if pe.ifh.SizeOfOptionalHeader.to_i > 0 if pe.x64? pe.image_optional_header = IMAGE_OPTIONAL_HEADER64.read(f, pe.ifh.SizeOfOptionalHeader) @@ -81,7 +83,7 @@ def self.read f, args = {} # The Windows loader expects to find the PE section headers after the optional header. It calculates the address of the first section header by adding SizeOfOptionalHeader to the beginning of the optional header. # // http://www.phreedom.org/research/tinype/ - f.seek( ioh_offset + pe.ifh.SizeOfOptionalHeader.to_i ) + f.seek( pe.ioh_offset + pe.ifh.SizeOfOptionalHeader.to_i ) pe.sections = read_sections(f, nToRead, args) pe_end = f.tell