Class: PEdump::Comparer
Overview
comparing 2 binaries
Constant Summary collapse
- METHODS =
[:sections, :data_dirs, :imports, :resources, :pe_hdr]
Instance Attribute Summary collapse
-
#ignored_data_dirs ⇒ Object
Returns the value of attribute ignored_data_dirs.
-
#ignored_sections ⇒ Object
Returns the value of attribute ignored_sections.
-
#verbose ⇒ Object
Returns the value of attribute verbose.
Class Method Summary collapse
-
._cmp(ldr1, ldr2) ⇒ Object
each arg is a PEdump::Loader.
-
.cmp(*args) ⇒ Object
arguments can be: a) filenames b) IO instances c) PEdump::Loader instances.
- .cmp_ios(*ios) ⇒ Object
Instance Method Summary collapse
- #cmp_data_dirs ⇒ Object
- #cmp_imports ⇒ Object
- #cmp_pe_hdr ⇒ Object
- #cmp_resources ⇒ Object
- #cmp_sections ⇒ Object
- #diff ⇒ Object
- #equal? ⇒ Boolean
-
#initialize(ldr1, ldr2) ⇒ Comparer
constructor
A new instance of Comparer.
Constructor Details
#initialize(ldr1, ldr2) ⇒ Comparer
Returns a new instance of Comparer.
14 15 16 17 18 |
# File 'lib/pedump/comparer.rb', line 14 def initialize ldr1, ldr2 @ldr1,@ldr2 = ldr1,ldr2 @ignored_data_dirs = [] @ignored_sections = [] end |
Instance Attribute Details
#ignored_data_dirs ⇒ Object
Returns the value of attribute ignored_data_dirs.
10 11 12 |
# File 'lib/pedump/comparer.rb', line 10 def ignored_data_dirs @ignored_data_dirs end |
#ignored_sections ⇒ Object
Returns the value of attribute ignored_sections.
10 11 12 |
# File 'lib/pedump/comparer.rb', line 10 def ignored_sections @ignored_sections end |
#verbose ⇒ Object
Returns the value of attribute verbose.
9 10 11 |
# File 'lib/pedump/comparer.rb', line 9 def verbose @verbose end |
Class Method Details
._cmp(ldr1, ldr2) ⇒ Object
each arg is a PEdump::Loader
126 127 128 |
# File 'lib/pedump/comparer.rb', line 126 def _cmp ldr1, ldr2 new(ldr1, ldr2).equal? end |
.cmp(*args) ⇒ Object
arguments can be:
a) filenames
b) IO instances
c) PEdump::Loader instances
113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/pedump/comparer.rb', line 113 def cmp *args handles = [] if args.all?{|x| x.is_a?(String)} handles = args.map{|x| File.open(x,"rb")} _cmp(*handles.map{|h| PEdump::Loader.new(h)}) else _cmp(*args) end ensure handles.each(&:close) end |
.cmp_ios(*ios) ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/pedump/comparer.rb', line 130 def cmp_ios *ios ndiff = 0 while !ios.any?(&:eof) bytes = ios.map(&:readbyte) if bytes.uniq.size > 1 ndiff += 1 printf ("\t%08x:"+" %02x"*ios.size).yellow+"\n", ios[0].pos-1, *bytes if ndiff >= 5 puts "\t...".yellow break end end end puts if ndiff > 0 end |
Instance Method Details
#cmp_data_dirs ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/pedump/comparer.rb', line 68 def cmp_data_dirs r = true @ldr1.pe.ioh.DataDirectory.each_with_index do |d1,idx| break if idx == 15 d2 = @ldr2.pe.ioh.DataDirectory[idx] case idx when PEdump::IMAGE_DATA_DIRECTORY::BASERELOC # total 8-byte size relocs == no relocs at all next if [d1.va, d2.va].min == 0 && [d1.size, d2.size].max == 8 end next if @ignored_data_dirs.include?(idx) if d1.va != d2.va && d1.size != d2.size r = false printf "[!] data_dir: %-12s: SIZE & VA: %6x %6x | %6x %6x\n".red, d1.type, d1.va, d1.size, d2.va, d2.size elsif d1.va != d2.va r = false printf "[!] data_dir: %-12s: VA : %x != %x\n".red, d1.type, d1.va, d2.va elsif d1.size != d2.size r = false printf "[!] data_dir: %-12s: SIZE : %x != %x\n".red, d1.type, d1.size, d2.size end end r end |
#cmp_imports ⇒ Object
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/pedump/comparer.rb', line 97 def cmp_imports @ldr1.pedump.imports.each_with_index do |iid1,idx| iid2 = @ldr2.pedump.imports[idx] if iid1 != iid2 puts "[!] diff imports".red return false end end true end |
#cmp_pe_hdr ⇒ Object
28 29 30 31 |
# File 'lib/pedump/comparer.rb', line 28 def cmp_pe_hdr @ldr1.pe.ioh.AddressOfEntryPoint == @ldr2.pe.ioh.AddressOfEntryPoint && @ldr1.pe.ioh.ImageBase == @ldr2.pe.ioh.ImageBase end |
#cmp_resources ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/pedump/comparer.rb', line 33 def cmp_resources PEdump.quiet do #@ldr1.pedump.resources == @ldr2.pedump.resources @ldr1.pedump.resources.each_with_index do |r1,idx| r2 = @ldr2.pedump.resources[idx] if (r1.to_a - [r1.file_offset]) != (r2.to_a - [r2.file_offset]) p r1 p r2 return false end end end true end |
#cmp_sections ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/pedump/comparer.rb', line 48 def cmp_sections r = true @ldr1.sections.each_with_index do |s1,idx| next if @ignored_sections.include?(s1.name) s2 = @ldr2.sections[idx] if !s2 r = false printf "[!] extra section %-12s in %s\n".red, s1.name.inspect, f1 elsif s1.data == s2.data printf "[.] section: %s == %s\n".green, s1.name, s2.name if @verbose else r = false printf "[!] section: %s != %s\n".red, s1.name, s2.name self.class.cmp_ios *[s1,s2].map{ |section| StringIO.new(section.data) } end end r end |
#diff ⇒ Object
24 25 26 |
# File 'lib/pedump/comparer.rb', line 24 def diff METHODS.map{ |m| send("cmp_#{m}") ? nil : m }.compact end |
#equal? ⇒ Boolean
20 21 22 |
# File 'lib/pedump/comparer.rb', line 20 def equal? METHODS.map{ |m| send("cmp_#{m}") }.uniq == [true] end |