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
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})
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())
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})
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)
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))
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))
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
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})
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
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')
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)
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)
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()] })
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)