class LibSignature

metasm dasm plugin: allow loading library signature files (see samples/generate_libsigs.rb)

Attributes

giantregex[RW]
siglenmax[RW]
sigs[RW]

Public Class Methods

new(file) click to toggle source

load signatures from a signature file

# File samples/dasm-plugins/match_libsigs.rb, line 12
def initialize(file)
        # hash symbolname => signature
        @sigs = {}

        # populate sigs
        symname = nil
        sig = ''
        File.read(file).each_line { |l|
                case l
                when /^ /
                        sig << l.strip
                else
                        @sigs[symname] = sig
                        symname = l.strip
                        sig = ''
                end
        }
        @sigs[symname] = sig
        @sigs.delete nil
        @siglenmax = @sigs.values.map { |v| v.length }.max

        # compile a giant regex from the signatures
        re = @sigs.values.uniq.map { |sigh|
                sigh.gsub(/../) { |b| b == '..' ? '.' : ('\x' + b) }
        }.join('|')

        # 'n' is a magic flag to allow high bytes in the regex (ruby1.9 + utfail)
        @giantregex = Regexp.new re, Regexp::MULTILINE, 'n'
end

Public Instance Methods

match(str) { |chunkoff| ... } click to toggle source

matches the signatures against a big raw string yields offset, symname for each match returns nr of matches found

# File samples/dasm-plugins/match_libsigs.rb, line 68
def match(str)
        chunksz = 1 << 20

        chunkoff = 0
        count = 0
        while chunkoff < str.length
                chunk = str[chunkoff, chunksz+@siglenmax]
                count += match_chunk(chunk) { |o, sym| yield chunkoff+o, sym if o < chunksz }
                chunkoff += chunksz
        end
        count
end
match_chunk(str) { |off, sym| ... } click to toggle source

matches the signatures against a raw string yields offset, symname for each match returns nr of matches found

# File samples/dasm-plugins/match_libsigs.rb, line 52
def match_chunk(str)
        count = 0
        off = 0
        while o = (str[off..-1] =~ @giantregex)
                count += 1
                off += o
                sym = matched_findsym(str, off)
                yield off, sym
                off += 1
        end
        count
end
matched_findsym(str, off) click to toggle source

we found a match on str at off, identify the specific symbol that matched on conflict, only return the first match

# File samples/dasm-plugins/match_libsigs.rb, line 44
def matched_findsym(str, off)
        str = str[off, @siglenmax].unpack('H*').first
        @sigs.find { |sym, sig| str =~ /^#{sig}/i }[0]
end