forked from p34709852/monkey
Implement detection of monkey on island or locally
Fix UI issue of cleanup Kill all monkeys works Implemented logic for V ticking
This commit is contained in:
parent
8bada60fcd
commit
95d35fc8aa
|
@ -5,6 +5,7 @@ from flask import Flask, send_from_directory, redirect, make_response
|
||||||
import flask_restful
|
import flask_restful
|
||||||
|
|
||||||
from cc.database import mongo
|
from cc.database import mongo
|
||||||
|
from cc.resources.client_run import ClientRun
|
||||||
from cc.resources.monkey import Monkey
|
from cc.resources.monkey import Monkey
|
||||||
from cc.resources.local_run import LocalRun
|
from cc.resources.local_run import LocalRun
|
||||||
from cc.resources.telemetry import Telemetry
|
from cc.resources.telemetry import Telemetry
|
||||||
|
@ -75,6 +76,7 @@ def init_app(mongo_url):
|
||||||
api.add_resource(Root, '/api')
|
api.add_resource(Root, '/api')
|
||||||
api.add_resource(Monkey, '/api/monkey', '/api/monkey/', '/api/monkey/<string:guid>')
|
api.add_resource(Monkey, '/api/monkey', '/api/monkey/', '/api/monkey/<string:guid>')
|
||||||
api.add_resource(LocalRun, '/api/local-monkey', '/api/local-monkey/')
|
api.add_resource(LocalRun, '/api/local-monkey', '/api/local-monkey/')
|
||||||
|
api.add_resource(ClientRun, '/api/client-monkey', '/api/client-monkey/')
|
||||||
api.add_resource(Telemetry, '/api/telemetry', '/api/telemetry/', '/api/telemetry/<string:monkey_guid>')
|
api.add_resource(Telemetry, '/api/telemetry', '/api/telemetry/', '/api/telemetry/<string:monkey_guid>')
|
||||||
api.add_resource(MonkeyConfiguration, '/api/configuration', '/api/configuration/')
|
api.add_resource(MonkeyConfiguration, '/api/configuration', '/api/configuration/')
|
||||||
api.add_resource(MonkeyDownload, '/api/monkey/download', '/api/monkey/download/',
|
api.add_resource(MonkeyDownload, '/api/monkey/download', '/api/monkey/download/',
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
from flask import request, jsonify
|
||||||
|
import flask_restful
|
||||||
|
|
||||||
|
from cc.services.node import NodeService
|
||||||
|
|
||||||
|
__author__ = 'itay.mizeretz'
|
||||||
|
|
||||||
|
|
||||||
|
class ClientRun(flask_restful.Resource):
|
||||||
|
def get(self):
|
||||||
|
client_ip = request.remote_addr
|
||||||
|
if client_ip == "127.0.0.1":
|
||||||
|
monkey = NodeService.get_monkey_island_monkey()
|
||||||
|
else:
|
||||||
|
monkey = NodeService.get_monkey_by_ip(client_ip)
|
||||||
|
NodeService.update_dead_monkeys()
|
||||||
|
if monkey is not None:
|
||||||
|
is_monkey_running = not monkey["dead"]
|
||||||
|
else:
|
||||||
|
is_monkey_running = False
|
||||||
|
|
||||||
|
return jsonify(is_running=is_monkey_running)
|
|
@ -48,7 +48,14 @@ def run_local_monkey():
|
||||||
|
|
||||||
class LocalRun(flask_restful.Resource):
|
class LocalRun(flask_restful.Resource):
|
||||||
def get(self):
|
def get(self):
|
||||||
return jsonify(is_running=(NodeService.get_monkey_island_monkey() is not None))
|
NodeService.update_dead_monkeys()
|
||||||
|
island_monkey = NodeService.get_monkey_island_monkey()
|
||||||
|
if island_monkey is not None:
|
||||||
|
is_monkey_running = not island_monkey["dead"]
|
||||||
|
else:
|
||||||
|
is_monkey_running = False
|
||||||
|
|
||||||
|
return jsonify(is_running=is_monkey_running)
|
||||||
|
|
||||||
def post(self):
|
def post(self):
|
||||||
body = json.loads(request.data)
|
body = json.loads(request.data)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import json
|
import json
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime
|
||||||
|
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
from flask import request
|
from flask import request
|
||||||
|
@ -14,19 +14,9 @@ __author__ = 'Barak'
|
||||||
# TODO: separate logic from interface
|
# TODO: separate logic from interface
|
||||||
|
|
||||||
|
|
||||||
def update_dead_monkeys():
|
|
||||||
# Update dead monkeys only if no living monkey transmitted keepalive in the last 10 minutes
|
|
||||||
if mongo.db.monkey.find_one({'dead': {'$ne': True}, 'keepalive': {'$gte': datetime.now() - timedelta(minutes=10)}}):
|
|
||||||
return
|
|
||||||
|
|
||||||
mongo.db.monkey.update(
|
|
||||||
{'keepalive': {'$lte': datetime.now() - timedelta(minutes=10)}, 'dead': {'$ne': True}},
|
|
||||||
{'$set': {'dead': True, 'modifytime': datetime.now()}}, upsert=False, multi=True)
|
|
||||||
|
|
||||||
|
|
||||||
class Monkey(flask_restful.Resource):
|
class Monkey(flask_restful.Resource):
|
||||||
def get(self, guid=None, **kw):
|
def get(self, guid=None, **kw):
|
||||||
update_dead_monkeys() # refresh monkeys status
|
NodeService.update_dead_monkeys() # refresh monkeys status
|
||||||
if not guid:
|
if not guid:
|
||||||
guid = request.args.get('guid')
|
guid = request.args.get('guid')
|
||||||
timestamp = request.args.get('timestamp')
|
timestamp = request.args.get('timestamp')
|
||||||
|
|
|
@ -5,6 +5,7 @@ import flask_restful
|
||||||
|
|
||||||
from cc.database import mongo
|
from cc.database import mongo
|
||||||
from cc.services.config import ConfigService
|
from cc.services.config import ConfigService
|
||||||
|
from cc.services.node import NodeService
|
||||||
|
|
||||||
from cc.utils import local_ip_addresses
|
from cc.utils import local_ip_addresses
|
||||||
|
|
||||||
|
@ -30,10 +31,11 @@ class Root(flask_restful.Resource):
|
||||||
elif action == "killall":
|
elif action == "killall":
|
||||||
mongo.db.monkey.update({}, {'$set': {'config.alive': False, 'modifytime': datetime.now()}}, upsert=False,
|
mongo.db.monkey.update({}, {'$set': {'config.alive': False, 'modifytime': datetime.now()}}, upsert=False,
|
||||||
multi=True)
|
multi=True)
|
||||||
return 200
|
return jsonify(status='OK')
|
||||||
else:
|
else:
|
||||||
return make_response(400, {'error': 'unknown action'})
|
return make_response(400, {'error': 'unknown action'})
|
||||||
|
|
||||||
def get_completed_steps(self):
|
def get_completed_steps(self):
|
||||||
# TODO implement
|
is_any_exists = NodeService.is_any_monkey_exists()
|
||||||
return dict(run_server=True, run_monkey=False, infection_done=False)
|
is_any_alive = NodeService.is_any_monkey_alive()
|
||||||
|
return dict(run_server=True, run_monkey=is_any_exists, infection_done=(is_any_exists and not is_any_alive))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
|
|
||||||
from cc.database import mongo
|
from cc.database import mongo
|
||||||
|
@ -236,3 +236,22 @@ class NodeService:
|
||||||
{"_id": node_id},
|
{"_id": node_id},
|
||||||
{"$set": {"exploited": True}}
|
{"$set": {"exploited": True}}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_dead_monkeys():
|
||||||
|
# Update dead monkeys only if no living monkey transmitted keepalive in the last 10 minutes
|
||||||
|
if mongo.db.monkey.find_one(
|
||||||
|
{'dead': {'$ne': True}, 'keepalive': {'$gte': datetime.now() - timedelta(minutes=10)}}):
|
||||||
|
return
|
||||||
|
|
||||||
|
mongo.db.monkey.update(
|
||||||
|
{'keepalive': {'$lte': datetime.now() - timedelta(minutes=10)}, 'dead': {'$ne': True}},
|
||||||
|
{'$set': {'dead': True, 'modifytime': datetime.now()}}, upsert=False, multi=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_any_monkey_alive():
|
||||||
|
return mongo.db.monkey.find_one({'dead': False}) is not None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_any_monkey_exists():
|
||||||
|
return mongo.db.monkey.find_one({}) is not None
|
||||||
|
|
|
@ -47,7 +47,8 @@ class MapPageComponent extends React.Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
graph: {nodes: [], edges: []},
|
graph: {nodes: [], edges: []},
|
||||||
selected: null,
|
selected: null,
|
||||||
selectedType: null
|
selectedType: null,
|
||||||
|
killPressed: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +112,12 @@ class MapPageComponent extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
killAllMonkeys = () => {
|
||||||
|
fetch('/api?action=killall')
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(res => this.setState({killPressed: (res.status=="OK")}));
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -132,6 +139,12 @@ class MapPageComponent extends React.Component {
|
||||||
Kill All Monkeys
|
Kill All Monkeys
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{this.state.killPressed ?
|
||||||
|
<div className="alert alert-info">
|
||||||
|
<i className="glyphicon glyphicon-info-sign" style={{'marginRight': '5px'}}/>
|
||||||
|
Kill command sent to all monkeys
|
||||||
|
</div>
|
||||||
|
: ''}
|
||||||
|
|
||||||
<PreviewPane item={this.state.selected} type={this.state.selectedType} />
|
<PreviewPane item={this.state.selected} type={this.state.selectedType} />
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
@ -28,6 +28,13 @@ class RunMonkeyPageComponent extends React.Component {
|
||||||
.then(res => this.setState({
|
.then(res => this.setState({
|
||||||
isRunningOnIsland: res['is_running']
|
isRunningOnIsland: res['is_running']
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
fetch('/api/client-monkey')
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(res => this.setState({
|
||||||
|
isRunningLocally: res['is_running']
|
||||||
|
}));
|
||||||
|
|
||||||
this.props.onStatusChange();
|
this.props.onStatusChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,16 +106,16 @@ class RunMonkeyPageComponent extends React.Component {
|
||||||
className="btn btn-default"
|
className="btn btn-default"
|
||||||
disabled={this.state.isRunningOnIsland}>
|
disabled={this.state.isRunningOnIsland}>
|
||||||
Run on C&C Server
|
Run on C&C Server
|
||||||
{ !this.state.isRunningOnIsland ?
|
{ this.state.isRunningOnIsland ?
|
||||||
<Icon name="check" className="text-success" style={{'marginLeft': '5px'}}/>
|
<Icon name="check" className="text-success" style={{'marginLeft': '5px'}}/>
|
||||||
: ''}
|
: ''}
|
||||||
</button>
|
</button>
|
||||||
<a href="/download-monkey"
|
<a href="/download-monkey"
|
||||||
className="btn btn-default"
|
className="btn btn-default"
|
||||||
disabled={this.state.isRunningLocally}
|
disabled={this.state.isRunningLocally}
|
||||||
style={{'margin-left': '1em'}}>
|
style={{'marginLeft': '1em'}}>
|
||||||
Download and run locally
|
Download and run locally
|
||||||
{ !this.state.isRunningLocally ?
|
{ this.state.isRunningLocally ?
|
||||||
<Icon name="check" className="text-success" style={{'marginLeft': '5px'}}/>
|
<Icon name="check" className="text-success" style={{'marginLeft': '5px'}}/>
|
||||||
: ''}
|
: ''}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -41,18 +41,14 @@ class StartOverPageComponent extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup = () => {
|
||||||
// TODO: fix
|
|
||||||
/*
|
|
||||||
this.setState({
|
this.setState({
|
||||||
cleaned: false
|
cleaned: false
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
fetch('/api?action=reset')
|
fetch('/api?action=reset')
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res["status"] == "OK") {
|
if (res["status"] == "OK") {
|
||||||
// TODO: fix this
|
|
||||||
this.setState({
|
this.setState({
|
||||||
cleaned: true
|
cleaned: true
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue