Skip to content

Commit

Permalink
Adding initial scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
ztgrace committed Mar 4, 2018
1 parent e420dee commit 0e90f00
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# pwnboard
# PWNboard
CCDC Red Team PWNboard

![PWNboard](https://raw.githubusercontent.com/ztgrace/pwnboard/master/img/PWNboard.png)
32 changes: 32 additions & 0 deletions demo_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python

import redis
import random
from pwnboard import getTimeDelta
import datetime as dt
import time
import string

r = redis.StrictRedis(host='localhost')
for team in range(21, 31):
for host in (3, 9, 11, 23, 27, 39, 240, 241, 254):
if random.randint(1, 10) % 2 == 0:
continue

ip = "172.25.%i.%i" % (team, host)
status = dict()
status['host'] = "RT%i" % random.randint(1,5)
if random.randint(1, 10) % 3 == 0:
status['type'] = "meterpreter"
status['session'] = random.randint(1,100)
status['last_seen'] = None
elif random.randint(1, 10) % 2 == 0:
status['type'] = "backdoor"
status['session'] = random.choice(('root', 'admin' 'nobody'))
status['last_seen'] = time.mktime((dt.datetime.now() - dt.timedelta(minutes=random.randint(1, 10))).timetuple())
else:
status['type'] = "empire"
status['session'] = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8))
status['last_seen'] = time.mktime((dt.datetime.now() - dt.timedelta(minutes=random.randint(1, 10))).timetuple())

r.hmset(ip, status)
Binary file added img/PWNboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
130 changes: 130 additions & 0 deletions pwnboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env python2

from flask import Flask, request, render_template, flash, url_for, make_response
import redis
import datetime

TEAMS = range(21, 33)
HOSTS = (3,9,11,23,27,39,100)
NETWORK = "172.25"

r = redis.StrictRedis(host='localhost')
app = Flask(__name__, static_url_path='/static')
app.debug = True

@app.route('/', methods=['GET'])
def index():
error = ""
board = getBoardDict()
resp = make_response(render_template('index.html', error=error, board=board, teams=sorted(TEAMS), hosts=sorted(HOSTS), network=NETWORK))
return resp

def getBoardDict():
board = dict()
for team in TEAMS:
board[team] = dict()
for host in HOSTS:
ip = NETWORK + ".%i.%i" % (team, host)
h, s, t, last = r.hmget(ip, ('host', 'session', 'type', 'last_seen'))
status = dict()
status['host'] = h
status['session'] = s
status['type'] = t
if isinstance(last, type(None)):
#print "last: %s" % last
status['last_seen'] = None
else:
print "last: %s" % last
status['last_seen'] = getTimeDelta(last)
board[team][ip] = status

return board

def getTimeDelta(ts):
try:
checkin = datetime.datetime.fromtimestamp(float(ts))
except:
return 0
diff = datetime.datetime.now() - checkin
minutes = int(diff.total_seconds()/60)
return minutes



@app.route('/slack-events', methods=['POST'])
def slack_events():
res = request.json
if res.get('challenge', None):
return request.json['challenge']

if res.get('event', None) and res.get('event')['channel'] == 'C92BL6PU4':
process_shellz_event(res['event'])

return ""


def process_shellz_event(event):
text = event['text']
if 'empire' in event['text']:
parse_empire(event)
else:
parse_linux(event)

def parse_linux(event):
# "%s %s backdoor active on %s"
text = event['text']
status = Status()
status.ip = text.split(' ')[5]
status.host = text.split(' ')[0]
status.session = text.split(' ')[1]
status.last_seen = event['ts']

print status
status.save()

def parse_empire(event):
text = event['text']
status = Status(type='empire')
if "new agent" in text:
# kali new agent on 10.0.2.15; agent: HLT4VKEK; platform: Linux,kali,4.7.0-kali1-amd64,#1 SMP Debian 4.7.5-1kali3 (2016-09-29),x86_64; type: empire

status.ip = text.split(' ')[4].replace(';', '')
status.host = text.split(' ')[0]
status.session = text.split(' ')[6].replace(';', '')
status.last_seen = event['ts']
print status
status.save()

else:
# kali empire agent EHUDM1C7 checked in
session = text.split(' ')[3]
status = Status(session=session, type='empire')
status.ip = r.get(status.session)
status.host, s, t, status.last_seen = r.hmget(status.ip, ('host', 'session', 'type', 'last_seen'))
status.last_seen = event['ts']
print status
status.save()


class Status(object):
def __init__(self, ip=None, host=None, session=None, type=None, last_seen=None):
self.ip = ip
self.host = host
self.session = session
self.type = type
self.last_seen = last_seen

self.redis = redis.StrictRedis(host='localhost')

def __str__(self,):
return "ip: %s, host: %s, session: %s, type: %s, last_seen: %s" % (self.ip, self.host, self.session, self.type, self.last_seen)

def save(self,):
r.hmset(self.ip, {'host': self.host, 'session': self.session, 'type': self.type, 'last_seen': self.last_seen})
if self.type == 'empire':
r.set(self.session, self.ip)



if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
5 changes: 5 additions & 0 deletions reset_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env python

import redis
r = redis.StrictRedis(host='localhost')
r.flushdb()
69 changes: 69 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<html>
<head>
<title>PWNboard</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha256-LA89z+k9fjgMKQ/kq4OO2Mrf8VltYml/VES+Rg0fh20=" crossorigin="anonymous"> <!-- Latest compiled and minified Bootstrap CSS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script> <!-- Latest compiled and minified JavaScript -->
<link href='https://fonts.googleapis.com/css?family=Titillium+Web:600,400' rel='stylesheet' type='text/css' />
<link href='https://fonts.googleapis.com/css?family=Jura:400,600' rel='stylesheet' type='text/css' />
<link rel='stylesheet' href='/static/pwnboard.css' type='text/css' />
<meta http-equiv="refresh" content="10">
</head>
<body>
<div class="container text-center">
{% if error %}
<p id="error" class="alert alert-danger">{{ error }}</p>
{% endif %}
{% block content %}
{% endblock %}
<h1 class="title">PWNboard</h1>
</div>
<div class="" style="width:100%">
<table class="table table-dark table-bordered">
<tr>
<thead>
<td>Hosts</td>
{% for team in teams %}
<td>Team {{ team - 20}}</td>
{% endfor %}
</tr>
{% for host in hosts %}
<tr>
{% if host == 3 %}
<td><b>2012</b></td>
{% elif host == 9 %}
<td><b>FILESERVER1</b></td>
{% elif host == 11 %}
<td><b>e-comm</b></td>
{% elif host == 23 %}
<td><b>Ubuntu DNS</b></td>
{% elif host == 27 %}
<td><b>DC</b></td>
{% elif host == 39 %}
<td><b>mail</b></td>
{% elif host == 100 %}
<td><b>PAN</b></td>
{% else %}
<td><b>Host</b></td>
{% endif %}
{% for team in teams %}
{% set ip = network + ".%i.%i" % (team, host) %}
{% if board.get(team, None) and board[team][ip]['type'] and board[team][ip]['last_seen'] < 5 %}
<td class="bg-success">
{% else %}
<td class="bg-danger">
{% endif %}
<b>{{ip}}</b><br/>
{% if board[team][ip]['type'] %}
<span style="font-size: 0.8em;">host: {{ board[team][ip]['host']}}, session: {{board[team][ip]['session']}}, type: {{board[team][ip]['type']}}</span>
<span style="font-size: 0.8em;">last seen: {{ board[team][ip]['last_seen'] }}m</span>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</div>
</body>
</html>

0 comments on commit 0e90f00

Please sign in to comment.