Land #5067, @wchen-r7's standalone jsobfu tool
commit
b42e0298fe
|
@ -0,0 +1,79 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
load Metasploit::Framework.root.join('tools/jsobfu.rb').to_path
|
||||||
|
|
||||||
|
require 'stringio'
|
||||||
|
|
||||||
|
describe Jsobfu do
|
||||||
|
|
||||||
|
let(:fname) {
|
||||||
|
'test.js'
|
||||||
|
}
|
||||||
|
|
||||||
|
let(:js) {
|
||||||
|
%Q|alert("test");|
|
||||||
|
}
|
||||||
|
|
||||||
|
describe Jsobfu::Driver do
|
||||||
|
|
||||||
|
subject do
|
||||||
|
Jsobfu::Driver.new
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#run' do
|
||||||
|
let(:default_opts) {
|
||||||
|
{ :input => fname, :iteration => 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
allow(Jsobfu::OptsConsole).to receive(:parse).with(any_args).and_return(default_opts)
|
||||||
|
allow(File).to receive(:open).with(fname, 'rb').and_yield(StringIO.new(js))
|
||||||
|
@out = $stdout
|
||||||
|
$stdout = StringIO.new
|
||||||
|
$stdout.string = ''
|
||||||
|
end
|
||||||
|
|
||||||
|
after(:each) do
|
||||||
|
$stdout = @out
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a javascript file is given' do
|
||||||
|
it 'returns an String' do
|
||||||
|
subject.run
|
||||||
|
expect($stdout.string).to be_a(String)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a non empty String' do
|
||||||
|
subject.run
|
||||||
|
expect($stdout.string).not_to be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns an String different than the original' do
|
||||||
|
subject.run
|
||||||
|
expect($stdout.string).not_to eq(js)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe Jsobfu::OptsConsole do
|
||||||
|
subject do
|
||||||
|
Jsobfu::OptsConsole
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when no options are given' do
|
||||||
|
it 'raises OptionParser::MissingArgument' do
|
||||||
|
expect{subject.parse([])}.to raise_error(OptionParser::MissingArgument)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when -t isn\'t a number' do
|
||||||
|
it 'raises OptionParser::MissingArgument' do
|
||||||
|
args = "-i #{fname} -t NaN".split
|
||||||
|
expect{subject.parse(args)}.to raise_error(OptionParser::InvalidOption)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,106 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
msfbase = __FILE__
|
||||||
|
while File.symlink?(msfbase)
|
||||||
|
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
|
||||||
|
end
|
||||||
|
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', 'lib')))
|
||||||
|
require 'msfenv'
|
||||||
|
require 'rex'
|
||||||
|
require 'msf/core'
|
||||||
|
require 'msf/base'
|
||||||
|
require 'optparse'
|
||||||
|
|
||||||
|
module Jsobfu
|
||||||
|
class OptsConsole
|
||||||
|
def self.parse(args)
|
||||||
|
options = {}
|
||||||
|
parser = OptionParser.new do |opt|
|
||||||
|
opt.banner = "Usage: #{__FILE__} [options]"
|
||||||
|
opt.separator ''
|
||||||
|
opt.separator 'Specific options:'
|
||||||
|
|
||||||
|
opt.on('-t', '--iteration <Fixnum>', "Number of times to obfuscate the JavaScript") do |v|
|
||||||
|
options[:iteration] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
opt.on('-i', '--input <String>', "The JavaScript file you want to obfuscate (default=1)") do |v|
|
||||||
|
options[:input] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
opt.on('-o', '--output <String>', "Save the obfuscated file as") do |v|
|
||||||
|
options[:output] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
opt.on_tail('-h', '--help', 'Show this message') do
|
||||||
|
$stdout.puts opt
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.parse!(args)
|
||||||
|
|
||||||
|
if options.empty?
|
||||||
|
raise OptionParser::MissingArgument, 'No options set, try -h for usage'
|
||||||
|
elsif options[:iteration] && options[:iteration] !~ /^\d+$/
|
||||||
|
raise OptionParser::InvalidOption, "#{options[:format]} is not a number"
|
||||||
|
elsif !::File.exists?(options[:input].to_s)
|
||||||
|
raise OptionParser::InvalidOption, "Cannot find: #{options[:input]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
options[:iteration] = 1 unless options[:iteration]
|
||||||
|
|
||||||
|
options
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Driver
|
||||||
|
def initialize
|
||||||
|
begin
|
||||||
|
@opts = OptsConsole.parse(ARGV)
|
||||||
|
rescue OptionParser::ParseError => e
|
||||||
|
$stderr.puts "[x] #{e.message}"
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
original_js = read_js(@opts[:input])
|
||||||
|
js = ::Rex::Exploitation::JSObfu.new(original_js)
|
||||||
|
js.obfuscate(:iterations=>@opts[:iteration].to_i)
|
||||||
|
js = js.to_s
|
||||||
|
|
||||||
|
output_stream = $stdout
|
||||||
|
output_stream.binmode
|
||||||
|
output_stream.write js
|
||||||
|
$stderr.puts
|
||||||
|
|
||||||
|
if @opts[:output]
|
||||||
|
save_as(js, @opts[:output])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def read_js(path)
|
||||||
|
js = ::File.open(path, 'rb') { |f| js = f.read }
|
||||||
|
js
|
||||||
|
end
|
||||||
|
|
||||||
|
def save_as(js, outfile)
|
||||||
|
File.open(outfile, 'wb') do |f|
|
||||||
|
f.write(js)
|
||||||
|
end
|
||||||
|
|
||||||
|
$stderr.puts
|
||||||
|
$stderr.puts "File saved as: #{outfile}"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if __FILE__ == $PROGRAM_NAME
|
||||||
|
driver = Jsobfu::Driver.new
|
||||||
|
driver.run
|
||||||
|
end
|
Loading…
Reference in New Issue