В Android существует замечательная возможность назначать поставщиком геокоординат любую программу, и вся система будет использовать те широту и долготу, которые она выдаст. В этой статье я покажу, как этим пользоваться и как самому написать программу для спуфинга координат GPS.

Идея родилась у меня в процессе написания статьи «Мониторим мониторинг. Что внутри у приложения для изоляции на дому» — именно тогда я обнаружил возможность менять поставщика координат в операционной системе, что открывает для пользователей много интересных возможностей.

С точки зрения юзера все очень просто: нужно лишь установить специальное приложение, затем включить в настройках режим разработчика и выбрать установленное приложение в качестве поставщика фиктивного местоположения. Таких программ великое множество — от простеньких до довольно развесистых, умеющих не только подменять координаты на заданные, но и менять их по расписанию или проигрывать заранее записанные треки, чтобы имитировать движение телефона по какому-то маршруту. В общем, вбивай запрос «Fake GPS» и выбирай по вкусу.

Сразу предупреждаю: надежность этого метода не очень высокая. При желании можно программно отследить наличие на телефоне такой программы-поставщика, и если программа серьезная, то просто так обдурить ее может не получиться.

Я же захотел разобраться, как именно работает этот механизм, и создать собственное приложение для спуфинга. А начал я с того, что посмотрел, как этот алгоритм реализован в одном из бесплатных приложений. Не читать же документацию, верно?

 

Реверсим FakeGPS

В качестве подопытного кролика было взято приложение FakeGPS 5.0.0. Внешне приложение представляет собой карту, на которой можно установить маркер в произвольную точку и с помощью кнопок «Старт» и «Стоп» запускать или останавливать трансляцию координат выбранной точки.

Вооружившись JEB Decompiler, открываем и смотрим. Первое, что бросается в глаза, — это наличие в манифесте пермишена android.permission.ACCESS_MOCK_LOCATION.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.vending.BILLING" />

В основной активити ничего интересного не обнаружено, обычная инициализация и настройка, но есть сервис с говорящим названием FakeGPSService.

Попытаемся прорваться сквозь дебри обфускации и посмотреть, что в нем есть интересного.

В методе onCreate имеется такой код:

this.f = "gps";
this.d = (LocationManager)this.getSystemService("location");
try {
  if(this.d == null) {
    goto label_46;
  }
  this.d.removeTestProvider(this.f);
  goto label_46;
} catch(IllegalArgumentException | NullPointerException unused_ex) {
  goto label_46;
}

label_46:
if(this.d != null) {
  this.d.addTestProvider(this.f, false, false, false, false, true, false, false, 0, 5);
  this.d.setTestProviderEnabled(this.f, true);
}

Если проще, то инициализируем LocationManager значением this.getSystemService("location"), затем удаляем тестового провайдера "gps" функцией removeTestProvider и добавляем заново с помощью функции addTestProvider, не забывая после этого включить его функцией setTestProviderEnabled("gps", true). Всё, тестовый провайдер добавлен и включен. А далее при изменении пользователем координат создаем и устанавливаем новое местоположение в функции onEventMainThread:

// Создаем
long v1 = System.currentTimeMillis();
Location v3 = new Location("");
v3.setProvider("gps");
v3.setLatitude(arg10.latitude);
v3.setLongitude(arg10.longitude);
v3.setAltitude(((double)FakeGPSService.p));
v3.setBearing(((float)FakeGPSService.q));
v3.setTime(v1);
v3.setAccuracy(((float)FakeGPSService.o));
v3.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());

// И устанавливаем
try {
  this.d.setTestProviderLocation(this.f, v3);
  Log.d("GpsMockProvider", v3.toString());
} catch(IllegalArgumentException unused_ex) {
}

Вроде бы все более-менее ясно, можно приступать к написанию своего провайдера фиктивных местоположений.

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее

18 комментариев

  1. Аватар

    0d8bc7

    09.07.2020 в 13:45

    Не могу дочитать статью, но не важно — тема важная, респект.
    Ещё бы делали фейковые камеры, микрофоны и прочее — было бы вообще замечательно (да-да, понимаю, что это может быть труднее, но всё равно). Уж слишком много проблем из-за того, что приложения получают доступ к реальным данным.

    • Аватар

      Novosedoff

      09.07.2020 в 19:43

      0d8bc7, слишком тонко троллите. Ну и что что в приложении Навигатора будут неправильно определяться координаты вашей машины, ну и что что в приложении аптеки не будет показан правильно адрес ближайшей к вам аптеки..
      Просто запретить приложению доступ к координатам — не вариант. Настоящие пацаны, чтоб почувствовать себя крутыми, должны обязательно разрешить, но подменить их!

      • Аватар

        Mazay

        09.07.2020 в 20:58

        В случае с тем же «социальным мониторингом» запретить — действительно не вариант. Ну запретишь ты, ну и вкатают тебе 4 тыщи в день, и иди обжалуй потом. И таких ситуаций куча — водители, курьеры…

      • Аватар

        0d8bc7

        10.07.2020 в 00:13

        Это не троллинг.
        Если ПОЛЬЗОВАТЕЛЮ нужно, чтобы конкретное приложение имело доступ к реальным данным — пусть имеет. Девайсы, приложения и прочее существуют для удовлетворения потребностей пользователей, а не наоборот.
        Запретить доступ — не вариант, т.к. приложение просто узнает об этом и может вести себя не так, как если бы доступ был. Хотя в случае с частью приложений всё может быть и нормально, неизвестно, как будут обстоять дела в случае с каким-то произвольным приложением — это риск, а следовательно, в целом поставка фейковых данных представляется более надёжным решением.

        • Аватар

          0d8bc7

          10.07.2020 в 05:00

          Сорри, не учёл, что поставщик-то фейковых данные предоставляет данные всем приложениям, а не только тем, которым нужно. Наверное. Ну, тут нормальный выход из ситуации состоит как раз в развитии этой темы в целом, при котором, может быть, когда-нибудь в ОС добавят эти возможности без необходимости использовать костыли.
          Ну и, к сожалению, вынужден констатировать, что Навигатору из вашего примера придётся страдать из-за того что на одном с ним устройстве установлен какой-нибудь «мониторинг» (поставщик данных же один, если я ничего не напутал, вот были бы они разные для разных приложений, было бы другое дело) ¯\_(ツ)_/¯

          • Аватар

            Mazay

            10.07.2020 в 07:02

            Можно создавать провайдера с произвольным именем, например MyFakeProvider, а потом с помощью apktool подправить то приложение, которое надо обмануть, чтобы оно работало не со стандартным провайдером gps, а с нашим MyFakeProvider. Тогда все, кроме этого приложения, будут получать реальные координаты.

            • Аватар

              Mazay

              10.07.2020 в 07:03

              Но тогда может возникнуть проблема с подписью или ещё с чем то, если обманываемое приложение проверяет свою целостность.

              • Аватар

                Mazay

                10.07.2020 в 07:05

                Но можно и проверку целостности вырезать:-) короче говоря, все зависит от желания и конкретной ситуации.

    • Аватар

      Mazay

      10.07.2020 в 06:59

      Насчёт фейковой камеры не слыхал, но подозреваю, что тут понадобится рут, и весьма вероятно, что решение будет сильно привязано к конкретной модели и версии прошивки. Но мысль интересная… А по поводу микрофона — можно взять штекер 3,5 и замкнуть определенные контакты через сопротивление (100 ом, вроде, но точно не помню), воткнуть его в телефон и телефон будет думать, что подключен внешний микрофон, его собственный при этом отключится. Когда надо позвонить — штекер вынимается, после звонка вставляется назад.

      • Аватар

        Laglag

        12.07.2020 в 12:57

        генеально спасибо!!!!!!

      • Аватар

        Lex.Mikachev

        12.07.2020 в 18:10

        Хм… А что, просто до безобразия, а главное — работает 🙂 Кстати, вспомнился лайф-хак с камерами для ноутбуков: заклеить чёрной изолентой, ну, или синей — она обычна всегда 100%-й вариант 🙂

  2. Аватар

    m2s2TNgqFNu4kvD5M

    14.07.2020 в 10:58

    Ни разу не видел, и у меня их тоже нет, в настройках телефона возможность разрешить устанавливать фиктивное местоположение. Режим разработчика включён. С какой версии Андроид такое разрешает?

  3. Аватар

    viktor_cortez

    20.07.2020 в 21:33

    Тут вот одна проблема остается. Галочка фиктивных локаций в настройках. Может ли установленное приложение видеть, что этот режим у телефона включен? Как видят рут доступ например. И заведомо понимать, что обманывают.

Оставить мнение