diff --git a/Gemfile b/Gemfile index 439ac47..fbb87a0 100644 --- a/Gemfile +++ b/Gemfile @@ -1,20 +1,16 @@ # frozen_string_literal: true -source "https://rubygems.org" +source 'https://rubygems.org' -git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } -gem "terrapin" +gem 'rubocop', group: 'development' +gem 'terrapin' +gem 'thor', '~> 1.2.1' -# Added at 2017-12-24 10:16:46 +0100 by coderobe: -gem "thor", "~> 0.20.0" +gem 'pry', '~> 0.14.1' -# Added at 2017-12-24 12:04:47 +0100 by coderobe: -gem "pry", "~> 0.11.3" +gem 'posix-spawn', '~> 0.3.13' -# Added at 2017-12-24 12:27:01 +0100 by coderobe: -gem "posix-spawn", "~> 0.3.13" - -# Added at 2017-12-24 12:50:49 +0100 by coderobe: -gem "colorize", "~> 0.8.1" +gem 'colorize', '~> 0.8.1' diff --git a/Gemfile.lock b/Gemfile.lock index 2d0cc2e..dbe2ac6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,17 +1,39 @@ GEM remote: https://rubygems.org/ specs: + ast (2.4.2) climate_control (0.2.0) - coderay (1.1.2) + coderay (1.1.3) colorize (0.8.1) - method_source (0.9.0) - posix-spawn (0.3.13) - pry (0.11.3) - coderay (~> 1.1.0) - method_source (~> 0.9.0) + json (2.6.2) + method_source (1.0.0) + parallel (1.22.1) + parser (3.1.2.1) + ast (~> 2.4.1) + posix-spawn (0.3.15) + pry (0.14.1) + coderay (~> 1.1) + method_source (~> 1.0) + rainbow (3.1.1) + regexp_parser (2.6.0) + rexml (3.2.5) + rubocop (1.37.1) + json (~> 2.3) + parallel (~> 1.10) + parser (>= 3.1.2.1) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.23.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.23.0) + parser (>= 3.1.1.0) + ruby-progressbar (1.11.0) terrapin (0.6.0) climate_control (>= 0.0.3, < 1.0) - thor (0.20.0) + thor (1.2.1) + unicode-display_width (2.3.0) PLATFORMS ruby @@ -19,9 +41,10 @@ PLATFORMS DEPENDENCIES colorize (~> 0.8.1) posix-spawn (~> 0.3.13) - pry (~> 0.11.3) + pry (~> 0.14.1) + rubocop terrapin - thor (~> 0.20.0) + thor (~> 1.2.1) BUNDLED WITH - 1.17.3 + 2.3.24 diff --git a/README.md b/README.md index bd380d1..3dc9ebc 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Some dependencies might not offer a package for your linux distribution **(like - Extracted VBIOS roms will be placed in `./output` ## Compatibility (non-exhaustive) +- Acer Aspire E1-571G (and models with the same BIOS) - [ASUS N580GD](https://github.com/coderobe/VBiosFinder/issues/15) - Lenovo y50-70 - [Lenovo S5 2nd Gen (20JAA009HH)](https://github.com/coderobe/VBiosFinder/issues/1) diff --git a/_init.rb b/_init.rb index 0a17e4f..783cecf 100644 --- a/_init.rb +++ b/_init.rb @@ -1,4 +1,4 @@ -require "./src/cli" +require './src/cli' $0=ARGV.first $PROGRAM_NAME=$0 diff --git a/src/cli.rb b/src/cli.rb index 4c66795..6ad87c9 100644 --- a/src/cli.rb +++ b/src/cli.rb @@ -1,20 +1,21 @@ -require "thor" -require "fileutils" -require "logger" -require "colorize" -require "./src/methods" -require "./src/utils" - -#Terrapin::CommandLine.logger = Logger.new(STDOUT) +require 'thor' +require 'fileutils' +require 'logger' +require 'colorize' +require './src/methods' +require './src/utils' +# Terrapin::CommandLine.logger = Logger.new(STDOUT) module VBiosFinder @@wd + class CLI < Thor desc 'extract '.colorize(:blue), 'attempts to extract an embedded vbios from a bios update' - def extract file=nil + + def extract(file = nil) wd = "#{Dir.pwd}/tmp-vbiosfinder" if file.nil? - puts "no file specified".colorize(:red) + puts 'no file specified'.colorize(:red) return end if File.directory? wd @@ -23,17 +24,18 @@ def extract file=nil end FileUtils.mkdir_p wd Kernel.at_exit do - puts "Cleaning up garbage".colorize(:blue) + puts 'Cleaning up garbage'.colorize(:blue) FileUtils.remove_entry_secure wd end @@wd = wd Dir.chdir wd - puts "output will be stored in '#{wd}'".colorize(":blue") - Utils::installed?("ruby") # "bugfix" - Utils::get_new_files # "bugfix" #2 + puts "output will be stored in '#{wd}'".colorize(':blue') + Utils.installed?('ruby') # "bugfix" + Utils.get_new_files # "bugfix" #2 FileUtils.cp(file, wd) + puts 'copying BIOS file to the work directory'.colorize(':blue') puts - Main::run Utils::get_new_files.first + Main.run Utils.get_new_files.first end end end diff --git a/src/extract-7z.rb b/src/extract-7z.rb index f33a9c4..51f6fc3 100644 --- a/src/extract-7z.rb +++ b/src/extract-7z.rb @@ -1,26 +1,23 @@ -require "terrapin" +require 'terrapin' module VBiosFinder class Extract - def self.p7zip file - begin - line = Terrapin::CommandLine.new("7z", "x :file") - line.run(file: file) - rescue Terrapin::ExitStatusError => e - puts e.message - return - end + def self.p7zip(file) + line = Terrapin::CommandLine.new('7z', 'x :file') + line.run(file: file) + rescue Terrapin::ExitStatusError => e + puts e.message + nil end end + class Test - def self.p7zip file - begin - line = Terrapin::CommandLine.new("7z", "l :file | grep 'Type = 7z'") - line.run(file: file) - true - rescue Terrapin::ExitStatusError => e - false - end + def self.p7zip(file) + line = Terrapin::CommandLine.new('7z', "l :file | grep 'Type = 7z'") + line.run(file: file) + true + rescue Terrapin::ExitStatusError => e + false end end -end \ No newline at end of file +end diff --git a/src/extract-innosetup.rb b/src/extract-innosetup.rb index 0f8613b..128acf5 100644 --- a/src/extract-innosetup.rb +++ b/src/extract-innosetup.rb @@ -1,26 +1,23 @@ -require "terrapin" +require 'terrapin' module VBiosFinder class Extract - def self.innosetup file - begin - line = Terrapin::CommandLine.new("innoextract", ":file") - puts line.run(file: file) - rescue Terrapin::ExitStatusError => e - puts e.message - return - end + def self.innosetup(file) + line = Terrapin::CommandLine.new('innoextract', ':file') + puts line.run(file: file) + rescue Terrapin::ExitStatusError => e + puts e.message + nil end end + class Test - def self.innosetup file - begin - line = Terrapin::CommandLine.new("innoextract", "-t :file") - line.run(file: file) - true - rescue Terrapin::ExitStatusError => e - false - end + def self.innosetup(file) + line = Terrapin::CommandLine.new('innoextract', '-t :file') + line.run(file: file) + true + rescue Terrapin::ExitStatusError => e + false end end -end \ No newline at end of file +end diff --git a/src/extract-polyglot.rb b/src/extract-polyglot.rb index b837eff..5f27e7c 100644 --- a/src/extract-polyglot.rb +++ b/src/extract-polyglot.rb @@ -1,25 +1,26 @@ module VBiosFinder class Extract - def self.polyglot file - File.open file, "r:ASCII-8BIT" do |data| - regex = /(.{4})\xAA\xEE\xAA\x76\x1B\xEC\xBB\x20\xF1\xE6\x51(.{1})/n + def self.polyglot(file) + File.open file, 'r:ASCII-8BIT' do |data| + regex = /(.{4})\xAA\xEE\xAA\x76\x1B\xEC\xBB\x20\xF1\xE6\x51(.)/n input = data.read matches = regex.match input - payload_size = matches.captures.first.unpack('V').first + payload_size = matches.captures.first.unpack1('V') payload_offset = matches.offset(2).last data.seek payload_offset - File.open "#{file}-polyglot", "w:ASCII-8BIT" do |outdata| + File.open "#{file}-polyglot", 'w:ASCII-8BIT' do |outdata| outdata.write data.read end end end end + class Test - def self.polyglot file - File.open file, "r:ASCII-8BIT" do |data| - regex = /(.{4})\xAA\xEE\xAA\x76\x1B\xEC\xBB\x20\xF1\xE6\x51.{1}/n - return !(regex.match(data.read).nil?) + def self.polyglot(file) + File.open file, 'r:ASCII-8BIT' do |data| + regex = /(.{4})\xAA\xEE\xAA\x76\x1B\xEC\xBB\x20\xF1\xE6\x51./n + return !regex.match(data.read).nil? end end end -end \ No newline at end of file +end diff --git a/src/extract-uefi.rb b/src/extract-uefi.rb index 04e68cd..6fff14c 100644 --- a/src/extract-uefi.rb +++ b/src/extract-uefi.rb @@ -1,27 +1,24 @@ -require "terrapin" +require 'terrapin' module VBiosFinder class Extract - def self.uefi file - begin - line = Terrapin::CommandLine.new("UEFIExtract", ":file all") - line.run(file: file) - rescue Terrapin::ExitStatusError => e - # TODO: fix Test::uefi before uncommenting this - puts e.message - return - end + def self.uefi(file) + line = Terrapin::CommandLine.new('uefiextract', ':file all') + line.run(file: file) + rescue Terrapin::ExitStatusError => e + # TODO: fix Test::uefi before uncommenting this + puts e.message + nil end end + class Test - def self.uefi file - begin - line = Terrapin::CommandLine.new("UEFIExtract", ":file report") - line.run(file: file) - true - rescue Terrapin::ExitStatusError => e - false - end + def self.uefi(file) + line = Terrapin::CommandLine.new('uefiextract', ':file report') + line.run(file: file) + true + rescue Terrapin::ExitStatusError => e + false end end -end \ No newline at end of file +end diff --git a/src/extract-upx.rb b/src/extract-upx.rb index 6e53f9c..58d5269 100644 --- a/src/extract-upx.rb +++ b/src/extract-upx.rb @@ -1,26 +1,23 @@ -require "terrapin" +require 'terrapin' module VBiosFinder class Extract - def self.upx file - begin - line = Terrapin::CommandLine.new("upx", "-d :file -o :outfile") - line.run(file: file, outfile: "upx-#{file}") - rescue Terrapin::ExitStatusError => e - puts e.message - return - end + def self.upx(file) + line = Terrapin::CommandLine.new('upx', '-d :file -o :outfile') + line.run(file: file, outfile: "upx-#{File.basename(file)}") + rescue Terrapin::ExitStatusError => e + puts e.message + nil end end + class Test - def self.upx file - begin - line = Terrapin::CommandLine.new("upx", "-t :file") - line.run(file: file) - true - rescue Terrapin::ExitStatusError => e - false - end + def self.upx(file) + line = Terrapin::CommandLine.new('upx', '-t :file') + line.run(file: file) + true + rescue Terrapin::ExitStatusError => e + false end end -end \ No newline at end of file +end diff --git a/src/extract-zlib.rb b/src/extract-zlib.rb index 53ae9d1..19be56b 100644 --- a/src/extract-zlib.rb +++ b/src/extract-zlib.rb @@ -1,27 +1,28 @@ -require "zlib" +require 'zlib' module VBiosFinder class Extract - def self.zlib file + def self.zlib(file) target = "#{file}-zlib" begin - File.open file, "r:ASCII-8BIT" do |data| - File.open target, "w:ASCII-8BIT" do |outdata| + File.open file, 'r:ASCII-8BIT' do |data| + File.open target, 'w:ASCII-8BIT' do |outdata| outdata.write Zlib::Inflate.inflate(data.read) end end rescue Zlib::DataError - puts "wrong guess :(".colorize(:red) + puts 'wrong guess :('.colorize(:red) FileUtils.rm target end end end + class Test - def self.zlib file - File.open file, "r:ASCII-8BIT" do |data| + def self.zlib(file) + File.open file, 'r:ASCII-8BIT' do |data| regex = /^\x78\x9C/n - return !(regex.match(data.read).nil?) + return !regex.match(data.read).nil? end end end -end \ No newline at end of file +end diff --git a/src/extraction.rb b/src/extraction.rb index 5dcb5a8..27cf71c 100644 --- a/src/extraction.rb +++ b/src/extraction.rb @@ -1,10 +1,10 @@ -require "colorize" -require "./src/utils" -require "./src/methods" +require 'colorize' +require './src/utils' +require './src/methods' module VBiosFinder class Extraction - def self.attempt method_s, requires, reason, file + def self.attempt(method_s, requires, reason, file) if Test.method(method_s).call(file) puts "found #{requires} archive".colorize(:green) Extract.method(method_s).call(file) @@ -13,4 +13,4 @@ def self.attempt method_s, requires, reason, file end end end -end \ No newline at end of file +end diff --git a/src/methods.rb b/src/methods.rb index a53e6b4..e6808c1 100644 --- a/src/methods.rb +++ b/src/methods.rb @@ -1,72 +1,76 @@ -require "terrapin" -require "find" -require "colorize" -require "./src/extraction" -require "./src/extract-innosetup" -require "./src/extract-upx" -require "./src/extract-uefi" -require "./src/extract-7z" -require "./src/extract-polyglot" -require "./src/extract-zlib" +require 'terrapin' +require 'find' +require 'colorize' +require './src/extraction' +require './src/extract-innosetup' +require './src/extract-upx' +require './src/extract-uefi' +require './src/extract-7z' +require './src/extract-polyglot' +require './src/extract-zlib' require 'digest/md5' -hashm = Hash.new +hashm = {} module VBiosFinder class Main @extractions = [] - @extractions << [:polyglot, "polyglot", "builtin module for polyglot files"] - @extractions << [:zlib, "zlib", "builtin module for zlib data"] - @extractions << [:innosetup, "innoextract", "required for Inno Installers"] - @extractions << [:upx, "upx", "required for UPX executables"] - @extractions << [:p7zip, "7z", "required for 7z (self-extracting) archives"] + @extractions << [:polyglot, 'polyglot', 'builtin module for polyglot files'] + @extractions << [:zlib, 'zlib', 'builtin module for zlib data'] + @extractions << [:innosetup, 'innoextract', 'required for Inno Installers'] + @extractions << [:upx, 'upx', 'required for UPX executables'] + @extractions << [:p7zip, '7z', 'required for 7z (self-extracting) archives'] - def self.extract file + def self.extract(file) puts "trying to extract #{file}" # Attempt all known extraction methods - @extractions.each{|e| Extraction::attempt(*e, file)} + @extractions.each { |e| Extraction.attempt(*e, file) } end - def self.run file - @extractions.select! do |sym, requires, reason, arg| - reason.start_with?("builtin") || Utils::installed?(requires, reason) + def self.run(file) + @extractions.select! do |_sym, requires, reason, _arg| + reason.start_with?('builtin') || Utils.installed?(requires, reason) end - files = Utils::get_new_files + files = Utils.get_new_files files << file while files.size > 0 files.each do |e| extract e end - files = Utils::get_new_files + files = Utils.get_new_files end - puts "extracting uefi data".colorize(:blue) - Find.find(".").reject{|e| File.directory? e}.each do |e| + puts 'extracting uefi data'.colorize(:blue) + Find.find('.').reject { |e| File.directory? e }.each do |e| puts "trying to extract #{e}" - Extraction::attempt(:uefi, "UEFIExtract", "required for UEFI images", e) + Extraction.attempt(:uefi, 'uefiextract', 'required for UEFI images', e) end outpath = "#{Dir.pwd}/../output" FileUtils.mkdir_p outpath FileUtils.cp file, "#{outpath}/bios_#{File.basename file}" - puts "filtering for modules...".colorize(:blue) - uefibins = Find.find(".").reject{|e| File.directory? e}.select{|e| e.end_with? ".bin"} + puts 'filtering for modules...'.colorize(:blue) + uefibins = Find.find('.').reject { |e| File.directory? e }.select { |e| e.end_with? '.bin' } puts "got #{uefibins.length} modules".colorize(:blue) - puts "finding vbios".colorize(:blue) - line = Terrapin::CommandLine.new("file", "-b :file") - modules = uefibins.select{|e| line.run(file: e).include? "Video"} + puts 'finding vbios'.colorize(:blue) + line = Terrapin::CommandLine.new('file', '-b :file') + modules = uefibins.select { |e| line.run(file: e).include? 'Video' } if modules.length > 0 puts "#{modules.length} possible candidates".colorize(:green) - if Utils::installed?("rom-parser", "required for proper rom naming & higher accuracy") + if Utils.installed?('rom-parser', 'required for proper rom naming & higher accuracy') modules.each do |mod| - rom_parser = Terrapin::CommandLine.new("rom-parser", ":file") + rom_parser = Terrapin::CommandLine.new('rom-parser', ':file') begin romdata = rom_parser.run(file: mod) - romdata = romdata.split("\n")[1].split(", ").map{|e| e.split(": ")}.to_h rescue nil + romdata = begin + romdata.split("\n")[1].split(', ').map { |e| e.split(': ') }.to_h + rescue StandardError + nil + end unless romdata.nil? || romdata['vendor'].nil? || romdata['device'].nil? puts "Found VBIOS for device #{romdata['vendor']}:#{romdata['device']}!".colorize(:green) new_filename = "vbios_#{romdata['vendor']}_#{romdata['device']}.rom" - new_filename =check_cpy(new_filename,romdata) + new_filename = check_cpy(new_filename, romdata) FileUtils.cp(mod, "#{outpath}/#{new_filename}") end rescue Terrapin::ExitStatusError => e @@ -81,31 +85,33 @@ def self.run file end puts "Job done. Extracted files can be found in #{outpath}".colorize(:green) else - puts "no candidates found :(".colorize(:red) + puts 'no candidates found :('.colorize(:red) if uefibins.length > 0 - puts "input contains uefi data but no vbios could be found".colorize(:yellow) - puts "the vbios might not be baked into the input!".colorize(:yellow) + puts 'input contains uefi data but no vbios could be found'.colorize(:yellow) + puts 'the vbios might not be baked into the input!'.colorize(:yellow) end end end end end - - -define_method (:check_cpy) do |new_filename,romdata| +define_method(:check_cpy) do |new_filename, romdata| count = 0 - Dir.glob('**/*',File::FNM_DOTMATCH).each do |f| - if File.directory?(f) - next - end + Dir.glob('**/*', File::FNM_DOTMATCH).each do |f| + next if File.directory?(f) + key = Digest::MD5.hexdigest(IO.read(f)).to_sym - if hashm.has_key?(key) then hashm[key].push(f) else hashm[key] = [f] end + if hashm.has_key?(key) + hashm[key].push(f) + else + hashm[key] = [f] + end end hashm.each_value do |a| next if a.length == 1 - count+= 1 + + count += 1 new_filename = "vbios_#{romdata['vendor']}_#{romdata['device']}_#{count}.rom" return new_filename diff --git a/src/utils.rb b/src/utils.rb index f361697..88ce5e3 100644 --- a/src/utils.rb +++ b/src/utils.rb @@ -1,17 +1,18 @@ -require "terrapin" -require "mkmf" -require "find" +require 'terrapin' +require 'mkmf' +require 'find' module VBiosFinder class Utils @@current_files = [] def self.get_new_files - current_files = Find.find(".").reject{|e| File.directory? e} + current_files = Find.find('.').reject { |e| File.directory? e } result = current_files - @@current_files @@current_files = current_files - return result + result end - def self.installed? program, reason="optional" + + def self.installed?(program, reason = 'optional') if find_executable(program).nil? puts "Install '#{program}' on your system (#{reason})".colorize(:red) false