├── .gitignore
├── .travis.yml
├── Common
├── SimplyEmail.ini
├── TaskController.py
└── __init__.py
├── Helpers
├── HtmlBootStrapTheme.py
├── Parser.py
├── __init__.py
└── helpers.py
├── License
├── LICENSE-BootStrap-Twitter
├── LICENSE-SimplyEmail
├── LICENSE-Veil
└── LICENSE-theHarvester
├── Modules
├── AskSearch.py
├── CanaryBinSearch.py
├── EmailHunter.py
├── FlickrSearch.py
├── GitHubCodeSearch.py
├── GitHubGistSearch.py
├── GoogleSearch.py
├── HtmlScrape.py
├── OnionStagram.py
├── SearchPGP.py
├── WhoisAPISearch.py
├── Whoisolgy.py
├── YahooSearch.py
└── __init__.py
├── README.md
├── Setup.sh
├── SimplyEmail.py
└── bootstrap-3.3.5
├── LICENSE
└── SimplyEmailTemplate.html
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 |
5 | # C extensions
6 | *.so
7 |
8 | # Distribution / packaging
9 | .Python
10 | env/
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | *.egg-info/
23 | .installed.cfg
24 | *.egg
25 |
26 | # PyInstaller
27 | # Usually these files are written by a python script from a template
28 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
29 | *.manifest
30 | *.spec
31 |
32 | # Installer logs
33 | pip-log.txt
34 | pip-delete-this-directory.txt
35 |
36 | # Unit test / coverage reports
37 | htmlcov/
38 | .tox/
39 | .coverage
40 | .coverage.*
41 | .cache
42 | nosetests.xml
43 | coverage.xml
44 | *,cover
45 |
46 | # Translations
47 | *.mo
48 | *.pot
49 |
50 | # Django stuff:
51 | *.log
52 |
53 | # Sphinx documentation
54 | docs/_build/
55 |
56 | # PyBuilder
57 | target/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - "2.7"
4 | script:
5 | - "sudo sh Setup.sh"
6 | - "sudo ./SimplyEmail.py -l"
7 |
--------------------------------------------------------------------------------
/Common/SimplyEmail.ini:
--------------------------------------------------------------------------------
1 | [GlobalSettings]
2 | UserAgent: (Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6
3 | SaveFile: Email_List.txt
4 | HtmlFile: Email_List.html
5 |
6 | [ProcessConfig]
7 | TottalProcs: 8
8 |
9 | [APIKeys]
10 | Funcoming=Green
11 |
12 | # Settings for HTML Scrapping module
13 | # Save can add in a path - default is the SimpleEmail folder with domain name
14 | [HtmlScrape]
15 | Depth: 2
16 | Wait: 0
17 | LimitRate: 10000k
18 | Timeout: 2
19 | Save:
20 | RemoveHTML: Yes
21 |
22 | # You can use a few diffrent Key Servers so a config may be a good idea for this
23 | [SearchPGP]
24 | KeyServer: pgp.rediris.es:11371
25 | Hostname: pgp.rediris.es
26 |
27 | # Settings for Google Search
28 | [GoogleSearch]
29 | StartQuantity: 100
30 | QueryLimit: 500
31 | QueryStart: 0
32 |
33 | #Flickr Settings
34 | [FlickrSearch]
35 | Hostname: flickr.com
36 |
37 | #GitHub Code Scraping settigns
38 | #Page Depth: WARNING every page can contain upto 30 users and multiple links to scrape, this can slow down the results obtain very fast
39 | [GitHubSearch]
40 | PageDepth: 3
41 | QueryStart: 1
42 |
43 | #StartPAge Search engine settings
44 | [StartPageSearch]
45 | StartQuantity: 100
46 | QueryLimit: 1000
47 | QueryStart: 0
48 |
49 | #YahooSearch engine settings
50 | [YahooSearch]
51 | StartQuantity: 100
52 | QueryLimit: 600
53 | QueryStart: 0
54 |
55 | #Canary PasteBin Search NON-API
56 | [CanaryPasteBin]
57 | PageDepth: 2
58 | QueryStart: 1
59 | MaxPastesToSearch: 50
60 |
61 | # Search Git Hub Gist code
62 | # Page Depth: WARNING every page can contain upto 30 users and multiple links to scrape, this can slow down the results obtain very fast
63 | [GitHubGistSearch]
64 | PageDepth: 3
65 | QueryStart: 1
66 |
67 | # Ask Search Engine Search
68 | [AskSearch]
69 | StartQuantity: 10
70 | QueryPAgeLimit: 10
71 | QueryStart: 0
72 |
--------------------------------------------------------------------------------
/Common/TaskController.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import imp
3 | import glob
4 | import multiprocessing
5 | import Queue
6 | import threading
7 | import configparser
8 | import os
9 | import sys
10 | import warnings
11 | import time
12 | import subprocess
13 | from Helpers import helpers
14 | from Helpers import HtmlBootStrapTheme
15 |
16 |
17 | class Conducter:
18 |
19 | # We are going to do the following in this order:
20 | # 1) Load Modules
21 | # 2) Add them to an array
22 | # 3) Task selector will take all those module names and place them into a queue
23 | # 4) The Threading function will call and pop from the queue and will instanciate that module
24 | # 5) The module will than can be dynamic in nature and we can add to the framework easily and effectily
25 | # 6) The module will place the results (emails) into a results queue in
26 | # memmory so we can output to Sqlite or WebPage or Console
27 |
28 | def __init__(self):
29 | # Create dictionaries of supported modules
30 | # empty until stuff loaded into them
31 | # stolen from Veil :)
32 | self.modules = {}
33 | self.dmodules = {}
34 | # create required array
35 | self.Emails = []
36 | self.ConsumerList = []
37 | self.Tasks = []
38 | self.version = "0.3"
39 | self.ResultsList = []
40 |
41 | def ConfigSectionMap(section):
42 | dict1 = {}
43 | options = Config.options(section)
44 | for option in options:
45 | try:
46 | dict1[option] = Config.get(section, option)
47 | if dict1[option] == -1:
48 | DebugPrint("skip: %s" % option)
49 | except:
50 | print("exception on %s!" % option)
51 | dict1[option] = None
52 | return dict1
53 |
54 | def TestModule(self, module, domain):
55 | ModuleName = module
56 | module = self.modules[module]
57 | module = module.ClassName(domain)
58 | name = "[*]" + module.name
59 | print name
60 | module.execute()
61 |
62 | # Handler for each Process that will call all the modules in the Queue
63 | def ExecuteModule(self, Task_queue, Results_queue, domain):
64 | while True:
65 | Task = Task_queue.get()
66 | # If the queue is emepty exit this proc
67 | if Task is None:
68 | break
69 | # Inst the class
70 | try:
71 | ModuleName = Task
72 | Task = self.modules[Task]
73 | Module = Task.ClassName(domain)
74 | name = "[*] Starting: " + Module.name
75 | print helpers.color(name, status=True)
76 | # Try to start the module
77 | try:
78 | # Emails will be returned as a list
79 | Emails = Module.execute()
80 | if Emails:
81 | count = len(Emails)
82 | Length = "[*] " + Module.name + \
83 | ": Gathered " + str(count) + " Email(s)!"
84 | print helpers.color(Length, status=True)
85 | for Email in Emails:
86 | Results_queue.put(Email)
87 | #Task_queue.task_done()
88 | else:
89 | Message = "[*] " + Module.name + \
90 | " has completed with no Email(s)"
91 | print helpers.color(Message, status=True)
92 | except Exception as e:
93 | error = "[!] Error During Runtime in Module " + \
94 | Module.name + ": " + str(e)
95 | print helpers.color(error, warning=True)
96 | except Exception as e:
97 | error = "[!] Error Loading Module: " + str(e)
98 | print helpers.color(error, warning=True)
99 |
100 | def printer(self, FinalEmailList):
101 | # Building out the Text file that will be outputted
102 | Date = time.strftime("%d/%m/%Y")
103 | Time = time.strftime("%I:%M:%S")
104 | PrintTitle = "\t----------------------------------\n"
105 | PrintTitle += "\tEmail Recon: " + Date + " " + Time + "\n"
106 | PrintTitle += "\t----------------------------------\n"
107 | x = 0
108 | for item in FinalEmailList:
109 | item = item + "\n"
110 | if x == 0:
111 | try:
112 | with open('Email_List.txt', "a") as myfile:
113 | myfile.write(PrintTitle)
114 | except Exception as e:
115 | print e
116 | try:
117 | with open('Email_List.txt', "a") as myfile:
118 | myfile.write(item)
119 | x += 1
120 | except Exception as e:
121 | print e
122 | print helpers.color("[*] Completed output!", status=True)
123 | return x
124 |
125 | def HtmlPrinter(self, FinalEmailList, Domain):
126 | # Builds the HTML file
127 | # try:
128 | Html = HtmlBootStrapTheme.HtmlBuilder(FinalEmailList, Domain)
129 | Html.BuildHtml()
130 | Html.OutPutHTML()
131 | # except Exception as e:
132 | #error = "[!] Error building HTML file:" + e
133 | # print helpers.color(error, warning=True)
134 |
135 | def CleanResults(self, domain):
136 | # Clean Up results, remove dupplicates and enforce strict Domain reuslts (future)
137 | # Set Timeout or you wont leave the While loop
138 | SecondList = []
139 | # Validate the domain.. this can mess up but i dont want to miss
140 | # anything
141 | for item in self.ConsumerList:
142 | if domain in item:
143 | SecondList.append(item)
144 | FinalList = []
145 | # Itt over all items in the list
146 | for item in SecondList:
147 | # Check if the value is in the new list
148 | if item not in FinalList:
149 | # Add item to list and put back in the Queue
150 | FinalList.append(item)
151 | # results_queue.put(item)
152 | print helpers.color("[*] Completed Cleaning Results", status=True)
153 | return FinalList
154 |
155 | def Consumer(self, Results_queue):
156 | while True:
157 | try:
158 | item = Results_queue.get()
159 | if item is None:
160 | break
161 | self.ConsumerList.append(item)
162 | except:
163 | pass
164 |
165 | def TaskSelector(self, domain):
166 | # Here it will check the Que for the next task to be completed
167 | # Using the Dynamic loaded modules we can easly select which module is up
168 | # Rather than using If statment on every task that needs to be done
169 |
170 | # Build our Queue of work for emails that we will gather
171 | Task_queue = multiprocessing.Queue()
172 | Results_queue = multiprocessing.Queue()
173 |
174 | # How many proc will we have, pull from config file, setting up the
175 | # config file handler
176 | Config = configparser.ConfigParser()
177 | Config.read("Common/SimplyEmail.ini")
178 | total_proc = int(Config['ProcessConfig']['TottalProcs'])
179 | # Place our email tasks in a queue
180 | for Task in self.modules:
181 | Task_queue.put(Task)
182 | # Make sure we arnt starting up Procs that arnt needed.
183 | if total_proc > len(self.modules):
184 | total_proc = len(self.modules)
185 | for i in xrange(total_proc):
186 | Task_queue.put(None)
187 | procs = []
188 | for thread in range(total_proc):
189 | procs.append(multiprocessing.Process(
190 | target=self.ExecuteModule, args=(Task_queue, Results_queue, domain)))
191 | for p in procs:
192 | p.daemon = True
193 | p.start()
194 | # This SAVED my life!
195 | # really important to understand that if the results queue was still full
196 | # the .join() method would not join even though a Consumer recived
197 | # a posin pill! This allows us to easily:
198 | # 1) start up all procs
199 | # 2) wait till all procs are posined
200 | # 3) than start up the cleaner and parser
201 | # 4) once finshed, than release by a break
202 | # 5) finally the Results_queue would be empty
203 | # 6) All procs can finally join!
204 | t = threading.Thread(target=self.Consumer, args=(Results_queue,))
205 | t.daemon = True
206 | t.start()
207 | # Enter this loop so we know when to terminate the Consumer thread
208 | # This multiprocessing.active_children() is also Joining!
209 | while True:
210 | LeftOver = multiprocessing.active_children()
211 | time.sleep(1)
212 | # We want to wait till we have no procs left, before we join
213 | if len(LeftOver) == 0:
214 | # Block untill all results are consumed
215 | time.sleep(2)
216 | Results_queue.put(None)
217 | # t.join()
218 | try:
219 | FinalEmailList = self.CleanResults(domain)
220 | except Exception as e:
221 | error = "[!] Something went wrong with parsing results:" + \
222 | str(e)
223 | print helpers.color(error, warning=True)
224 | try:
225 | FinalCount = self.printer(FinalEmailList)
226 | except Exception as e:
227 | error = "[!] Something went wrong with outputixng results:" + \
228 | str(e)
229 | print helpers.color(error, warning=True)
230 | Results_queue.close()
231 | try:
232 | self.HtmlPrinter(FinalEmailList, domain)
233 | except Exception as e:
234 | error = "[!] Something went wrong with HTML results:" + \
235 | str(e)
236 | print helpers.color(error, warning=True)
237 | break
238 | for p in procs:
239 | p.join()
240 | Task_queue.close()
241 | # Launches a single thread to output results
242 | self.CompletedScreen(FinalCount, domain)
243 |
244 | # This is the Test version of the multi proc above, this function
245 | # Helps with testing only one module at a time. Helping with proper
246 | # Module Dev and testing before intergration
247 | def TestModule(self, domain, module):
248 | Config = configparser.ConfigParser()
249 | Config.read("Common/SimplyEmail.ini")
250 | total_proc = int(1)
251 | Task_queue = multiprocessing.JoinableQueue()
252 | Results_queue = multiprocessing.Queue()
253 | for Task in self.modules:
254 | if module in Task:
255 | Task_queue.put(Task)
256 | # Only use one proc since this is a test module
257 | for i in xrange(total_proc):
258 | Task_queue.put(None)
259 | procs = []
260 | for thread in range(total_proc):
261 | procs.append(multiprocessing.Process(
262 | target=self.ExecuteModule, args=(Task_queue, Results_queue, domain)))
263 | for p in procs:
264 | p.daemon = True
265 | p.start()
266 | # This SAVED my life!
267 | # really important to understand that if the results queue was still full
268 | # the .join() method would not join even though a Consumer recived
269 | # a posin pill! This allows us to easily:
270 | # 1) start up all procs
271 | # 2) wait till all procs are posined
272 | # 3) than start up the cleaner and parser
273 | # 4) once finshed, than release by a break
274 | # 5) finally the Results_queue would be empty
275 | # 6) All procs can finally join!
276 | t = threading.Thread(target=self.Consumer, args=(Results_queue,))
277 | t.daemon = True
278 | t.start()
279 | # Enter this loop so we know when to terminate the Consumer thread
280 | # This multiprocessing.active_children() is also Joining!
281 | while True:
282 | LeftOver = multiprocessing.active_children()
283 | time.sleep(1)
284 | # We want to wait till we have no procs left, before we join
285 | if len(LeftOver) == 0:
286 | # Block untill all results are consumed
287 | time.sleep(2)
288 | Results_queue.put(None)
289 | # t.join()
290 | try:
291 | FinalEmailList = self.CleanResults(domain)
292 | except Exception as e:
293 | error = "[!] Something went wrong with parsing results:" + \
294 | str(e)
295 | print helpers.color(error, warning=True)
296 | try:
297 | FinalCount = self.printer(FinalEmailList)
298 | except Exception as e:
299 | error = "[!] Something went wrong with outputixng results:" + \
300 | str(e)
301 | print helpers.color(error, warning=True)
302 | Results_queue.close()
303 | try:
304 | self.HtmlPrinter(FinalEmailList, domain)
305 | except Exception as e:
306 | error = "[!] Something went wrong with HTML results:" + \
307 | str(e)
308 | print helpers.color(error, warning=True)
309 | break
310 | for p in procs:
311 | p.join()
312 | Task_queue.close()
313 | # Launches a single thread to output results
314 | self.CompletedScreen(FinalCount, domain)
315 |
316 | def load_modules(self):
317 | # loop and assign key and name
318 | warnings.filterwarnings('ignore', '.*Parent module*',)
319 | x = 1
320 | for name in glob.glob('Modules/*.py'):
321 | if name.endswith(".py") and ("__init__" not in name):
322 | loaded_modules = imp.load_source(
323 | name.replace("/", ".").rstrip('.py'), name)
324 | self.modules[name] = loaded_modules
325 | self.dmodules[x] = loaded_modules
326 | x += 1
327 | return self.dmodules
328 | return self.modules
329 |
330 | def ListModules(self):
331 | print helpers.color(" [*] Available Modules are:\n", blue=True)
332 | lastBase = None
333 | x = 1
334 | for name in self.modules:
335 | parts = name.split("/")
336 | if lastBase and parts[0] != lastBase:
337 | print ""
338 | lastBase = parts[0]
339 | print "\t%s)\t%s" % (x, '{0: <24}'.format(name))
340 | x += 1
341 | print ""
342 |
343 | def title(self):
344 | os.system('clear')
345 | # stolen from Veil :)
346 | print " ============================================================"
347 | print " Curent Version: " + self.version + " | Website: CyberSyndicates.com"
348 | print " ============================================================"
349 | print " Twitter: @real_slacker007 | Twitter: @Killswitch_gui"
350 | print " ============================================================"
351 |
352 | def title_screen(self):
353 | offtext = """------------------------------------------------------------
354 | ______ ________ __ __
355 | / \/ | / / |
356 | /$$$$$$ $$$$$$$$/ _____ ____ ______ $$/$$ |
357 | $$ \__$$/$$ |__ / \/ \ / \/ $$ |
358 | $$ \$$ | $$$$$$ $$$$ |$$$$$$ $$ $$ |
359 | $$$$$$ $$$$$/ $$ | $$ | $$ |/ $$ $$ $$ |
360 | / \__$$ $$ |_____$$ | $$ | $$ /$$$$$$$ $$ $$ |
361 | $$ $$/$$ $$ | $$ | $$ $$ $$ $$ $$ |
362 | $$$$$$/ $$$$$$$$/$$/ $$/ $$/ $$$$$$$/$$/$$/
363 |
364 | ------------------------------------------------------------"""
365 | print helpers.color(offtext, bold=False)
366 |
367 | def CompletedScreen(self, FinalCount, domain):
368 | Config = configparser.ConfigParser()
369 | Config.read("Common/SimplyEmail.ini")
370 | TextSaveFile = str(Config['GlobalSettings']['SaveFile'])
371 | HtmlSaveFile = str(Config['GlobalSettings']['HtmlFile'])
372 |
373 | Line = " [*] Email reconnaissance has been completed:\n\n"
374 | Line += " File Location: \t\t" + os.getcwd() + "\n"
375 | Line += " Unique Emails Found:\t\t" + str(FinalCount) + "\n"
376 | Line += " Raw Email File:\t\t" + str(TextSaveFile) + "\n"
377 | Line += " HTML Email File:\t\t" + str(HtmlSaveFile) + "\n"
378 | Line += " Domain Performed:\t\t" + str(domain) + "\n"
379 | self.title()
380 | print Line
381 |
382 | # Ask user to open report on CLI
383 | Question = "[>] Would you like to launch the HTML report?: "
384 | Answer = raw_input(helpers.color(Question, bold=False))
385 | Answer = Answer.upper()
386 | if Answer in "NO":
387 | sys.exit(0)
388 | if Answer in "YES":
389 | # gnome-open cisco.doc
390 | subprocess.Popen(("gnome-open",HtmlSaveFile), stdout=subprocess.PIPE)
391 |
--------------------------------------------------------------------------------
/Common/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustedsec/SimplyEmail/0666c57f64d642d8b2c8bb477d0696f9e0d30f23/Common/__init__.py
--------------------------------------------------------------------------------
/Helpers/HtmlBootStrapTheme.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # encoding=utf8
3 | import sys
4 | from Helpers import helpers
5 |
6 | # This Classes main goal is to build the HTML output file using all self
7 | # contained CSS and JS
8 |
9 |
10 | class HtmlBuilder:
11 |
12 | def __init__(self, Emails, Domain):
13 | self.Emails = Emails
14 | self.Domain = Domain
15 | self.HTML = ""
16 | reload(sys)
17 | sys.setdefaultencoding('utf8')
18 |
19 | def BuildHtml(self):
20 | BottomHtml = """
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
31 |
32 |
41 |
74 |
75 |