Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Commit

Permalink
Open Sourced.
Browse files Browse the repository at this point in the history
  • Loading branch information
postmodern committed Nov 26, 2014
0 parents commit d67b51c
Show file tree
Hide file tree
Showing 58 changed files with 2,855 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .document
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-
ChangeLog.md
LICENSE.txt
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Gemfile.lock
doc/
pkg/
vendor/cache/*.gem
*.eml
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--colour --format documentation
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.9.3
1 change: 1 addition & 0 deletions .yardopts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--markup markdown --title "TackleBox Documentation" --protected
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### 0.1.0 / 2014-06-03

* Initial release:

11 changes: 11 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
source 'https://rubygems.org/'

gemspec

group :development do
gem 'rake'
gem 'rspec', '~> 3.0'

gem 'kramdown'
gem 'yard', '~> 0.8'
end
1 change: 1 addition & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Copyright (c) 2014 Trail of Bits, Inc.
141 changes: 141 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# tacklebox

* [Homepage](https://github.com/trailofbits/tackle_box)
* [Documentation](http://rubydoc.info/gems/tackle_box/frames)

## Description

A phishing toolkit for generating and sending phishing emails.

## Features

* Provides a [Liquid][liquid] + Markdown email template system.
* Provides built-in [liquid] tags for customized emails:
* {TackleBox::Email::Template::Tags::Attachment attachment}
* {TackleBox::Email::Template::Tags::Date date}
* {TackleBox::Email::Template::Tags::Day day}
* {TackleBox::Email::Template::Tags::Link link}
* {TackleBox::Email::Template::Tags::RandomDate random_date}
* {TackleBox::Email::Template::Tags::RandomDay random_day}
* {TackleBox::Email::Template::Tags::RandomGreeting random_greeting}
* {TackleBox::Email::Template::Tags::RandomWeekDay random_week_day}
* {TackleBox::Email::Template::Tags::WeekDay week_day}
* {TackleBox::Email::Template::Tags::Year year}
* Renders dynamic emails based on the recipient.
* Supports targeting specific sub-groups of people within an organization.
* Supports embedding links and/or attachments into emails.
* Supports custom 1x1 tracking pixel URLs.

## API

* {TackleBox::Attachment}
* {TackleBox::Link}
* {TackleBox::Person}
* {TackleBox::Organization}
* {TackleBox::Campaign}
* {TackleBox::Campaign#initialize}
* {TackleBox::Campaign#each_email}

## Examples

require 'tackle_box'

email_template = TackleBox::Email::Template.open('nude_pics.eml')

org = TackleBox::Organization.new(
'Trail of Bits, Inc.',

domain: 'trailofbits.com',
website: 'http://www.trailofbits.com/',
industry: 'Technology'
)
org.person('dan@trailofbits.com', name: 'Dan Guido',
title: 'CEO',
department: 'Management',
location: 'New York, NY')

campaign = TackleBox::Campaign.new(
email_template, org,

link: 'http://www.imdurr.com/gallery/x5ae18.png',
tracking_pixel: 'http://www.imdurr.com/pixel.gif',
account: TackleBox::Person.new(
'nick.d@yelpfortoilets.com',
name: 'Nick Depetrillo',
title: 'CTO'
)
)

sender = TackleBox::Email::Sender.new(
'trailofberts.com' => {
address: 'mail.yelpfortoilets.com',
port: 587,
user_name: 'nick.d',
password: 'test1234',
authentication: :plain,
enable_starttls_auto: true
}
)

campaign.each_email do |email|
puts ">>> Sending email to #{email.to}"
puts email

sender.send(email)
end

### Example Email Template

Date: Tue, 01 Jul 2014 14:21:08 -0700
Message-ID: <53b32644bd0dd_b221112ff0516b4@tank.lab.mail>
Subject: Nude pics!
Mime-Version: 1.0
Content-Type: text/html;
charset=ISO-8895-1
Content-Transfer-Encoding: 7bit

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>test email</title>
</head>
<body text="#000000" bgcolor="#FFFFFF">
Yo {{ to.name }}, checkout these <a href="{% link %}">nudes</a>
of Brian Krebs!
</body>
</html>

## Requirements

* [Ruby] >= 1.9.3
* [activesupport] ~> 3.2
* [shorturl] ~> 1.0
* [liquid] ~> 2.4
* [nokogiri] ~> 1.6
* [chars] ~> 0.2
* [mail] ~> 2.5

## Install

$ bundle install

## Testing

$ rake spec

## Documentation

$ rake yard
$ open ./doc/index.html

## Copyright

Copyright (c) 2014 Trail of Bits, Inc.

[Ruby]: http://www.ruby-lang.org/
[activesupport]: https://github.com/rails/rails/tree/master/activesupport#readme
[shorturl]: https://github.com/robbyrussell/shorturl#readme
[liquid]: http://liquidmarkup.org/
[nokogiri]: http://nokogiri.org/
[chars]: https://github.com/postmodern/chars#readme
[mail]: https://github.com/mikel/mail
32 changes: 32 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# encoding: utf-8

require 'rubygems'

begin
require 'bundler'
rescue LoadError => e
warn e.message
warn "Run `gem install bundler` to install Bundler."
exit -1
end

begin
Bundler.setup(:development)
rescue Bundler::BundlerError => e
warn e.message
warn "Run `bundle install` to install missing gems."
exit e.status_code
end

require 'rake'
require 'bundler/gem_tasks'

require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new

task :test => :spec
task :default => :spec

require 'yard'
YARD::Rake::YardocTask.new
task :doc => :yard
74 changes: 74 additions & 0 deletions bin/edit
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env ruby

require 'bundler/setup'
require 'tackle_box/version'
require 'tackle_box/email/editor'

require 'optparse'

replacements = []
domains = []

from = nil
from_name = nil
dry_run = false

options = OptionParser.new("usage: #{$0} [OPTIONS] EMAIL") do |opts|
opts.on('-R','--replace STRING:SUB','Replaces STRING with SUB') do |arg|
replacements << arg.split(':',2)
end

opts.on('-f','--from [ADDR]','Replaces the From address with ADDR') do |addr|
from = addr || '{{ from.address }}'
end

opts.on('-F','--from-name [NAME]','Replaces the From name') do |name|
from_name = name || '{{ from.name }}'
end

opts.on('-D','--domain OLD:NEW','Replaces the OLD domain with NEW') do |arg|
domains << arg.split(':',2)
end

opts.on('-d','--dry-run','Do not save the edits') do
dry_run = true
end

opts.on('-V','--version','Prints the tacklebox version') do
puts TackleBox::VERSION
exit
end

opts.on('-h','--help','Prints this message') do
puts opts
exit
end
end

options.parse!(ARGV)

unless (path = ARGV.first)
abort "#{$0}: EMAIL argument not specified"
end

editor = TackleBox::Email::Editor.new(path)

# always dequote the email
editor.dequote

editor.replace_to
editor.replace_to_name
editor.replace_from(from) if from
editor.replace_from_name(from_name) if from_name

domains.each do |(old,new)|
editor.replace_domain(old,new)
end

replacements.each do |(str,sub)|
editor.replace(str,sub)
end

unless dry_run then editor.save
else puts editor
end
6 changes: 6 additions & 0 deletions lib/tackle_box.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require 'tackle_box/person'
require 'tackle_box/organization'
require 'tackle_box/attachment'
require 'tackle_box/link'
require 'tackle_box/campaign'
require 'tackle_box/version'
96 changes: 96 additions & 0 deletions lib/tackle_box/attachment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
module TackleBox
class Attachment

# The path to the file to attach
attr_reader :path

# The desired name of the attachment
attr_reader :name

# The contents for the attachment
attr_reader :content

# The encoding of the attachment
attr_reader :encoding

# The password for the attachment
attr_reader :password

#
# Initializes the attachment.
#
# @param [Hash] options
# Additional options.
#
# @option options [String] :name
# The desired name for the attachment.
# Defaults to the basename of the path.
#
# @option options [String] :content
# The optional contents for the attachment.
# Defaults to the contents of the file.
#
# @option options [String] :encoding
# The encoding of the attachment (ex: `zip`, `7z`, `rar`).
# Defaults to the extension of the attachment name.
#
# @option options [String] :password
# The password for the attachment.
#
# @raise [ArgumentError]
# Either `:path` or `:content` must be specified, or `:name`
#
# @example Use an existing file:
# Attachment.new(path: 'path/to/nudes.exe')
#
# @example Use an existing file but with a different name:
# Attachment.new(path: 'path/to/nudes.exe', name: 'nudes.jpg')
#
# @example Specify a custom name and contents:
# Attachment.new(name: 'nudes.jpg', content: data)
#
def initialize(options={})
unless (options[:path] || options[:content])
raise(ArgumentError,"must specify :path or :content")
end

@path = options[:path]
@name = options.fetch(:name) do
unless @path
raise(ArgumentError,":path or :name are required")
end

File.basename(@path)
end

@content = options.fetch(:content) do
File.binread(@path)
end

@encoding = options.fetch(:encoding) do
File.extname(@name)[1..-1]
end

@password = options[:password]
end

#
# Converts the attachment into a liquid hash.
#
# @return [Hash{String => String,nil}]
# The liquid hash containing:
#
# * `name`
# * `encoding`
# * `password`
#
def to_liquid
{
'name' => @name,
'encoding' => @encoding,
'password' => @password
}
end

end
end
Loading

0 comments on commit d67b51c

Please sign in to comment.