Authenticating location result - android

I have developed a location based service which identifies the location of the user using GPS. I want to authenticate the data from GPS because an attacker can spoof location information with a simulator.
I've studied an authenticating mechanism from here, but i don't know how to implement the technique they have mentioned.

The idea of the paper is to retrieve geolocation from two different providers. In your case you'd get the device's GPS position for high accuracy and the cell id position to validate this data.
Here's a full example how to get locations by cell id: http://www.devx.com/wireless/Article/40524
You need to define a threshold for the difference of these locations. So we believe the GPS location is faked when the distance between GPS and cellular is greater than our threshold.
Some abstract code example:
static final int THRESHOLD = 2000 // maximum discrepancy in meters
Location getLocationFromGPS();
Location getCellularLocation();
boolean isLocationValid(Location gps) {
Location cell = getCellularLocation();
return gps.distanceTo(cell) <= THRESHOLD;
}
Following this approach there can be two different types of mistakes:
assuming the GPS data is faked but it is not
trust the GPS data while it's faked
Setting small values for THRESHOLD will more and more lead to mistake #1. Most of all users will never fake their GPS data, so claiming they're cheaters won't make your app successful ;-)
The paper states that the Cellular Network Based accuracy is about 100 - 1500 meters. So I highly recommend you to choose values greater than 1500 meters.
Please mind that - as Rune FS mentioned - advanced users may fake both location providers at the same time.

Related

How does Apple or Android calculate speed in devices?

There are any documentation for this? I've checked many formulas and algorithms but didn't find an explicit definition how they get the speed provided in Geolocation object.
The GPS chipset provides the current velocity to the system along with the current location.
The chipset may compute the velocity by comparing location over time and correcting for the curvature of the Earth at the current location, or from the Doppler shift of the received satellite signals.
Whichever method is used, the operating system doesn’t need to do any processing to get the speed. The velocity data is provided along with location and altitude data directly from the GPS chip (actually chips in many newer devices support both GPS and GLONASS, but which system is used is not visible to the user).
Physics.org has a simple explanation of how GPS works
Wherever you are on the planet, at least four GPS satellites are ‘visible’ at any time. Each one transmits information about its position and the current time at regular intervals. These signals, travelling at the speed of light, are intercepted by your GPS receiver, which calculates how far away each satellite is based on how long it took for the messages to arrive.
Once it has information on how far away at least three satellites are, your GPS receiver can pinpoint your location using a process called trilateration.
But you can search for more detailed explanations of the mathematics and physics involved.
It basically scans your location (i.e. your latitude and longitude) and compares with the last check. Using euclidian distance, it can get the distance in the period of time. With the time (for example, if it scans your location every 2 seconds), it can easily estimate your speed by doing Speed = Distance/2.

How does some apps(wechat) ignore fake location and then detect the real one?

I have installed a fake location app and set my location different. Then opened Google Maps and Wechat app,
Google Maps shows my location as what i set(fake)
Wechat app ignores fake location and detects real location (how?)
Then i wanted to prevent wechat analyze my previously received real locations and new fake location.
Uninstalled Wechat
Restarted my device
Set my location as fake
Installed Wechat again
But same result, it detects my real location.
I really want to understand how they do this. Any ideas?
What i have tried
Gps provider spoof
Network provider spoof
Fused location provider spoof
IP geolocation spoof
Gps provider spoof + IP geolocation spoof
UPDATE
Uses GPS even when disabled.
07-02 11:46:15.504 2346-2356/? D/LocationManagerService: request 434a7e28 gps Request[ACCURACY_FINE gps requested=+1s0ms fastest=+1s0ms] from com.tencent.mm(10173)
CONCLUSION
You can fake location on older versions of wechat(lower than 6.0)
Uses something like BaiduLocationSDK. It's not affected from any mock attempt through LocationManager and Fused provider.
I'm not sure but, seems like BaiduLocationSDK uses GPS through hardware level.
To check for fake location most applications look for GGA and GSV sentences in the NMEA (National Marine Electronics Association) data received by them. The fake location providers do not send NMEA sentences along with location, so this parameter can be used to If they haven't received and GGA and GSV sentences in a threshold amount of time, say 100 seconds they red flag the current location provider.
This process is repeated till a valid set of NMEA sentences has been received and then the corresponding location is selected.
To retreive NMEA data LocationManager#addNmeaListener(GpsStatus.NmeaListener listener) is called and then in the listener
void onNmeaReceived(long timestamp, String nmea) {
Log.d("Nmea Data",nmea);
}
for more info see adding a NmeaListener
the NMEA sentences, GGA and GSV look as follows
GGA - essential fix data which provide 3D location and accuracy data.
Sample : "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"
Where:
GGA Global Positioning System Fix Data
123519 Fix taken at 12:35:19 UTC
4807.038,N Latitude 48 deg 07.038' N
01131.000,E Longitude 11 deg 31.000' E
1 Fix quality: 0 = invalid
1 = GPS fix (SPS)
2 = DGPS fix
3 = PPS fix
4 = Real Time Kinematic
5 = Float RTK<br/>
6 = estimated (dead reckoning) (2.3 feature)
7 = Manual input mode>
8 = Simulation mode
08 Number of satellites being tracked
0.9 Horizontal dilution of position
545.4,M Altitude, Meters, above mean sea level
46.9,M Height of geoid (mean sea level) above WGS84 ellipsoid
(empty field) time in seconds since last DGPS update
(empty field) DGPS station ID number
*47 the checksum data, always begins with *
GSV - Satellites in View shows data about the satellites that the unit might be able to find based on its viewing mask and almanac data. It also shows current ability to track this data. Note that one GSV sentence only can provide data for up to 4 satellites and thus there may need to be 3 sentences for the full information. It is reasonable for the GSV sentence to contain more satellites than GGA might indicate since GSV may include satellites that are not used as part of the solution. It is not a requirement that the GSV sentences all appear in sequence. To avoid overloading the data bandwidth some receivers may place the various sentences in totally different samples since each sentence identifies which one it is.
Sample:"$GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75"
Where:
GSV Satellites in view
2 Number of sentences for full data
1 sentence 1 of 2
08 Number of satellites in view
01 Satellite PRN number
40 Elevation, degrees
083 Azimuth, degrees
46 SNR - higher is better
for up to 4 satellites per sentence
*75 the checksum data, always begins with *
Source : NMEAData
Some 3rd party location sdk like BaiduLocationSDK doesn't reflect the fake location setup by system.
It's for safety purpose.
The reason I was asking the questions in the comments is that I was hoping you tested how Wechat responds to different conditions.
There are a couple of other ways to detect device location which TestProvider shouldn't affect AFAIK. This needs testing but here are some ideas:
LocationManager.getLastKnownLocation(String provider) - this allows you to force using for example a GPS provider and get cached data.
GPS NMEA listener, and a new one in API 24 - these APIs allow listening for low-level events from GPS hardware using NMEA 0183 protocol.
IP address geolocation.
You can get country-level geolocation via Telephony Manager.
Edit: added Telephony manager option.
#Bona Fide
Then you can remove the TestProvider from the LocationManager and get
the actual location.
Even wechat would use this approach before requesting location updates, to avoid providers being spoofed by other applications, like something below
// HERE WECHAT APP
// WECHAT REMOVES THEM IF ANY (just supposition)
locationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
locationManager.removeTestProvider(LocationManager.NETWORK_PROVIDER);
// WECHAT REQUESTING LOCATION UPDATES
// ....
So this approach causes throwing a IllegalArgumentException on the location faker app. Even in that case, i can easily handle this issue and continue spoofing GPS and NETWORK providers again,
// HERE LOCATION FAKER APP
// LOCATION FAKER APP SETS FAKE LOCATIONS
while (mRunning){
try {
locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, gpsLocation);
} catch (IllegalArgumentException e){
locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, false, false, false, false, true, true, 1, 1);
locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);
}
try {
locationManager.setTestProviderLocation(LocationManager.NETWORK_PROVIDER, networkLocation);
} catch (IllegalArgumentException e){
locationManager.addTestProvider(LocationManager.NETWORK_PROVIDER, false, false, false, false, false, true, true, 1, 1);
locationManager.setTestProviderEnabled(LocationManager.NETWORK_PROVIDER, true);
}
gpsLocation.setTime(System.currentTimeMillis());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
gpsLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
networkLocation.setTime(System.currentTimeMillis());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
networkLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
try {
Thread.sleep(500);
} catch (Exception e) {}
}
Everything works perfectly but out of WECHAT
Fake locations are possible if ALLOW_MOCK_LOCATION is set and a TestProvider is added to the LocationManager. To get the real location you need to do these two steps:
Detect if MockSettings are enabled and whether there are Apps installed how could fake the location.
Then you can remove the TestProvider from the LocationManager and get the actual location.
Checkout Jambaaz answer to get an example how this works in code.
Note: To remove an TestProvider you need the Permission android.permission.ACCESS_MOCK_LOCATION and ALLOW_MOCK_LOCATION is now deprecated since API 23. You can now check if the Location is from a TestProvider directly from Location.isFromMockProvider()
I have managed to spoof location with wechat and zalo, both seem just as difficult.
I would load a mock location and fake gps app. set my location. check maps and see it's correct, can even move around the world and it's working.
But wechat and zalo don't agree, they say I am in my basement lol.
THEN I uninstall fake gps app (might be able to force stop and disable) and go to wechat and clear location etc and try again and often it will move me to faked gps location. It won't stay that way after closing the wechat app though. it is temporary.
It might not be easy to do but might give someone a hint or path to look at.

How to accuratly find other Android users within a radius of 200ft ( How did Color do it?)

I'm working on a app which requires that a device with this app installed will automatically find other users within a maximum radius of 200ft (worst case scenario 300ft, but that's pushing it) and/or a minimum radius of 40ft.
Ive tried the obvious solution of using GPS and a MYSQL query that query's our location table for other users within the 200ft radius, but as you probably would guess this is not incredibly accurate and if the device uploads coordinates that are off by over 200ft the server will return a list of users that are not within proximity. While I would prefer to just get the app to work the way it was meant to I'd rather the server return no users than false positives.
I know there's probably no simple way to do it accurately, but what other options do I have? And how did Color manage to do it? With all the tech in the avg smartphone and all the location based apps this has to be possible to do.
200ft (60m) is no Problem for GPS. Usually GPS is below 10m.
You even have a location.getAccuracy() method which you should evaluate
Just use GPS as your only location source. do not use cell tower location provider, when you want accuracy < 60m.
Of course inside a building, when you are sitting at your desktop GPS will not work, or is off by 60m.
GPS needs a view to open sky not obstructed (by dense materials).
Take a look at this question:
how to get the most accurate location using GPS and AGPS with given time in android?
Basically it depends on the phone's GPS and the current environment. Besides that, there's probably nothing you can do to further boost the location accuracy other than using GPS.

Does Location#distanceTo(Location) take Location#getAccuracy() into account?

I want to write a LocationListener that takes the most accurate and precise recent location as its location. I'm intending to use this code in my LocationListener:
#Override
public void onLocationChanged(Location location) {
if(location.distanceTo(mLocation)>location.getAccuracy()){
mLocation = location;
}
}
What I intend this to do is update the location if the user's old location is outside the circle of "possible locations" that the new location indicates. So, for example, if our last measurement was a GPS signal and the new one is a cell tower, and the old location was in range of the cell tower, we don't update; on the other hand, if the cell tower is sufficiently distant, we know the user has moved and record that.
However, the distanceTo(Location) function states it returns the approximate distance in metres between locations. Does it already take the accuracy into account? Will it give me a precise enough figure to let me use in this way?
Short answer is no, Location.distanceTo(Location) does not take Location.getAccuracy() value into account when measuring distance.
Here's the actual code from the Android platform that is used to calculate distance for Location.distanceTo(Location):
https://github.com/android/platform_frameworks_base/blob/master/location/java/android/location/Location.java#L272
It uses Vincenty's Inverse Formula (http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf - Section 4) based on the given latitude and longitude (accuracy not considered).
As to whether your method of updating the "true" user location will be "precise enough", it really depends on GPS sensitivity, accuracy, and precision, which can vary significantly from device to device.
The accuracy estimate value from Location.getAccuracy() can also vary widely depending on the OEM, and typically devices I've seen overestimate accuracy (i.e., the device gives an accuracy value greater than the true accuracy) more than underestimate accuracy.
You might want to check out an app I created "GPS Benchmark" (http://www.gpsbenchmark.com/) which helps quickly benchmark location provider accuracy (GPS and Network) on Android devices, as well as "estimated accuracy" accuracy. I also co-authored a paper on this topic (http://journals.cambridge.org/repo_A82eaJIy) based on GPS benchmarking results from some Java ME devices, and most of the material is also relevant to Android.

Getting multiple NETWORK_PROVIDER from LocationManager

How does LocationManager choose which NETWORK_PROVIDER to use when getting location data? I would like to be able to identify the providers that LocationManager selects the NETWORK_PROVIDER from.
For example, there are two nearby NETWORK_PROVIDER locations, X (close) and Y (not as close). When standing in a single spot, sometimes the NETWORK_PROVIDER will be X, sometimes Y. I assume that the location with the highest accuracy gets returned (which is why usually X is returned), and all other networks are ignored, but I would like to return a list of all the nearby networks (or at least the top 2 or 3) at the same time.
Any of the .getProvider() methods (as far as I know) return the type of the provider (network, gps, passive), but nothing to actually identify the provider. When the location is returned, the location data is unique for the providers, but cannot be used to choose providers. I can get data from X, but I can't tell the program to ignore X (or can I?).
Anyway to make this happen? To return a list or array of NETWORK_PROVIDERS and then step through them getting location data?
And no, using GPS_PROVIDER is not an acceptable answer, because I need NETWORK_PROVIDER data only.
This answer is not based on any evidence, but rather my understanding of how the location provider works. When you request NETWORK_PROVIDER, you're basically asking it to give you the location that they estimate based on all the information that is available. For example, you might have 3 wifi networks and 2 cell towers, and that info is sent up to a server on the internet. Using that info, they calculate where they think you are, and return that to you. So, in other words, the network_provider location is based on the sum of all wifi/cell-tower info available to your phone.
Individually, a wifi hotspot doesn't tell you too much about where you are. A cell tower gives you some location info, but you'll need a few sources to accurately triangulate your location. Also, note that you need a internet/data connection, since the location is determined by some server, and not done on your phone. This is because knowing the nearby wifi hotspots (more specifically the MAC addresses) is useless without a database that maps each hotspot to it's physical location.

Categories

Resources