Skip to content

Commit ea89d34

Browse files
committed
Add updater-polyglot extraction & zlib inflation; Switch from UEFIDump to UEFIExtract; Decrease verbosity;
1 parent 3edc877 commit ea89d34

File tree

8 files changed

+124
-57
lines changed

8 files changed

+124
-57
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Laptops with NVIDIA Optimus graphics often have the dGPU VBIOS integrated in the
66
## Dependencies
77
- Ruby
88
- bundler **(a ruby gem)**
9-
- [UEFIDump](https://github.com/LongSoft/UEFITool) **(note: UEFIDump can be found in the branch `new_engine`)**
9+
- [UEFIExtract](https://github.com/LongSoft/UEFITool) **(note: UEFIExtract can be found in the branch `new_engine`)**
1010
- [rom-parser](https://github.com/awilliam/rom-parser)
1111
- p7zip **(optional)**
1212
- [innoextract](https://github.com/dscharrer/innoextract) **(optional)**

src/cli.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ def extract file=nil
1717
puts "no file specified".colorize(:red)
1818
return
1919
end
20+
if File.directory? wd
21+
puts "dirty work directory! remove #{wd}".colorize(:red)
22+
exit 1
23+
end
2024
FileUtils.mkdir_p wd
2125
Kernel.at_exit do
2226
puts "Cleaning up garbage".colorize(:blue)

src/extract-polyglot.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module VBiosFinder
2+
class Extract
3+
def self.polyglot file
4+
File.open file, "r:ASCII-8BIT" do |data|
5+
regex = /(.{4})\xAA\xEE\xAA\x76\x1B\xEC\xBB\x20\xF1\xE6\x51(.{1})/n
6+
input = data.read
7+
matches = regex.match input
8+
payload_size = matches.captures.first.unpack('V').first
9+
payload_offset = matches.offset(2).last
10+
data.seek payload_offset
11+
File.open "#{file}-polyglot", "w:ASCII-8BIT" do |outdata|
12+
outdata.write data.read
13+
end
14+
end
15+
end
16+
end
17+
class Test
18+
def self.polyglot file
19+
File.open file, "r:ASCII-8BIT" do |data|
20+
regex = /(.{4})\xAA\xEE\xAA\x76\x1B\xEC\xBB\x20\xF1\xE6\x51.{1}/n
21+
return !(regex.match(data.read).nil?)
22+
end
23+
end
24+
end
25+
end

src/extract-uefi.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ module VBiosFinder
44
class Extract
55
def self.uefi file
66
begin
7-
line = Cocaine::CommandLine.new("UEFIDump", ":file")
8-
puts line.run(file: file)
7+
line = Cocaine::CommandLine.new("UEFIExtract", ":file all")
8+
line.run(file: file)
99
rescue Cocaine::ExitStatusError => e
1010
# TODO: fix Test::uefi before uncommenting this
11-
# puts e.message
11+
puts e.message
1212
return
1313
end
1414
end
1515
end
1616
class Test
1717
def self.uefi file
1818
begin
19-
line = Cocaine::CommandLine.new("UEFIDump", ":file")
20-
puts line.run(file: file)
19+
line = Cocaine::CommandLine.new("UEFIExtract", ":file report")
20+
line.run(file: file)
2121
true
2222
rescue Cocaine::ExitStatusError => e
2323
false

src/extract-zlib.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
require "zlib"
2+
3+
module VBiosFinder
4+
class Extract
5+
def self.zlib file
6+
File.open file, "r:ASCII-8BIT" do |data|
7+
File.open "#{file}-zlib", "w:ASCII-8BIT" do |outdata|
8+
outdata.write Zlib::Inflate.inflate(data.read)
9+
end
10+
end
11+
end
12+
end
13+
class Test
14+
def self.zlib file
15+
File.open file, "r:ASCII-8BIT" do |data|
16+
regex = /^\x78\x9C/n
17+
return !(regex.match(data.read).nil?)
18+
end
19+
end
20+
end
21+
end

src/extraction.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
module VBiosFinder
66
class Extraction
77
def self.attempt method_s, requires, reason, file
8-
if Utils::installed?(requires, reason) && Test.method(method_s).call(file)
8+
if Test.method(method_s).call(file)
99
puts "found #{requires} archive".colorize(:green)
1010
Extract.method(method_s).call(file)
1111
else
12-
puts "not extractable with #{requires}".colorize(:red)
12+
#puts "not extractable with #{requires}".colorize(:red)
1313
end
1414
end
1515
end

src/methods.rb

Lines changed: 65 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,66 +6,83 @@
66
require "./src/extract-upx"
77
require "./src/extract-uefi"
88
require "./src/extract-7z"
9+
require "./src/extract-polyglot"
10+
require "./src/extract-zlib"
911

1012
module VBiosFinder
1113
class Main
12-
def self.run file
13-
puts "trying to extract #{file}"
14+
@extractions = []
15+
@extractions << [:polyglot, "polyglot", "builtin module for polyglot files"]
16+
@extractions << [:zlib, "zlib", "builtin module for zlib data"]
17+
@extractions << [:innosetup, "innoextract", "required for Inno Installers"]
18+
@extractions << [:upx, "upx", "required for UPX executables"]
19+
@extractions << [:p7zip, "7z", "required for 7z (self-extracting) archives"]
1420

21+
def self.extract file
22+
puts "trying to extract #{file}"
1523
# Attempt all known extraction methods
16-
extractions = []
17-
extractions << [:innosetup, "innoextract", "required for Inno Installers", file]
18-
extractions << [:upx, "upx", "required for UPX executables", file]
19-
extractions << [:p7zip, "7z", "required for 7z (self-extracting) archives", file]
20-
extractions.each{|e| Extraction::attempt(*e)}
24+
@extractions.each{|e| Extraction::attempt(*e, file)}
25+
end
26+
27+
def self.run file
28+
@extractions.select! do |sym, requires, reason, arg|
29+
reason.start_with?("builtin") || Utils::installed?(requires, reason)
30+
end
31+
32+
files = Utils::get_new_files
33+
files << file
34+
35+
while files.size > 0
36+
files.each do |e|
37+
extract e
38+
end
39+
files = Utils::get_new_files
40+
end
2141

22-
# Try to find an UEFI bios image now
23-
if Utils::installed?("UEFIDump", "required for UEFI images") && Test::uefi(file)
24-
puts "found UEFI image".colorize(:green)
25-
outpath = "#{Dir.pwd}/../output"
26-
FileUtils.mkdir_p outpath
27-
FileUtils.cp file, "#{outpath}/bios_#{File.basename file}"
28-
Extract::uefi file
29-
puts "extracted. filtering modules...".colorize(:blue)
30-
modules = Find.find("#{file}.dump").reject{|e| File.directory? e}.select{|e| e.end_with? ".bin"}
31-
puts "got #{modules.length} modules".colorize(:blue)
32-
puts "finding vbios".colorize(:blue)
33-
line = Cocaine::CommandLine.new("file", "-b :file")
34-
modules = modules.select{|e| line.run(file: e).include? "Video"}
35-
if modules.length > 0
36-
puts "#{modules.length} possible candidates".colorize(:green)
37-
if Utils::installed?("rom-parser", "required for proper rom naming & higher accuracy")
38-
modules.each do |mod|
39-
rom_parser = Cocaine::CommandLine.new("rom-parser", ":file")
40-
begin
41-
romdata = rom_parser.run(file: mod)
42-
romdata = romdata.split("\n")[1].split(", ").map{|e| e.split(": ")}.to_h rescue nil
43-
unless romdata.nil? || romdata['vendor'].nil? || romdata['device'].nil?
44-
puts "Found VBIOS for device #{romdata['vendor']}:#{romdata['device']}!".colorize(:green)
45-
new_filename = "vbios_#{romdata['vendor']}_#{romdata['device']}.rom"
46-
FileUtils.cp(mod, "#{outpath}/#{new_filename}")
47-
end
48-
rescue Cocaine::ExitStatusError => e
49-
puts "can't determine vbios type"
42+
puts "extracting uefi data".colorize(:blue)
43+
Find.find(".").reject{|e| File.directory? e}.each do |e|
44+
puts "trying to extract #{e}"
45+
Extraction::attempt(:uefi, "UEFIExtract", "required for UEFI images", e)
46+
end
47+
48+
outpath = "#{Dir.pwd}/../output"
49+
FileUtils.mkdir_p outpath
50+
FileUtils.cp file, "#{outpath}/bios_#{File.basename file}"
51+
puts "filtering for modules...".colorize(:blue)
52+
uefibins = Find.find(".").reject{|e| File.directory? e}.select{|e| e.end_with? ".bin"}
53+
puts "got #{uefibins.length} modules".colorize(:blue)
54+
puts "finding vbios".colorize(:blue)
55+
line = Cocaine::CommandLine.new("file", "-b :file")
56+
modules = uefibins.select{|e| line.run(file: e).include? "Video"}
57+
if modules.length > 0
58+
puts "#{modules.length} possible candidates".colorize(:green)
59+
if Utils::installed?("rom-parser", "required for proper rom naming & higher accuracy")
60+
modules.each do |mod|
61+
rom_parser = Cocaine::CommandLine.new("rom-parser", ":file")
62+
begin
63+
romdata = rom_parser.run(file: mod)
64+
romdata = romdata.split("\n")[1].split(", ").map{|e| e.split(": ")}.to_h rescue nil
65+
unless romdata.nil? || romdata['vendor'].nil? || romdata['device'].nil?
66+
puts "Found VBIOS for device #{romdata['vendor']}:#{romdata['device']}!".colorize(:green)
67+
new_filename = "vbios_#{romdata['vendor']}_#{romdata['device']}.rom"
68+
FileUtils.cp(mod, "#{outpath}/#{new_filename}")
5069
end
51-
end
52-
else
53-
modules.each do |mod|
54-
FileUtils.cp(mod, outpath)
70+
rescue Cocaine::ExitStatusError => e
71+
puts "can't determine vbios type"
5572
end
5673
end
57-
puts "Job done. Extracted files can be found in #{outpath}".colorize(:green)
5874
else
59-
puts "no candidates found :(".colorize(:red)
75+
modules.each do |mod|
76+
FileUtils.cp(mod, outpath)
77+
end
6078
end
61-
exit 0
79+
puts "Job done. Extracted files can be found in #{outpath}".colorize(:green)
6280
else
63-
puts "not an uefi image"
64-
end
65-
66-
Utils::get_new_files.each do |e|
67-
puts
68-
run e
81+
puts "no candidates found :(".colorize(:red)
82+
if uefibins.length > 0
83+
puts "input contains uefi data but no vbios could be found".colorize(:yellow)
84+
puts "the vbios might not be baked into the input!".colorize(:yellow)
85+
end
6986
end
7087
end
7188
end

src/utils.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def self.get_new_files
1313
end
1414
def self.installed? program, reason="optional"
1515
if find_executable(program).nil?
16-
puts "Install '#{program}' on your system (#{reason})"
16+
puts "Install '#{program}' on your system (#{reason})".colorize(:red)
1717
false
1818
else
1919
true

0 commit comments

Comments
 (0)