Beispiel #1
0
    def list(self, request):

        start = 0
        units = 100
        logical = False

        if request.query_params.get('addr'):
            start = int(request.query_params.get('addr'), 0)
        if request.query_params.get('units'):
            units = int(request.query_params.get('units'), 0)
        if request.query_params.get('logical'):
            logical = True  # TODO: Check this value for realz

        oda = OdaMaster.objects.get(
            short_name=request.query_params.get('short_name'),
            revision=request.query_params.get('revision'))

        dasm = Disassembler(oda.odb_file)
        dunits = dasm.display(start, units, logical)

        logger.debug("DisplayUnitsViewSet: Generate serialized data")
        serializer = self.get_serializer(dunits, many=True)
        serialData = Response(serializer.data)
        logger.debug("DisplayUnitsViewSet: Serial data complete")
        return serialData
Beispiel #2
0
    def makeFunction(self, request, pk):
        oda = OdaMaster.objects.get(short_name=request.data.get('short_name'),
                                    revision=request.data.get('revision'))

        error = None
        vma = 0
        if request.data.get('vma'):
            vma = request.data.get('vma')

        name = 'func_%x' % vma
        if request.data.get('name'):
            name = request.data.get('name')

        args = 'unknown'
        if request.data.get('args'):
            args = request.data.get('args')

        retval = 'unknown'
        if request.data.get('retval'):
            retval = request.data.get('retval')

        dasm = Disassembler(oda.odb_file)
        try:
            dasm.make_function(vma, name, args, retval)
            oda.save()
        except Exception as e:
            error = e.message
            return Response({'error': error},
                            status=status.HTTP_400_BAD_REQUEST)

        return Response({'function': name, 'error': error})
Beispiel #3
0
    def size(self, request, pk):
        oda = OdaMaster.objects.get(
            short_name=request.query_params.get('short_name'),
            revision=request.query_params.get('revision'))

        dasm = Disassembler(oda.odb_file)
        return Response(dasm.total_lines())
Beispiel #4
0
    def partial_update(self, request, pk):
        oda = OdaMaster.objects.get(short_name=request.data['short_name'],
                                    revision=request.data['revision'])

        error = None
        vma = None
        if request.data.get('vma'):
            vma = request.data.get('vma', 0)

        name = None
        if request.data.get('name'):
            name = request.data.get('name')

        args = None
        if request.data.get('args'):
            args = request.data.get('args')

        retval = None
        if request.data.get('retval'):
            retval = request.data.get('retval')

        dasm = Disassembler(oda.odb_file)
        try:
            dasm.edit_function(vma, name, args, retval)
            oda.save()
        except Exception as e:
            error = e.message
            return Response({'error': error},
                            status=status.HTTP_400_BAD_REQUEST)

        return Response({'function': name, 'error': error})
Beispiel #5
0
    def test_total_lines(self):
        odb_file = OdbFile(BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64'))
        odb_file.execute(LoadOperation())

        dasm = Disassembler(odb_file)
        total_lines = dasm.total_lines()

        self.assertEquals(41614, total_lines)
Beispiel #6
0
    def ldaToVma(self, request, pk):
        oda = OdaMaster.objects.get(
            short_name=request.query_params.get('short_name'),
            revision=request.query_params.get('revision'))

        lda = 0
        if request.query_params.get('lda'):
            lda = int(request.query_params.get('lda'), 0)

        dasm = Disassembler(oda.odb_file)
        return Response(dasm.lda_to_vma(lda))
Beispiel #7
0
    def vmaToLda(self, request, pk):
        oda = OdaMaster.objects.get(
            short_name=request.query_params.get('short_name'),
            revision=request.query_params.get('revision'))

        vma = 0
        if request.query_params.get('vma'):
            vma = int(request.query_params.get('vma'), 0)

        dasm = Disassembler(oda.odb_file)
        return Response(dasm.vma_to_lda(vma))
Beispiel #8
0
    def getNodes(self):

        dasm = Disassembler(self.odb_file)

        # convert _nodes to representation needed by front end
        nodes = []
        for startAddr, node in self._nodes.items():
            startLine = self.parcels.vma_to_lda(startAddr)
            endLine = self.parcels.vma_to_lda(startAddr + node.size)
            if endLine is None:
                endLine = self.parcels.sum_ldas()
            dus = dasm.display(startAddr, endLine - startLine, False)
            nodes.append({'id': node.id, 'instructions': dus})

        return nodes
Beispiel #9
0
    def makeCode(self, request, pk):
        oda = OdaMaster.objects.get(
            short_name=request.query_params.get('short_name'),
            revision=request.query_params.get('revision'))

        error = None
        vma = 0
        if request.query_params.get('vma'):
            vma = int(request.query_params.get('vma'), 0)

        dasm = Disassembler(oda.odb_file)
        try:
            dasm.make_code(vma)
        except Exception as e:
            raise OdaRestException(e)
        oda.save()

        return Response({'error': error})
Beispiel #10
0
def download_text_listing(request):
    # /odaweb/_download?short_name=strcpy_x86&revision=0
    short_name = request.GET[
        'short_name']  # oda_master.odb_file.get_binary().options.architecture
    revision = request.GET['revision']

    oda_master = OdaMaster.objects.get(short_name=short_name,
                                       revision=revision)

    dasm = Disassembler(oda_master.odb_file)
    text_listing = dasm.get_text_listing()
    if 'HTTP_USER_AGENT' in request.META:
        if 'windows' in request.META['HTTP_USER_AGENT'].lower():
            text_listing = text_listing.replace('\n', '\r\n')
    response = HttpResponse(text_listing, content_type='text')
    response[
        'Content-Disposition'] = 'attachment; filename="%s.txt"' % oda_master.project_name
    return response
Beispiel #11
0
def fileinfo(request):
    oda_master = get_session(request)
    if not oda_master:
        return HttpResponse("Session Not Initialized", status=400)

    binary = oda_master.binary
    dasm = Disassembler(binary)

    malware = False

    # lookup in malware hash registry
    try:
        [
            cymru_record,
        ] = dns.resolver.query('%s.malware.hash.cymru.com' % binary.md5(),
                               'TXT')
        malware = True
        logger.info('cymru is %s' % cymru_record)
    # if the name does not exist, this binary is not recognized as malware
    except dns.resolver.NXDOMAIN:
        pass
    # Timeout should not ever happen, but sometimes it does
    # TODO: Indicate to the user, that it is unknown
    except dns.resolver.Timeout:
        pass

    # lookup in national software reference library
    benign = False
    try:
        sock = socket.create_connection(('nsrl.kyr.us', 9120), timeout=0.5)
        sock.send('Version: 2.0\n')
        ack_ver = sock.recv(4096)
        sock.send('query %s\n' % binary.md5())
        ack_sum = sock.recv(4096)
        sock.send('BYE\n')
        if ack_ver.startswith('OK') and ack_sum.startswith('OK 1'):
            benign = True
        sock.close()
    except Exception:
        pass

    fileinfo_tab = render_to_string(
        'tab_fileinfo.djhtml', {
            'binary': binary,
            'malware': malware,
            'benign': benign,
            'project_name': oda_master.project_name,
        })

    # Return the new disassembly
    return HttpResponse(
        json.dumps({
            'fileinfo_tab': fileinfo_tab,
            # 'section_flags' : dasm.sectionFlagsInfo(),
        }),
        content_type='application/json')
Beispiel #12
0
    def list(self, request):

        try:
            bytes = self.request.query_params.get('bytes', None)
            oda = OdaMaster.objects.get(
                short_name=request.query_params.get('short_name'),
                revision=request.query_params.get('revision'))

            dasm = Disassembler(oda.odb_file)
            results = [{
                'addr': key,
                'section': value
            } for key, value in sorted(dasm.find(bytes).items(),
                                       key=lambda s: s[0])]
            serializer = self.get_serializer(results, many=True)

        except Exception as e:
            raise OdaRestException(e)

        return Response(serializer.data)
Beispiel #13
0
    def test_analyzer_output(self):
        odb_file = OdbFile(BinaryFile(self.get_test_bin_path('ls'), 'elf64-x86-64', 'i386:x86-64'))
        odb_file.execute(LoadOperation())
        odb_file.execute(PassiveScanOperation())

        dasm = Disassembler(odb_file)

        # Disassemble at a provided vma
        units = dasm.display(0x4095e0, 200, False)

        # The provided address should be the first instruction
        self.assertEquals(0x4095e0, units[0].vma)
        self.assertEquals("mov", units[0].opcode)

        # Another random instruction
        self.assertEquals("test", units[18].opcode)
        self.assertEquals("al,al", units[18].operands)

        # Disassemble at a provided negative vma
        units = dasm.display(0x4095e0, -10, False)

        # The provided address should be the last instruction
        self.assertEquals(0x4095e0, units[9].vma)
        self.assertEquals("mov", units[9].opcode)
        # IDA finds this one through a function pointer in data section
        # self.assertEquals(True, units[9].isFunction)

        # 9 instructions earlier
        self.assertEquals(0x4095BB, units[0].vma)
        self.assertEquals("call", units[0].opcode)

        # Disassemble a function
        units = dasm.display(0x40BEE0, 10, False)
        self.assertEquals(True, units[0].isFunction)

        # Cross Parcel Boundaries
        units = dasm.display(0x412BF4, -10, False)
        self.assertEquals(0x412BF4, units[9].vma)
        self.assertEquals("ret", units[9].opcode)
        self.assertEquals(".fini", units[9].section_name)
        self.assertEquals(0x412BE1, units[2].vma)
        self.assertEquals("jmp", units[2].opcode)
        self.assertEquals(".text", units[2].section_name)

        # Cross Code/Data Boundaries
        units = dasm.display(0x412BF4, 10, False)
        self.assertEquals(0x412BF4, units[0].vma)
        self.assertEquals(0x412C00, units[1].vma)
        self.assertEquals(1, units[1].dataSize)
Beispiel #14
0
    def get(self, request):
        short_name = request.query_params.get('short_name')
        revision = request.query_params.get('revision', 0)
        oda = OdaMaster.objects.get(short_name=short_name, revision=revision)
        odb_file = oda.odb_file
        binary = oda.odb_file.get_binary()
        sym_dict = {
            sym.vma: sym
            for sym in odb_file.get_structure_list(Symbol) if (sym.vma != 0)
        }

        branches = odb_file.get_structure_list(Branch)

        live_mode = isinstance(binary, BinaryString)

        symbols = sym_dict.values()

        parcels = sorted(odb_file.get_structure_list(Parcel),
                         key=lambda p: p.vma_start)

        sections = filter(lambda s: s.is_loadable(),
                          odb_file.get_structure_list(Section))

        dasm = Disassembler(odb_file)
        size = dasm.total_lines()

        # Include the built in types
        builtins = [field() for field in BuiltinTypes()]

        # Include c_structs too
        cstructs = odb_file.get_structure_list(CStruct)
        fieldTypes = sorted(builtins + cstructs,
                            key=lambda s: type(s).__name__)

        binary_text = 'N/A'
        if live_mode:
            binary_text = binary.binary_string_display

        return Response({
            'project_name':
            oda.project_name,
            'binary': {
                'size': int(str(binary.size)),
                'md5': str(binary.md5()),
                'sha1': str(binary.sha1()),
                'desc': binary.desc(),
                'name': binary.name,
                'malware': False,  # str(lookup_malware(binary)),
                'benign': True,  # str(lookup_benign(binary)),
                'text': binary_text,
                'options': {
                    'architecture': binary.options.architecture,
                    'base_address': binary.options.base_address,
                    'endian': binary.options.endian,
                    'selected_opts': binary.options.selected_opts
                }
            },
            'live_mode':
            live_mode,
            'functions': [
                FunctionSerializer(x).data
                for x in odb_file.get_structure_list(Function)
            ],
            'labels': [
                LabelSerializer(x).data
                for x in odb_file.get_structure_list(Label)
            ],
            'sections':
            SectionSerializer(sections, many=True).data,
            'parcels': [ParcelSerializer(x).data for x in parcels],
            'comments': [
                CommentSerializer(x).data
                for x in odb_file.get_structure_list(Comment)
            ],
            'symbols': [SymbolSerializer(x).data for x in symbols],
            'branches': [BranchSerializer(x).data for x in branches],
            'default_permission_level':
            oda.default_permission_level().name,
            'strings': [
                DataStringSerializer({
                    'string': x.value,
                    'addr': x.addr
                }).data for x in odb_file.get_structure_list(DataString)
            ],
            'structTypes': [
                CStructSerializer(x).data
                for x in odb_file.get_structure_list(CStruct)
            ],
            'structFieldTypes':
            [CStructFieldTypeSerializer(x).data for x in fieldTypes],
            'displayUnits': {
                "size": size
            },
            #TODO Move these elsewhere
            'user':
            UserSerializer(request.user).data,
            'architectures':
            get_supported_archs(),
            'endians': [{
                'name': x,
                'intValue': y
            } for x, y in get_supported_endians().items()]
        })
Beispiel #15
0
def upload(request):
    form = UploadFileForm(request.POST, request.FILES)
    status = 200
    filename = 'unknown'
    if 'filedata' in request.FILES:
        filename = request.FILES['filedata'].name
    if form.is_valid():

        project_name = form.cleaned_data['project_name']
        default_sharing_level = OdaMasterPermissionLevel[
            form.cleaned_data['default_sharing_level']]

        filedata = form.cleaned_data['filedata']

        idbImport = IdbImport(filedata)
        if idbImport.is_idb():
            binary_file = BinaryFile.create_from_idb(filedata)
            binary_file.save()
            arch, target = idbImport.guess_arch()
            description = idbImport.describe()
        else:
            binary_file = BinaryFile.create(filedata)
            binary_file.save()
            description = binary_file.desc()
            arch, target = Disassembler.guess_bfd_arch(
                binary_file.file_handle().name)

        oda_master = OdaMaster(short_name=id_generator(),
                               project_name=project_name,
                               default_permission=default_sharing_level.value,
                               ipAddress=request.META.get('REMOTE_ADDR'))
        if request.user.is_authenticated():
            oda_master.owner = request.user

        oda_master.save()

        request.session["disassembly_id"] = oda_master.short_name
        request.session["disassembly_token"] = {
            'id': oda_master.short_name,
            'version': 0
        }

        binary_file.binary_options.architecture = arch
        binary_file.binary_options.target = target
        binary_file.binary_options.save()

        odb_file = OdbFile(BinaryFileModel(binary_file.id))

        # todo this should not be saved until after user has committed options
        oda_master.odb_file = odb_file

        oda_master.save()

        data = {
            'short_name': oda_master.short_name,
            'revision': oda_master.revision,
            'arch': arch,
            'target': target,
            'file_format': description,
        }
    else:
        status = 413
        data = {
            'error':
            'Invalid File "%s", maximum size is %d kb' %
            (filename, UploadFileForm.MAX_UPLOAD_SIZE_KB)
        }

    return HttpResponse(json.dumps(data),
                        content_type='application/json',
                        status=status)