2019-02-18 05:28:05 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
from datetime import datetime
|
2019-02-19 04:40:35 +00:00
|
|
|
from hashlib import sha1
|
|
|
|
from pathlib import Path
|
|
|
|
from sqlalchemy import LargeBinary, Column, ForeignKey, Integer, String, DateTime, create_engine
|
2019-02-18 05:28:05 +00:00
|
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
|
|
from sqlalchemy.orm import Session, relationship, backref
|
|
|
|
from sqlalchemy.orm.collections import attribute_mapped_collection
|
2019-02-20 23:32:34 +00:00
|
|
|
import json
|
2019-02-18 05:28:05 +00:00
|
|
|
|
2019-02-20 23:32:34 +00:00
|
|
|
from .disassemble import disasm
|
2019-02-18 05:28:05 +00:00
|
|
|
|
2019-02-20 23:32:34 +00:00
|
|
|
now = '{0:%Y%m%dT%H%M%S}'.format(datetime.utcnow())
|
2019-02-18 05:28:05 +00:00
|
|
|
Base = declarative_base()
|
|
|
|
|
2019-02-19 23:04:45 +00:00
|
|
|
|
2019-02-19 04:40:35 +00:00
|
|
|
def db_config(path: Path) -> Session:
|
|
|
|
engine = create_engine(f'sqlite:///{path.resolve()}', native_datetime=True)
|
|
|
|
Base.metadata.create_all(engine)
|
|
|
|
session = Session(engine)
|
|
|
|
return session
|
2019-02-18 05:28:05 +00:00
|
|
|
|
2019-02-19 23:04:45 +00:00
|
|
|
|
2019-02-19 04:40:35 +00:00
|
|
|
class ScrapNode(Base):
|
|
|
|
__tablename__ = 'scrap_node'
|
2019-02-18 05:28:05 +00:00
|
|
|
ctime = Column(DateTime, default=datetime.utcnow)
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
|
|
length = Column(Integer, default=0)
|
|
|
|
mtime = Column(DateTime, onupdate=datetime.utcnow)
|
|
|
|
parent_id = Column(Integer, ForeignKey(id))
|
|
|
|
checksum = Column(String)
|
2019-02-20 23:32:34 +00:00
|
|
|
disasm = Column(String)
|
2019-02-19 04:40:35 +00:00
|
|
|
image = Column(LargeBinary)
|
2019-02-18 05:28:05 +00:00
|
|
|
|
|
|
|
children = relationship(
|
2019-02-19 04:40:35 +00:00
|
|
|
"ScrapNode",
|
2019-02-18 05:28:05 +00:00
|
|
|
cascade="all, delete-orphan",
|
|
|
|
backref=backref("parent", remote_side=id),
|
|
|
|
collection_class=attribute_mapped_collection('name'))
|
|
|
|
|
2019-02-19 04:40:35 +00:00
|
|
|
def __init__(self, *, child: bytes, parent_id: int = None):
|
|
|
|
self.parent_id = parent_id
|
2019-02-18 05:28:05 +00:00
|
|
|
self.image = child
|
|
|
|
self.length = len(child)
|
2019-02-19 04:40:35 +00:00
|
|
|
self.sha1sum
|
2019-02-20 23:32:34 +00:00
|
|
|
self.disasm = disasm(child)
|
2019-02-19 04:40:35 +00:00
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
values = {
|
|
|
|
'checksum': self.checksum,
|
|
|
|
'length': self.length,
|
2019-02-20 23:32:34 +00:00
|
|
|
'disasm': self.disasm,
|
2019-02-19 04:40:35 +00:00
|
|
|
'parent_id': self.parent_id,
|
2019-02-19 22:56:11 +00:00
|
|
|
'id': self.id,
|
2019-02-19 04:40:35 +00:00
|
|
|
}
|
|
|
|
|
2019-02-20 23:32:34 +00:00
|
|
|
return json.dumps(values, indent=1)
|
2019-02-18 05:28:05 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def sha1sum(self):
|
|
|
|
if self.checksum:
|
|
|
|
return self.checksum
|
|
|
|
|
|
|
|
checksum = sha1()
|
|
|
|
checksum.update(self.image)
|
|
|
|
self.checksum = checksum.hexdigest()
|
|
|
|
|
|
|
|
return self.checksum
|
2019-02-20 23:32:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
def disasm(shellcode: bytes) -> str:
|
|
|
|
opcodes = list()
|
|
|
|
|
|
|
|
for opcode in capstone.disasm(shellcode, 0):
|
|
|
|
opcodes += f'{opcode.mnemonic} {opcode.op_str}\n'
|
|
|
|
|
|
|
|
return opcodes
|