Skip to content
This repository has been archived by the owner on Jan 8, 2024. It is now read-only.

Commit

Permalink
Add user attribution for ida actions
Browse files Browse the repository at this point in the history
  • Loading branch information
Tristan Pourcelot committed Feb 12, 2018
1 parent 66d57db commit 6541dbc
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 40 deletions.
66 changes: 39 additions & 27 deletions poli/controllers/idaactions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"""
This file is part of Polichombr.
(c) 2017 ANSSI-FR
(c) 2018 ANSSI-FR
Description:
Managers for all the actions associated with IDAPro models
Expand All @@ -26,6 +25,9 @@ class IDAActionsController(object):
"""
@staticmethod
def get_all(sid=None, timestamp=None):
"""
Return all the actions for a sample from a timestamp
"""
if sid is None:
return False
query = IDAAction.query
Expand All @@ -37,16 +39,25 @@ def get_all(sid=None, timestamp=None):
return schema.dump(query.all()).data

@staticmethod
def add_comment(address, data):
def setup_generic_action(action, address, data, user_id=None):
"""
Setup and commit the common parts of an IDA action
"""
action.address = address
action.data = data
action.timestamp = datetime.datetime.now()
action.user_id = user_id
db.session.add(action)
db.session.commit()
return action

@classmethod
def add_comment(cls, address, data, user_id=None):
"""
Creates a new comment action
"""
comment = IDACommentAction()
comment.address = address
comment.data = data
comment.timestamp = datetime.datetime.now()
db.session.add(comment)
db.session.commit()
comment = cls.setup_generic_action(comment, address, data, user_id)
return comment.id

@staticmethod
Expand Down Expand Up @@ -78,17 +89,13 @@ def get_comments(cls, sid=None, addr=None, timestamp=None):
data = schema.dump(data).data
return data

@staticmethod
def add_name(address=None, data=None):
@classmethod
def add_name(cls, address=None, data=None, user_id=None):
"""
Creates a new name action
"""
name = IDANameAction()
name.address = address
name.data = data
name.timestamp = datetime.datetime.now()
db.session.add(name)
db.session.commit()
name = cls.setup_generic_action(name, address, data, user_id)
return name.id

@classmethod
Expand All @@ -102,22 +109,28 @@ def get_names(cls, sid, addr=None, timestamp=None):
schema = IDAActionSchema(many=True)
return schema.dump(data).data

@staticmethod
def create_struct(name=None):
@classmethod
def create_struct(cls, name=None, user_id=None):
"""
Create a new struct.
"""
if name is None:
app.logger.error("Cannot create anonymous struct")
return False
mstruct = IDAStruct()
mstruct = cls.setup_generic_action(mstruct, 0, name, user_id)

mstruct.name = name
mstruct.data = name
mstruct.timestamp = datetime.datetime.now()
mstruct.size = 0
db.session.add(mstruct)
db.session.commit()
return mstruct.id

@staticmethod
def get_structs(sid, timestamp=None):
"""
List all structs from a given timestamp
"""
query = IDAStruct.query
query = query.filter(IDAStruct.samples.any(Sample.id == sid))

Expand Down Expand Up @@ -166,7 +179,7 @@ def rename_struct(struct_id, name):
@staticmethod
def delete_struct(struct_id):
"""
Delete a struct, but not it's members
"""
mstruct = IDAStruct.query.get(struct_id)
app.logger.debug("Deleting struct %s", mstruct.name)
Expand All @@ -176,6 +189,9 @@ def delete_struct(struct_id):

@staticmethod
def create_struct_member(name=None, size=None, offset=None):
"""
Create a struct member, but don't affect it to the struct yet
"""
member = IDAStructMember()
if member is None:
return False
Expand Down Expand Up @@ -241,17 +257,13 @@ def change_struct_member_size(cls, struct_id, mid, new_size):

return True

@staticmethod
def add_typedef(address, typedef):
@classmethod
def add_typedef(cls, address, typedef, user_id):
"""
Creates a new type definition
"""
mtype = IDATypeAction()
mtype.address = address
mtype.data = typedef
mtype.timestamp = datetime.datetime.now()
db.session.add(mtype)
db.session.commit()
mtype = cls.setup_generic_action(mtype, address, typedef, user_id)
return mtype.id

@classmethod
Expand Down
8 changes: 4 additions & 4 deletions poli/controllers/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def create_sample_from_file(self, file_data, orig_filename="", user=None,
# If not, we will just update some information
if Sample.query.filter_by(sha256=sha_256).count() != 0:
sample = Sample.query.filter_by(sha256=sha_256).first()
if sample.storage_file is not None and sample.storage_file != "" and os.path.exists(
if sample.storage_file is not None and os.path.exists(
sample.storage_file):
return sample

Expand Down Expand Up @@ -637,12 +637,12 @@ def add_metadata(sample, metadata_type, metadata_value):
metadata_value = hex(metadata_value)
else:
try:
metadata_value = str(metadata_value)
metadata_value = str(metadata_value).replace("\x00", "")
except Exception as e:
app.logger.exception(e)
return False
for s_metadata in sample.s_metadata:
if s_metadata.type_id == metadata_type and s_metadata.value == metadata_value:
for meta in sample.s_metadata:
if meta.type_id == metadata_type and meta.value == metadata_value:
return True
s_metadata = SampleMetadata()
s_metadata.value = metadata_value
Expand Down
2 changes: 1 addition & 1 deletion poli/templates/sample.html
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ <h3 class="panel-title">IDA PRO commands <a class="btn btn-xs btn-default" style
<td>{{"0x%x"|format((act.address|int))}}</td>
<td>{{act.type}}</td>
<td>{{act.data}}</td>
<td>Analyst</td>
<td>{{act.user_id}}</td>
<td><button type="button" class="warning" aria-label="Close">Delete</span></button> </td>
</tr>
{% endfor %}
Expand Down
14 changes: 9 additions & 5 deletions poli/views/api_idaactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import datetime

from flask import jsonify, request, abort, current_app
from flask_security import login_required
from flask_security import login_required, current_user

from poli import api
from poli.views.apiview import apiview
Expand Down Expand Up @@ -105,12 +105,13 @@ def api_post_sample_comments(sid):
abort(400, "Missing comment or address arguments")
address = data['address']
comment = data['comment']
user_id = current_user.id
current_app.logger.debug(
"Getting a new comment for sample %d : %s@0x%x",
sid,
comment,
address)
action_id = api.idacontrol.add_comment(address, comment)
action_id = api.idacontrol.add_comment(address, comment, user_id)
result = api.samplecontrol.add_idaaction(sid, action_id)
return jsonify({'result': result})

Expand Down Expand Up @@ -141,12 +142,13 @@ def api_post_sample_names(sid):
data = request.json
addr = data['address']
name = data['name']
user_id = current_user.id
current_app.logger.debug(
"Getting a new name for sample %d : %s@0x%x",
sid,
name,
addr)
action_id = api.idacontrol.add_name(addr, name)
action_id = api.idacontrol.add_name(addr, name, user_id)
result = api.samplecontrol.add_idaaction(sid, action_id)
if result is True:
api.samplecontrol.rename_func_from_action(sid, addr, name)
Expand All @@ -164,8 +166,9 @@ def api_post_sample_types(sid):
data = request.json
addr = data['address']
typedef = data['typedef']
user_id = current_user.id

action_id = api.idacontrol.add_typedef(addr, typedef)
action_id = api.idacontrol.add_typedef(addr, typedef, user_id)
result = api.samplecontrol.add_idaaction(sid, action_id)
return jsonify(dict(result=result))

Expand Down Expand Up @@ -194,7 +197,8 @@ def api_create_struct(sid):
result = False
name = data['name']
current_app.logger.debug("Creating structure %s" % name)
mstruct = api.idacontrol.create_struct(name=name)
user_id = current_user.id
mstruct = api.idacontrol.create_struct(name=name, user_id=user_id)
if mstruct is not False:
result = api.samplecontrol.add_idaaction(sid, mstruct)
return jsonify({'result': result, 'structs': [{'id': mstruct}]})
Expand Down
5 changes: 3 additions & 2 deletions poli/views/apiview.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from poli.models.user import User

from flask import jsonify, request, abort, make_response
from flask import Blueprint
from flask import Blueprint, current_app

apiview = Blueprint('apiview', __name__,
url_prefix=app.config['API_PATH'])
Expand Down Expand Up @@ -106,7 +106,8 @@ def generate_token():
key = data['api_key']
user = User.query.filter_by(api_key=key).first()
if not user:
abort(400, "Invalid user")
current_app.logger.error("Invalid user trying to login")
abort(401, "Invalid user")
return jsonify({'token': user.get_auth_token()})


Expand Down
11 changes: 11 additions & 0 deletions run.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
#!/usr/bin/env python
"""
This file is part of Polichombr.
(c) 2018 ANSSI-FR
Description:
Wrapper for running the application
"""

from poli import app

if __name__ == "__main__":

app.run(app.config['SERVER_ADDR'],
port=app.config['SERVER_PORT'],
debug=app.config['DEBUG'])
2 changes: 1 addition & 1 deletion tests/tests_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ def test_get_all(self):
self.assertIn(actions["idaactions"][3]["data"], "TESTCOMMENT2")

self.assertIn(actions["idaactions"][4]["type"], "idastructs")
self.assertEqual(actions["idaactions"][4]["address"], None)
self.assertEqual(actions["idaactions"][4]["address"], 0)
self.assertIn(actions["idaactions"][4]["data"], "ThisIsAStruct")

def test_push_comments(self):
Expand Down

0 comments on commit 6541dbc

Please sign in to comment.