मॉक लोकेशन के लिए अक्षम / चेक करें (जीपीएस स्पूफिंग को रोकें)


90

एंड्रॉइड पर जीपीएस स्पूफिंग को रोकने / पता लगाने का सबसे अच्छा तरीका खोजना। यह कैसे पूरा होता है, इस पर कोई सुझाव और इसे रोकने के लिए क्या किया जा सकता है? मैं अनुमान लगा रहा हूं कि उपयोगकर्ता को GPS को बिगाड़ने के लिए नकली स्थानों को चालू करना होगा, यदि ऐसा किया जाता है, तो वे GPS को खराब कर सकते हैं?

मुझे लगता है कि मुझे पता लगाने की आवश्यकता होगी कि क्या मॉक लोकेशन सक्षम हैं? कोई अन्य सुझाव?


2
मुझे लगता है कि वह ग्रहण में डीडीएमएस दृश्य में उपलब्ध स्थान स्पूफिंग फ़ंक्शन के बारे में पूछ रहा है।
शॉन वाल्टन

2
मेरे पास एक स्थान आधारित गेम है, जिसे मैं लोगों को धोखा नहीं देना चाहता, इसलिए मैं स्पूफिंग को ब्लॉक करना चाहता हूं, मेरी समझ यह है कि यह दो तरीकों में से एक हो सकता है .. नकली स्थानों को सक्षम करने और एक कस्टम छवि बनाने में जो निम्न स्तर का स्पूफिंग करता है और सेटिंग ऐप में स्पूफिंग सेटिंग की उपेक्षा करता है। MockLocations के लिए Settings.System प्रदाता को खोजने की कोशिश कर रहा है, या यह देखने के लिए देख रहा है कि क्या यह सक्षम है (ऐप के बीच में श्रोता के साथ)।
क्रिसपिक्स

जवाबों:


125

मैंने कुछ जांच की है और अपने परिणामों को यहाँ साझा किया है, यह दूसरों के लिए उपयोगी हो सकता है।

सबसे पहले, हम जाँच सकते हैं कि क्या MockSetting विकल्प चालू है

public static boolean isMockSettingsON(Context context) {
    // returns true if mock location enabled, false if not enabled.
    if (Settings.Secure.getString(context.getContentResolver(),
                                Settings.Secure.ALLOW_MOCK_LOCATION).equals("0"))
        return false;
    else
        return true;
}

दूसरा, हम जांच सकते हैं कि क्या डिवाइस में अन्य एप्लिकेशन हैं, जो उपयोग कर रहे हैं android.permission.ACCESS_MOCK_LOCATION(स्थान स्पूफिंग ऐप्स)

public static boolean areThereMockPermissionApps(Context context) {
    int count = 0;

    PackageManager pm = context.getPackageManager();
    List<ApplicationInfo> packages =
        pm.getInstalledApplications(PackageManager.GET_META_DATA);

    for (ApplicationInfo applicationInfo : packages) {
        try {
            PackageInfo packageInfo = pm.getPackageInfo(applicationInfo.packageName,
                                                        PackageManager.GET_PERMISSIONS);

            // Get Permissions
            String[] requestedPermissions = packageInfo.requestedPermissions;

            if (requestedPermissions != null) {
                for (int i = 0; i < requestedPermissions.length; i++) {
                    if (requestedPermissions[i]
                        .equals("android.permission.ACCESS_MOCK_LOCATION")
                        && !applicationInfo.packageName.equals(context.getPackageName())) {
                        count++;
                    }
                }
            }
        } catch (NameNotFoundException e) {
            Log.e("Got exception " , e.getMessage());
        }
    }

    if (count > 0)
        return true;
    return false;
}

यदि उपरोक्त दोनों विधियाँ, प्रथम और द्वितीय सत्य हैं, तो इस बात की अच्छी संभावना है कि स्थान ख़राब या नकली हो सकता है।

अब, स्थान प्रबंधक के API का उपयोग करके स्पूफिंग से बचा जा सकता है।

हम दोनों प्रदाताओं (नेटवर्क और जीपीएस) से स्थान अपडेट का अनुरोध करने से पहले परीक्षण प्रदाता को हटा सकते हैं

LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);

try {
    Log.d(TAG ,"Removing Test providers")
    lm.removeTestProvider(LocationManager.GPS_PROVIDER);
} catch (IllegalArgumentException error) {
    Log.d(TAG,"Got exception in removing test  provider");
}

lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, locationListener);

मैंने देखा है कि removeTestProvider (~) जेली बीन और उसके बाद के संस्करण पर बहुत अच्छी तरह से काम करता है। यह एपीआई आइसक्रीम सैंडविच तक अविश्वसनीय दिखाई दिया।


बहुत ही रोचक अवलोकन। इसे साझा करने के लिए विशेष रूप से अंतिम एक +1।
अर-जी

2
RemoveTestProvider विधि के बारे में ध्यान दें। यदि आप स्थान प्रबंधक को पृष्ठभूमि में काम करने की अनुमति देते हैं तो उपयोगकर्ता मॉक ऐप पर जा सकता है और मॉकिंग स्थान को पुनः आरंभ कर सकता है। आपका स्थान प्रबंधक तब तक नकली स्थानों को प्राप्त करना शुरू कर देगा, जब तक कि आप फिर से removeTestProvider को कॉल न करें।
तैमूर_सी

4
साथ ही आपके ऐप को काम करने की android.permission.ACCESS_MOCK_LOCATIONअनुमति होनी चाहिए removeTestProvider, जो मुझे लगता है कि सबसे बड़ा नुकसान है।
तैमूर_सी

18
जवाब के लिए धन्यवाद! सिर्फ एक बिंदु: Android 6.0 ALLOW_MOCK_LOCATION में पदावनत किया गया है। और वास्तव में नकली स्थान के लिए कोई चेकबॉक्स भी नहीं है। एक देख सकते हैं कि स्थान स्थान वस्तु से सही नकली है या नहीं: location.isFromMockProvider ()
Silwester

2
@ ब्लेककारा मैंने इसका इस्तेमाल नहीं किया। मैं के एक अनुकूलित संयोजन का इस्तेमाल किया isMockSettingsON(), Location.isFromMockProvider()और areThereMockPermissionApps()क्षुधा की एक काली सूची के साथ। ACCESS_MOCK_LOCATION अनुमति के साथ कई प्रीइंस्टॉल्ड सिस्टम ऐप हैं , उदाहरण के लिए एचटीसी और सैमसंग डिवाइस। सभी वैध ऐप्स का श्वेतसूची बेहतर होगा, लेकिन सबसे लोकप्रिय स्थान स्पूफिंग ऐप्स की एक काली सूची ने मेरे मामले में अच्छा काम किया। और मैंने यह भी जांचा कि क्या डिवाइस रूट किया गया था।
तैमूर_का

45

एपीआई 18 के बाद से, ऑब्जेक्ट स्थान में विधि है .isFromMockProvider () ताकि आप नकली स्थानों को फ़िल्टर कर सकें।

यदि आप 18 से पहले के संस्करणों का समर्थन करना चाहते हैं, तो इस तरह से कुछ का उपयोग करना संभव है:

boolean isMock = false;
if (android.os.Build.VERSION.SDK_INT >= 18) {
    isMock = location.isFromMockProvider();
} else {
    isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
}

मुझे पूरा यकीन है कि आपकी दूसरी अभिव्यक्ति पीछे की ओर है (जब वह झूठी वापस आनी चाहिए तो सच होगी)। मुझे लगता है कि यह होना चाहिए:isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
AjahnCharles

3
आपका स्वागत है। अधिक आधुनिक उत्तर पोस्ट करने के लिए धन्यवाद! वास्तव में यह आज के अनुसार सही उत्तर है।
अजानचार्ल्स

1
हम एसडीके के लिए 18 से ऊपर "स्थान" ऑब्जेक्ट के बिना कैसे कर सकते हैं?
अजीत शर्मा

35

ऐसा लगता है कि ऐसा करने का एकमात्र तरीका लोकल स्पोकिंग को रोकने के लिए मॉकक्लोशंस को रोकना है। नीचे की ओर कुछ उपयोगकर्ता हैं जो बेहतर संकेत प्राप्त करने के लिए ब्लूटूथ जीपीएस डिवाइस का उपयोग करते हैं, वे ऐप का उपयोग नहीं कर पाएंगे क्योंकि उन्हें मॉक स्थानों का उपयोग करना आवश्यक है।

ऐसा करने के लिए, मैंने निम्नलिखित कार्य किया:

// returns true if mock location enabled, false if not enabled.
if (Settings.Secure.getString(getContentResolver(),
       Settings.Secure.ALLOW_MOCK_LOCATION).equals("0")) 
       return false; 
       else return true;

4
हालांकि यह मूर्खतापूर्ण सबूत नहीं है। गैर-रूट किए गए डिवाइस पर उपयोगकर्ता अभी भी भविष्य में एक मॉक लोकेशन, w / टाइम सेट कर सकते हैं, फिर मॉक लोकेशन को डिसेबल कर सकते हैं, और मॉक लोकेशन अभी भी सक्रिय है। इससे भी बदतर, वे नकली स्थान को एक ही प्रदाता का नाम नेटवर्क / जीपीएस कह सकते हैं और यह स्पष्ट रूप से उसी से खींचता है ..
क्रिसपिक्स

3
इसके अलावा, फेक जीपीएस को रूट किए गए डिवाइस पर मॉक लोकेशन सेटिंग की आवश्यकता नहीं होती है।
पॉल लामार्ट्समा

हमेशा यह सत्यापित करने के लिए जांच कर सकता है कि नकली.जीपीएस ऐप स्थापित नहीं है :)
क्रिसपिक्स

11
आप उपयोग कर सकते हैं return !xके बजाय if(x) return false; else return true
कोडइन्चोस

वास्तव में, नकली स्थान रूट किए गए उपकरणों पर भी नकली स्थान सेटिंग को बदल देगा।
PageNotFound 13

25

कुछ साल बाद इस धागे पर ठोकर लगी। 2016 में, अधिकांश एंड्रॉइड डिवाइसों में एपीआई स्तर> = 18 होगा और इस प्रकार फर्नांडो द्वारा बताए गए स्थान पर भरोसा करना चाहिए ।isFromMockProvider ()

मैंने बड़े पैमाने पर विभिन्न एंड्रॉइड डिवाइस और डिस्ट्रो पर नकली / नकली स्थानों के साथ प्रयोग किया। दुर्भाग्य से .isFromMockProvider () 100% विश्वसनीय नहीं है। हर एक बार एक नकली स्थान को नकली के रूप में लेबल नहीं किया जाएगा । ऐसा लगता है कि Google स्थान API में कुछ गलत आंतरिक संलयन तर्क के कारण है।

मैंने इस बारे में एक विस्तृत ब्लॉग पोस्ट लिखी , यदि आप और अधिक सीखना चाहते हैं। संक्षेप में बताने के लिए, यदि आप स्थान एपीआई से स्थान अपडेट की सदस्यता लेते हैं, तो एक नकली जीपीएस ऐप पर स्विच करें और प्रत्येक स्थान का परिणाम प्रिंट करें। स्ट्रिंग () कंसोल पर, आपको कुछ इस तरह दिखाई देगा:

यहाँ छवि विवरण दर्ज करें

ध्यान दें कि कैसे, स्थान अपडेट की धारा में, एक स्थान में अन्य लोगों के समान निर्देशांक होते हैं, लेकिन मॉक के रूप में चिह्नित नहीं किया जाता है और इसमें बहुत कम स्थान सटीकता होती है।

इस समस्या को हल करने के लिए, मैं एक उपयोगिता वर्ग ने लिखा है कि होगा सभी आधुनिक Android संस्करण (एपीआई स्तर 15 और ऊपर) भर में मज़बूती से दबाने कृत्रिम स्थान:

LocationAssistant - Android पर परेशानी रहित स्थान अपडेट

मूल रूप से, यह गैर-नकली स्थानों को "अविश्वास" करता है जो अंतिम ज्ञात नकली स्थान के 1 किमी के भीतर हैं और उन्हें एक नकली के रूप में लेबल करता है। यह तब तक करता है जब तक कि महत्वपूर्ण संख्या में गैर-नकली स्थान नहीं आ गए। LocationAssistant न केवल कृत्रिम स्थान अस्वीकार कर सकते हैं, लेकिन यह भी स्थापित करने और स्थान अपडेट की ग्राहकी की परेशानी से ज्यादातर से आप unburdens।

केवल वास्तविक स्थान अपडेट प्राप्त करने के लिए (अर्थात मोज़ेक को दबाएं), इसका उपयोग इस प्रकार करें:

public class MyActivity extends Activity implements LocationAssistant.Listener {

    private LocationAssistant assistant;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        // You can specify a different accuracy and interval here.
        // The last parameter (allowMockLocations) must be 'false' to suppress mock locations.  
        assistant = new LocationAssistant(this, this, LocationAssistant.Accuracy.HIGH, 5000, false);
    }

    @Override
    protected void onResume() {
        super.onResume();
        assistant.start();
    }

    @Override
    protected void onPause() {
        assistant.stop();
        super.onPause();
    }

    @Override
    public void onNewLocationAvailable(Location location) {
        // No mock locations arriving here
    }

    ...
}

onNewLocationAvailable()अब केवल वास्तविक स्थान जानकारी के साथ लागू किया जाएगा। कुछ और श्रोता विधियां हैं जिन्हें आपको लागू करने की आवश्यकता है, लेकिन आपके प्रश्न के संदर्भ में (जीपीएस स्पूफिंग को कैसे रोका जाए) यह मूल रूप से है।

बेशक, एक जड़ वाले ओएस के साथ आप अभी भी स्थान की जानकारी को खराब करने के तरीके पा सकते हैं जो सामान्य एप्लिकेशन के लिए पता लगाना असंभव है।


आपको लिंक किए गए ब्लॉग पोस्ट को संक्षिप्त रूप से संक्षेप में प्रस्तुत करना चाहिए (जहां फ़र्म्समॉकपॉइडर विफल रहता है)।
अजानचर्ल्स

@CodeConfident - टिप्पणी के लिए धन्यवाद! मुझे यकीन नहीं है कि मुझे क्या जोड़ना चाहिए। मेरे उत्तर का दूसरा पैराग्राफ ब्लॉग पोस्ट का सारांश है। .isFromMockProvider छिटपुट और अप्रत्याशित रूप से विफल हो जाता है। लेख में मैं बस और अधिक विस्तार से वर्णन करता हूं जो मैंने इसे खोजने और उपाय करने के लिए उठाए थे।
क्लेसनॉटफाउंड

खैर मुझे यह समझने के लिए आपके लेख पर कूदने के लिए मजबूर किया गया था जो मुझे ऐसा लगता है कि यह एसओ के इरादे के खिलाफ चलता है। मेरा सबसे अच्छा सुझाव यह होगा: (1) अपना चित्र सम्मिलित करें जो डोडी स्थान दिखाता है (मॉक के रूप में चिह्नित नहीं है) और (2) उन्हें समाप्त करने के लिए जल्दी से अपने तर्क पर ध्यान दें (एक किमी के दायरे में अनदेखा करें)
AjahnCharat

ठीक है, गच्चा। मुझे लगता है कि ओ पी के संदर्भ में, की बारीकियों क्यों .isFromMockProvider () अविश्वसनीय है भी प्रासंगिक नहीं हैं। लेकिन मैं आपके द्वारा बताए गए विवरण को बड़ी तस्वीर के लिए जोड़ने का प्रयास करूंगा। प्रतिक्रिया के लिए धन्यवाद!
क्लेसनॉटफाउंड

1
यदि उपयोगकर्ता के पास Google Play सेवा स्थापित नहीं है तो क्या होगा?
यूरी चेर्नशॉ

6

यदि आपको सेल टावरों के सामान्य स्थान का पता चल गया है, तो आप यह देखने के लिए जांच सकते हैं कि क्या वर्तमान सेल टॉवर दिए गए स्थान से मेल खाता है (10 या अधिक मील की तरह कुछ बड़े के एक त्रुटि मार्जिन के भीतर)।

उदाहरण के लिए, यदि आपका ऐप केवल उन विशेषताओं को अनलॉक करता है यदि उपयोगकर्ता किसी विशिष्ट स्थान पर है (आपका स्टोर, उदाहरण के लिए), तो आप जीपीएस के साथ-साथ सेल टॉवर भी देख सकते हैं। वर्तमान में, कोई भी जीपीएस स्पूफिंग ऐप सेल टावरों को भी ख़राब नहीं करता है, इसलिए आप देख सकते हैं कि क्या देश भर में कोई व्यक्ति केवल आपके विशेष फीचर्स में अपना रास्ता ख़राब करने की कोशिश कर रहा है (मैं एक उदाहरण के लिए डिज़नी मोबाइल मैजिक ऐप के बारे में सोच रहा हूँ)।

यह कैसे Llama एप्लिकेशन डिफ़ॉल्ट रूप से स्थान का प्रबंधन करता है, क्योंकि सेल टॉवर आईडी की जाँच करना जीपीएस की तुलना में बहुत कम बैटरी गहन है। यह बहुत विशिष्ट स्थानों के लिए उपयोगी नहीं है, लेकिन अगर घर और काम कई मील दूर हैं, तो यह दो सामान्य स्थानों के बीच बहुत आसानी से भेद कर सकता है।

बेशक, इसके लिए उपयोगकर्ता को एक सेल सिग्नल की आवश्यकता होगी। और आपको क्षेत्र के सभी सेल टावरों आईडी को जानना होगा - सभी नेटवर्क प्रदाता - या आप एक झूठे नकारात्मक के जोखिम को चलाएंगे।


1
धन्यवाद, यह एक बहुत अच्छा विचार है। मुझे उस पर गौर करना पड़ सकता है। धन्यवाद
क्रिसपिक्स

3

इस कोड को इसके बहुत ही सरल और उपयोगी प्रयास करें

  public boolean isMockLocationEnabled() {
        boolean isMockLocation = false;
        try {
            //if marshmallow
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                AppOpsManager opsManager = (AppOpsManager) getApplicationContext().getSystemService(Context.APP_OPS_SERVICE);
                isMockLocation = (opsManager.checkOp(AppOpsManager.OPSTR_MOCK_LOCATION, android.os.Process.myUid(), BuildConfig.APPLICATION_ID)== AppOpsManager.MODE_ALLOWED);
            } else {
                // in marshmallow this will always return true
                isMockLocation = !android.provider.Settings.Secure.getString(getApplicationContext().getContentResolver(), "mock_location").equals("0");
            }
        } catch (Exception e) {
            return isMockLocation;
        }
        return isMockLocation;
    }

यह ऊपर दिए गए isMockLocationEnabled विधि का एक बेहतर संस्करण है।
सेटज़ामोरा

AppOpsManager.checkOp () फेंकता SecurityException यदि एप्लिकेशन को इस सेशन पर क्रैश करने के लिए कॉन्फ़िगर किया गया है। जैसे: java.lang.SecurityException: uid 11151 से packagename MOCK_LOCATION करने की अनुमति नहीं है। यह विधि "यदि आपका ऐप स्थानों का मजाक उड़ा सकता है" का पता लगाने वाला है। लेकिन "अगर प्राप्त स्थानों का मजाक उड़ाया जाता है" नहीं।
सर्जियो

@Sergio "अगर आपका ऐप लोकेशन को मॉक कर सकता है" तो आपका मतलब है कि क्या मौजूदा ऐप में लोकेशन मॉक करने की अनुमति है, है ना?
विक्टर लेरटे

@VictorLaerte मैंने किसी विषय का एक संदर्भ दिया है: / सही। लेकिन सवाल यह था कि: "कैसे पता लगाया जाए कि किसी प्राप्त स्थान का मजाक उड़ाया गया है या किसी नकली प्रदाता से"। या नकली स्थानों को कैसे अनदेखा करें।
सर्जियो

2

यह संख्या एंड्रॉइड के सभी संस्करण के लिए काम कर रही है और मैं इसे कई खोज के बाद ढूंढता हूं

LocationManager locMan;
    String[] mockProviders = {LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER};

    try {
        locMan = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        for (String p : mockProviders) {
            if (p.contentEquals(LocationManager.GPS_PROVIDER))
                locMan.addTestProvider(p, false, false, false, false, true, true, true, 1,
                        android.hardware.SensorManager.SENSOR_STATUS_ACCURACY_HIGH);
            else
                locMan.addTestProvider(p, false, false, false, false, true, true, true, 1,
                        android.hardware.SensorManager.SENSOR_STATUS_ACCURACY_LOW);

            locMan.setTestProviderEnabled(p, true);
            locMan.setTestProviderStatus(p, android.location.LocationProvider.AVAILABLE, Bundle.EMPTY,
                    java.lang.System.currentTimeMillis());
        }
    } catch (Exception ignored) {
        // here you should show dialog which is mean the mock location is not enable
    }

1

आप Google मैप्स जियोलोकेशन एपीआई का उपयोग करके सेल टॉवर ट्राइएंग्यूलेशन या वाईफाई एक्सेस पॉइंट्स की जानकारी के आधार पर अतिरिक्त चेक जोड़ सकते हैं

CellTowers के बारे में जानकारी प्राप्त करने का सबसे सरल तरीका

final TelephonyManager telephonyManager = (TelephonyManager) appContext.getSystemService(Context.TELEPHONY_SERVICE);
String networkOperator = telephonyManager.getNetworkOperator();
int mcc = Integer.parseInt(networkOperator.substring(0, 3));
int mnc = Integer.parseInt(networkOperator.substring(3));
String operatorName = telephonyManager.getNetworkOperatorName();
final GsmCellLocation cellLocation = (GsmCellLocation) telephonyManager.getCellLocation();
int cid = cellLocation.getCid();
int lac = cellLocation.getLac();

आप साइट के साथ अपने परिणामों की तुलना कर सकते हैं

Wifi Access Points के बारे में जानकारी प्राप्त करने के लिए

final WifiManager mWifiManager = (WifiManager) appContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);

if (mWifiManager != null && mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) {

    // register WiFi scan results receiver
    IntentFilter filter = new IntentFilter();
    filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);

    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                List<ScanResult> results = mWifiManager.getScanResults();//<-result list
            }
        };

        appContext.registerReceiver(broadcastReceiver, filter);

        // start WiFi Scan
        mWifiManager.startScan();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.