Skip to content

Commit

Permalink
Merge pull request #144 from ChrisTruncer/nuke_it_all
Browse files Browse the repository at this point in the history
EyeWitness 2.0
  • Loading branch information
ChrisTruncer committed Jun 15, 2015
2 parents e0f3c85 + b3b3d15 commit 02bb7be
Show file tree
Hide file tree
Showing 19 changed files with 3,365 additions and 1,881 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.pyc
/EyeWitness.sublime-workspace
/EyeWitness.sublime-project
/setup.cfg
2,234 changes: 495 additions & 1,739 deletions EyeWitness.py

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -674,3 +674,28 @@ may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

PhantomJS:

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 changes: 5 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
EyeWitness
======

<!---
### Status
[![Build Status](https://travis-ci.org/ChrisTruncer/EyeWitness.png)](https://travis-ci.org/simkimsia/ChrisTruncer/EyeWitness)
-->
EyeWitness is designed to take screenshots of websites, RDP services, and open VNC servers, provide some server header info, and identify default credentials if possible.

EyeWitness is designed to take screenshots of websites, provide some server header info, and identify default credentials if possible.

Inspiration came from Tim Tomes's PeepingTom Script. I just wanted to change some things, and then it became a thought exercise to write it myself.

EyeWitness is designed to run on Kali Linux. It will auto detect the file you give it with the -f flag as either being a text file with URLs on each new line, nmap xml output, or nessus xml output. The -t (timeout) flag is completely optional, and lets you provide the max time to wait when trying to render and screenshot a web page. The --open flag, which is optional, will open the URL in a new tab within iceweasel.
EyeWitness is designed to run on Kali Linux. It will auto detect the file you give it with the -f flag as either being a text file with URLs on each new line, nmap xml output, or nessus xml output. The -t (timeout) flag is completely optional, and lets you provide the max time to wait when trying to render and screenshot a web page.

A complete usage guide which documents EyeWitness features and its typical use cases is available here - https://www.christophertruncer.com/eyewitness-usage-guide/

Expand All @@ -20,10 +13,6 @@ Kali Linux

Debian 7+ (at least stable, looking into testing) (Thanks to @themightyshiv)

CentOS 6.5+ (Thanks to @themightyshiv)

Windows - Download from: https://www.christophertruncer.com/InstallMe/EyeWitness.zip (Note: To check for default creds, be sure to include the signatures.txt file within the same directory as EyeWitness.exe)


E-Mail: EyeWitness [@] christophertruncer [dot] com

Expand All @@ -38,12 +27,11 @@ Usage:

Examples:

./EyeWitness -f urls.txt
./EyeWitness -f urls.txt --web

./EyeWitness -f urls.xml -t 8 --open
./EyeWitness -f urls.xml -t 8 --headless

Config File:
There is a sample config file within the "configs" directory. To use a config file, copy it (and modify it as needed) into the same directory as EyeWitness. Currently, the config file only works with the ruby version, however this will be added into the python version shortly. The config file is always trumped by the command line options.
./EyeWitness -f rdp.txt --rdp

Thanks:
Thanks to Jason Hill (@jasonhillva) for helping to get the xml parsing working. And thanks to the group of guys I work with giving me their thoughts on new features I could add in, ways to optimize the code, and more.
Expand Down
61 changes: 61 additions & 0 deletions Search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python

import glob
import os
import sys
import webbrowser

from distutils.util import strtobool
from modules.db_manager import DB_Manager
from modules.reporting import search_report


def open_file_input(cli_parsed):
files = glob.glob(os.path.join(cli_parsed.d, 'search.html'))
if len(files) > 0:
print 'Would you like to open the report now? [Y/n]',
while True:
try:
response = raw_input().lower()
if response is "":
return True
else:
return strtobool(response)
except ValueError:
print "Please respond with y or n",
else:
print '[*] No report files found to open, perhaps no hosts were successful'
return False


if __name__ == "__main__":
if len(sys.argv) < 3:
print 'Search a previously completed EyeWitness scan (HTTP page title/source)\n'
print '[*] Usage: python Search.py <dbpath> <searchterm>'
print 'DBPath should point to the ew.db file in your EyeWitness output folder'
sys.exit()
db_path = sys.argv[1]
if not os.path.isfile(db_path):
print '[*] No valid db path provided'
sys.exit()
search_term = sys.argv[2]
dbm = DB_Manager(db_path)
dbm.open_connection()
results = dbm.search_for_term(search_term)
if len(results) == 0:
print 'No results found!'
sys.exit()
else:
print 'Found {0} Results!'.format(str(len(results)))
cli_parsed = dbm.get_options()
cli_parsed.results = 25
oldfiles = glob.glob(os.path.join(cli_parsed.d, "*search*.html"))
for f in oldfiles:
os.remove(f)
search_report(cli_parsed, results, search_term)
newfiles = glob.glob(os.path.join(cli_parsed.d, "search.html"))
if open_file_input(cli_parsed):
for f in newfiles:
webbrowser.open(f)
sys.exit()
sys.exit()
1 change: 1 addition & 0 deletions bin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/phantomjs
Binary file added bin/dismissauth.xpi
Binary file not shown.
5 changes: 5 additions & 0 deletions bin/jquery-1.11.3.min.js

Large diffs are not rendered by default.

Empty file added modules/__init__.py
Empty file.
240 changes: 240 additions & 0 deletions modules/db_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
import pickle
import sqlite3

from objects import HTTPTableObject
from objects import UAObject
from objects import VNCRDPTableObject


class DB_Manager(object):

"""docstring for DB_Manager"""

def __init__(self, dbpath):
super(DB_Manager, self).__init__()
self._dbpath = dbpath
self._connection = None

@property
def connection(self):
return self._connection

@connection.setter
def connection(self, connection):
self._connection = connection

def initialize_db(self):
c = self.connection.cursor()
sqlite3.register_adapter(bool, int)
sqlite3.register_converter("BOOLEAN", lambda v: bool(int(v)))
c.execute('''CREATE TABLE opts
(object blob)''')
c.execute('''CREATE TABLE http
(id integer primary key, object blob, complete boolean)''')
c.execute('''CREATE TABLE rdpvnc
(id integer primary key, object blob, complete boolean)''')
c.execute('''CREATE TABLE ua
(id integer primary key, parent_id integer, object blob,
complete boolean, key text)''')
self.connection.commit()
c.close()

def open_connection(self):
self._connection = sqlite3.connect(
self._dbpath, check_same_thread=False)
self._connection.row_factory = sqlite3.Row

def create_http_object(self, remote_system, cli_parsed):
c = self.connection.cursor()
obj = HTTPTableObject()
obj.remote_system = remote_system
obj.set_paths(
cli_parsed.d, 'baseline' if cli_parsed.cycle is not None else None)
obj.max_difference = cli_parsed.difference
c.execute("SELECT MAX(id) FROM http")
rowid = c.fetchone()[0]
if rowid is None:
rowid = 0
obj.id = rowid + 1
pobj = sqlite3.Binary(pickle.dumps(obj, protocol=2))
c.execute(("INSERT INTO http (object, complete)"
"VALUES (?,?)"),
(pobj, False))
self.connection.commit()
c.close()
return obj

def create_ua_object(self, http_object, browser, ua):
c = self.connection.cursor()
obj = UAObject(browser, ua)
obj.copy_data(http_object)
c.execute("SELECT MAX(id) FROM ua")
rowid = c.fetchone()[0]
if rowid is None:
rowid = 0
obj.id = rowid + 1
pobj = sqlite3.Binary(pickle.dumps(obj, protocol=2))
c.execute(("INSERT INTO ua (parent_id, object, complete, key)"
" VALUES (?,?,?,?)"),
(http_object.id, pobj, False, browser))
self.connection.commit()
c.close()
return obj

def update_ua_object(self, ua_object):
c = self.connection.cursor()
o = sqlite3.Binary(pickle.dumps(ua_object, protocol=2))
c.execute(("UPDATE ua SET object=?,complete=? WHERE id=?"),
(o, True, ua_object.id))
self.connection.commit()
c.close()

def update_http_object(self, http_object):
c = self.connection.cursor()
o = sqlite3.Binary(pickle.dumps(http_object, protocol=2))
c.execute(("UPDATE http SET object=?,complete=? WHERE id=?"),
(o, True, http_object.id))
self.connection.commit()
c.close()

def save_options(self, cli_parsed):
opts = sqlite3.Binary(pickle.dumps(cli_parsed, protocol=2))
c = self.connection.cursor()
c.execute("INSERT INTO opts (object) VALUES (?)",
(opts,))
self.connection.commit()
c.close()

def get_options(self):
c = self.connection.cursor()
c.execute("SELECT * FROM opts")
blob = c.fetchone()['object']
cli_parsed = pickle.loads(str(blob))
return cli_parsed

def get_incomplete_http(self, q):
count = 0
c = self.connection.cursor()
for row in c.execute("SELECT * FROM http WHERE complete=0"):
o = pickle.loads(str(row['object']))
q.put(o)
count += 1
c.close()
return count

def get_incomplete_ua(self, q, key):
count = 0
c = self.connection.cursor()
for row in c.execute("SELECT * FROM ua WHERE complete=? AND key=?",
(0, key)):
o = pickle.loads(str(row['object']))
q.put(o)
count += 1
c.close()
return count

def get_complete_http(self):
finished = []
c = self.connection.cursor()
rows = c.execute("SELECT * FROM http WHERE complete=1").fetchall()
for row in rows:
o = pickle.loads(str(row['object']))
uadat = c.execute("SELECT * FROM ua WHERE parent_id=?",
(o.id,)).fetchall()
for ua in uadat:
uao = pickle.loads(str(ua['object']))
if uao is not None:
o.add_ua_data(uao)
finished.append(o)
c.close()
return finished

def create_vnc_rdp_object(self, proto, remote_system, cli_parsed):
c = self.connection.cursor()
obj = VNCRDPTableObject(proto)
if proto == 'vnc':
if ':' in remote_system:
ip, port = remote_system.split(':')
port = int(port)
else:
ip, port = remote_system, 5900
else:
if ':' in remote_system:
ip, port = remote_system.split(':')
port = int(port)
else:
ip, port = remote_system, 3389

obj.remote_system = ip
obj.port = port
obj.set_paths(cli_parsed.d)
c.execute("SELECT MAX(id) FROM rdpvnc")
rowid = c.fetchone()[0]
if rowid is None:
rowid = 0
obj.id = rowid + 1
pobj = sqlite3.Binary(pickle.dumps(obj, protocol=2))
c.execute(("INSERT INTO rdpvnc (object, complete)"
"VALUES (?,?)"),
(pobj, False))
self.connection.commit()
c.close()

def update_vnc_rdp_object(self, obj):
c = self.connection.cursor()
o = sqlite3.Binary(pickle.dumps(obj, protocol=2))
c.execute(("UPDATE rdpvnc SET complete=?, object=? WHERE id=?"),
(True, o, obj.id))
self.connection.commit()
c.close()

def get_incomplete_vnc_rdp(self):
targets = []
count = 0
c = self.connection.cursor()
for row in c.execute("SELECT * FROM rdpvnc WHERE complete=0",):
o = pickle.loads(str(row['object']))
targets.append(o)
count += 1
c.close()
return count, targets

def get_complete_vnc_rdp(self):
finished = []
c = self.connection.cursor()
rows = c.execute("SELECT * FROM rdpvnc WHERE complete=1").fetchall()
for row in rows:
o = pickle.loads(str(row['object']))
finished.append(o)
c.close()
return finished

def clear_table(self, tname):
c = self.connection.cursor()
c.execute("DELETE FROM {0}".format(tname))
self.connection.commit()
c.close()

def close(self):
self._connection.close()

def get_cursor(self):
return self.connection.cursor()

def search_for_term(self, search):
finished = []
c = self.connection.cursor()
rows = c.execute("SELECT * FROM http WHERE complete=1").fetchall()
for row in rows:
o = pickle.loads(str(row['object']))
uadat = c.execute("SELECT * FROM ua WHERE parent_id=?",
(o.id,)).fetchall()
for ua in uadat:
uao = pickle.loads(str(ua['object']))
if uao is not None:
o.add_ua_data(uao)
if o.error_state is None:
if search in o.source_code or search in o.page_title:
finished.append(o)
c.close()
return finished
Loading

0 comments on commit 02bb7be

Please sign in to comment.