class IDAAction(db.Model): """ Abstract class for implementing IDA actions. This mirrors actions done by the analyst on his database """ __tablename__ = "idaactions" id = db.Column(db.Integer(), primary_key=True) # The action data data = db.Column(db.String()) # The address where the action occured address = db.Column(db.Integer(), index=True) # We must keep timestamp to reorder actions timestamp = db.Column(db.DateTime()) # We also keep the last user user_id = db.Column(db.Integer, db.ForeignKey('user.id')) # The action type type = db.Column(db.String()) __mapper_args__ = { 'polymorphic_identity': 'analysisresult', 'polymorphic_on': type }
class IDAStructMember(db.Model): __tablename__ = "idastructmember" id = db.Column(db.Integer(), primary_key=True) struct_id = db.Column(db.Integer(), db.ForeignKey("idastructs.id")) name = db.Column(db.String(), index=True) size = db.Column(db.Integer()) mtype = db.Column(db.String()) offset = db.Column(db.Integer())
class CheckList(db.Model): """ Checklist fields and description. This is a global information, set in the admin panel, links will just determine if checked or not. """ __tablename__ = 'checklist' id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String()) description = db.Column(db.String())
class FamilyDataFile(db.Model): """ Family data file. Whatever you want, script, report, etc. """ __tablename__ = "family_file" id = db.Column(db.Integer, primary_key=True) filepath = db.Column(db.String()) filename = db.Column(db.String()) description = db.Column(db.String()) TLP_sensibility = db.Column(db.Integer(), default=TLPLevel.TLPAMBER) family_id = db.Column(db.Integer(), db.ForeignKey("family.id"))
class DetectionElement(db.Model): """ Detection element: provided by users, can be any of the DetectionType values. """ __tablename__ = "detection_element" id = db.Column(db.Integer, primary_key=True) abstract = db.Column(db.String()) name = db.Column(db.String()) TLP_sensibility = db.Column(db.Integer(), default=TLPLevel.TLPAMBER) item_type = db.Column(db.Integer()) family_id = db.Column(db.Integer(), db.ForeignKey("family.id"))
class AnalysisResult(db.Model): """ Containing all PE analysis data. """ __tablename__ = "analysisresult" id = db.Column(db.Integer(), primary_key=True) sample_id = db.Column(db.Integer(), db.ForeignKey('sample.id')) analysis_status = db.Column(db.Boolean()) analysis_date = db.Column(db.DateTime()) title = db.Column(db.String()) data = db.Column(db.String()) type = db.Column(db.String())
class PESection(db.Model): __tablename__ = 'pesection' id = db.Column(db.Integer(), primary_key=True) s_Name = db.Column(db.String(), index=True) s_Misc = db.Column(db.Integer()) s_PhysicalAddress = db.Column(db.Integer()) s_VirtualSize = db.Column(db.Integer()) s_VirtualAddress = db.Column(db.Integer()) s_SizeOfRawData = db.Column(db.Integer()) s_PointerToRawData = db.Column(db.Integer()) s_PointerToRelocations = db.Column(db.Integer()) s_PointerToLineNumbers = db.Column(db.Integer()) s_NumberOfRelocations = db.Column(db.Integer()) s_NumberOfLinenumbers = db.Column(db.Integer()) s_Characteristics = db.Column(db.Integer()) s_md5 = db.Column(db.String())
class FileName(db.Model): """ Sample's files names. """ __tablename__ = 'filename' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String()) sample_id = db.Column(db.Integer(), db.ForeignKey("sample.id"))
class Role(db.Model, RoleMixin): __tablename__ = 'auth_role' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String()) def __init__(self, name, description): self.name = name self.description = description def setDescription(self, description): self.description = description def toString(self): return {"name": self.name, "description": self.description} def __repr__(self): return '<Role %r>' % self.name
class SampleMatch(db.Model): """ Match between samples. Used to spot samples similarities on analysis. Displayed to user. """ __tablename__ = 'samplematch' id = db.Column(db.Integer, primary_key=True) sid_1 = db.Column(db.Integer, db.ForeignKey('sample.id'), index=True) sid_2 = db.Column(db.Integer, db.ForeignKey('sample.id'), index=True) match_type = db.Column(db.String(), index=True)
class StringsItem(db.Model): """ Strings contained in a binary file. Strings types are defined by the StringsType enum class. """ __tablename__ = 'stringsitem' id = db.Column(db.Integer, primary_key=True) string_type = db.Column(db.Integer(), index=True) string_value = db.Column(db.String()) sample_id = db.Column(db.Integer(), db.ForeignKey("sample.id"), index=True)
class IDACommentAction(IDAAction): """ Implement comments """ __tablename__ = 'idacomments' id = db.Column(db.Integer(), db.ForeignKey('idaactions.id'), primary_key=True) comment = db.Column(db.String()) __mapper_args__ = {'polymorphic_identity': 'idacomment'}
class SampleMetadata(db.Model): """ Generic table used to store generic file metadata. Type must be defined in the SampleMetadataType enum class below. Value contains the metadata itself. """ __tablename__ = 'samplemetadata' id = db.Column(db.Integer, primary_key=True) type_id = db.Column(db.Integer(), index=True) value = db.Column(db.String()) sample_id = db.Column(db.Integer(), db.ForeignKey("sample.id"), index=True)
class FunctionInfo(db.Model): """ Function information. Contains function's name, machoc hash and address. Used for quick function access. Machoc hash can be updated by tasks or by skelenox itself. """ __tablename__ = 'functioninfo' id = db.Column(db.Integer, primary_key=True) address = db.Column(db.BigInteger(), index=True) name = db.Column(db.String(), index=True) machoc_hash = db.Column(db.BigInteger(), index=True) sample_id = db.Column(db.Integer(), db.ForeignKey("sample.id"), index=True)
class YaraRule(db.Model): """ Yara rule model. """ __tablename__ = 'yararule' id = db.Column(db.Integer, primary_key=True) # yara name (displayed) name = db.Column(db.String(), unique=True) # raw yara rule raw_rule = db.Column(db.String()) # creation's date creation_date = db.Column(db.DateTime()) # TLP sensibility TLP_sensibility = db.Column(db.Integer(), nullable=False) def __init__(self, name, raw_rule, TLP_sensibility): self.creation_date = datetime.now() self.modif_date = datetime.now() self.raw_rule = raw_rule self.name = name self.TLP_sensibility = TLP_sensibility
class Family(db.Model): """ Family model. """ __tablename__ = 'family' id = db.Column(db.Integer, primary_key=True) # N-N relationships samples = db.relationship('Sample', secondary=familytosample, backref=db.backref('families', lazy='dynamic')) yaras = db.relationship('YaraRule', secondary=familytoyara, backref=db.backref('families', lazy='dynamic')) # 1-N relationships parent_id = db.Column(db.Integer, db.ForeignKey('family.id')) subfamilies = db.relationship('Family', backref=db.backref('parents', remote_side=[id])) # 1-N relationships, without any backrefs for now associated_files = db.relationship('FamilyDataFile') detection_items = db.relationship('DetectionElement') # Family name's name = db.Column(db.String(), index=True, unique=True) # User-supplied abstract abstract = db.Column(db.String()) # Analysis status status = db.Column(db.Integer(), default=FamilyStatus.NOT_STARTED) # Tlp level TLP_sensibility = db.Column(db.Integer(), default=TLPLevel.TLPAMBER) def __repr__(self): return 'Family %d %s' % (self.id, self.name) def __init__(self, name=None): if name is None: raise IOError self.name = name
class User(db.Model, UserMixin): """ User model. """ __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) # N-N relationships samples = db.relationship('Sample', secondary=usersample, backref=db.backref('users', lazy="dynamic")) families = db.relationship('Family', secondary=userfamily, backref=db.backref('users', lazy="dynamic")) # Login nickname = db.Column(db.String(), index=True, unique=True) # Complete user name completename = db.Column(db.String(), index=True, unique=True) theme = db.Column(db.String()) # User's email (not used for now) email = db.Column(db.String(), index=True, unique=True) # Password password = db.Column(db.String()) api_key = db.Column(db.String()) roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic')) last_login_at = db.Column(db.DateTime()) current_login_at = db.Column(db.DateTime()) last_login_ip = db.Column(db.String(45)) current_login_ip = db.Column(db.String(45)) login_count = db.Column(db.Integer) active = db.Column(db.Boolean(), default=False) def get_id(self): return self.id def __repr__(self): return '<User %r>' % (self.nickname)
class IDAStruct(IDAAction): """ Structures are a particular type of actions, as the address and will always be null, and they store a relationship with their members The management of the members is done by the controller, and at each update the structure's timestamp is updated """ __tablename__ = "idastructs" id = db.Column(db.Integer(), db.ForeignKey('idaactions.id'), primary_key=True) name = db.Column(db.String()) size = db.Column(db.Integer()) members = db.relationship("IDAStructMember", backref=db.backref("struct"), remote_side=[id]) __mapper_args__ = {"polymorphic_identity": "idastructs"}
class User(db.Model, UserMixin): """ User model. """ __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) # N-N relationships samples = db.relationship('Sample', secondary=usersample, backref=db.backref('users', lazy="dynamic")) families = db.relationship('Family', secondary=userfamily, backref=db.backref('users', lazy="dynamic")) # Login nickname = db.Column(db.String(), index=True, unique=True) # Complete user name completename = db.Column(db.String(), index=True, unique=True) theme = db.Column(db.String()) # User's email (not used for now) email = db.Column(db.String(), index=True, unique=True) # User's most loved pokemon!!! poke_id = db.Column(db.Integer()) # Password password = db.Column(db.String()) api_key = db.Column(db.String()) # Priv level privilege_level = db.Column(db.Integer()) # Flask-login related methods. All methods return True because multiple # logins are authorized. def get_id(self): return self.id def is_active(self): return True def is_authenticated(self): return True def __repr__(self): return '<User %r>' % (self.nickname)
class Sample(db.Model): """ Samples model. """ __tablename__ = 'sample' id = db.Column(db.Integer, primary_key=True) # N-N relationships family_id = db.Column(db.Integer, db.ForeignKey('family.id')) check_list = db.relationship('CheckList', secondary=sampletochecklist, backref=db.backref('samples', lazy='dynamic')) actions = db.relationship('IDAAction', secondary=sampletoactions, backref=db.backref('samples', lazy='dynamic')) yaras = db.relationship('YaraRule', secondary=sampletoyara, backref=db.backref('samples', lazy='dynamic')) # Enriched N-N relationships (double link) linked_samples = db.relationship('SampleMatch', backref=db.backref('sample1', remote_side=[id]), foreign_keys=[SampleMatch.sid_1]) linked_samples_2 = db.relationship('SampleMatch', backref=db.backref('sample2', remote_side=[id]), foreign_keys=[SampleMatch.sid_2]) # 1-N relationships strings = db.relationship( "StringsItem", backref=db.backref( 'sample', remote_side=[id])) s_metadata = db.relationship( "SampleMetadata", backref=db.backref( 'sample', remote_side=[id])) functions = db.relationship( "FunctionInfo", backref=db.backref( 'sample', remote_side=[id]), lazy="dynamic") filenames = db.relationship( "FileName", backref=db.backref( 'sample', remote_side=[id])) analysis_data = db.relationship( 'AnalysisResult', backref=db.backref( "sample", remote_side=[id])) # Sample's binary path storage_file = db.Column(db.String()) # File size size = db.Column(db.Integer()) # File's internal date (compilation timestamp, etc.) file_date = db.Column(db.DateTime(), index=True) # Hashes md5 = db.Column(db.String(32), index=True, nullable=False) sha1 = db.Column(db.String(40), index=True, nullable=False) sha256 = db.Column(db.String(64), index=True, nullable=False) # Mime type mime_type = db.Column(db.String()) full_mime_type = db.Column(db.String()) # Abstract, set by user abstract = db.Column(db.String()) # Import hash, set by tasks import_hash = db.Column(db.String(), index=True) # TLP level, mandatory TLP_sensibility = db.Column( db.Integer(), nullable=False, default=TLPLevel.TLPAMBER) # Analysis status analysis_status = db.Column( db.Integer(), nullable=False, default=AnalysisStatus.TOSTART) # Sample's analysis date analysis_date = db.Column(db.DateTime()) # "status" is not used, for now # status = db.Column(db.Integer()) def __repr__(self): return 'Sample %d' % self.id
class PEExport(db.Model): __tablename__ = 'peexport' id = db.Column(db.Integer(), primary_key=True) module_name = db.Column(db.String(), index=True) function_name = db.Column(db.String())