Jump to content

Remove CE limits from DJI products and other fun stuff in DJI Go4


Bin4ry

Recommended Posts

Hey, 

Update:

You can find the Modding tool on github: https://github.com/Bin4ry/deejayeye-modder

Feel free to contribute. 

 

i saw that here are already 2 topics regarding DJI products and their limitations, so i guessed it is ok to show you some of my recent work here. I don't want to introduce myself here too much, if you want to know something about me find me on XDA. 

Ok, so i recently bought a DJI spark, and i tried to come up with a way to remove the CE transmission limit without rooting the drone (because technically this is not my drone but my wifes :D ) and i started with reversing the dji go app. What i found was this part of code which is called when the app is started (this is decompiled from classes4.dex, because of that the code looks strange):

public void a(String paramString1, String paramString2, dji.pilot.countrycode.model.a parama1, dji.pilot.countrycode.model.a parama2, a parama)
  {
    boolean bool = dji.pilot2.usercenter.activate.c.d(DJIApplication.getAppContext());
    StringBuilder localStringBuilder = new StringBuilder(40);
    if ((!parama1.a()) && (bool))
    {
      a(paramString1, paramString2, parama1, parama);
      localStringBuilder.append("飞机GPS获得,采取策略1:UavGps策略");  //Aircraft GPS gets, take strategy 1: UavGps strategy
    }
    for (;;)
    {
      a.a(this.c, "【国家码获取(get)】触发后策略选择: " + localStringBuilder); //[Country code get (get)] After the trigger strategy selection:
      return;
      if ((!parama2.a()) && (bool))
      {
        b(paramString1, paramString2, parama2, parama);
        localStringBuilder.append("飞机GPS没有获得,手机GPS获得,采取策略2:MobileGps策略"); //Aircraft GPS does not get, mobile GPS gets, take strategy 2: MobileGps strategy
      }
      else if (a(parama, false, -1))
      {
        localStringBuilder.append("飞机GPS没有获得,手机GPS没有获得,mCC获得,采取策略3:Mcc策略"); //Aircraft GPS did not get, cell phone GPS did not get, mCC get, take strategy 3: Mcc strategy
      }
      else if (bool)
      {
        a(paramString1, paramString2, parama);
        localStringBuilder.append("飞机GPS没有获得,手机GPS没有获得,mCC没有获得,采取策略4:IP策略"); //Aircraft GPS did not get, cell phone GPS did not get, mCC did not get, take strategy 4: IP strategy
      }
      else
      {
        parama.a(-1, "get cc failure for network is disconnect");
      }
    }
  }

I added comments to translate the chinese stuff. So what this code does is simple, it has a few checks and goes through a strategy to determine which limitations it should apply. 

1.) check if aircraft has gps -> if yes, use the coords to determine which country (done on phone!)

2.) if 1 failed -> check if mobile has gps ......

3.) if 2 failed -> check if mobile has SIM, if yes look for MCC and determine sim country

4.) if 3 failed -> check if mobile has internet, if yes go to: https://mydjiflight.dji.com/api/v2/geocoder_service/geoip and parse the json result

 

Ok, so there are a few ways to get the app think we are located in the US to get FCC limits instead of CE. First i modified the above functions smali code to represent something lilke this java code: 

    public void a(String string, String string2, dji.pilot.countrycode.model.a a2, dji.pilot.countrycode.model.a a3, a a4) {
        c.d((Context)DJIApplication.getAppContext());
        StringBuilder stringBuilder = new StringBuilder(40);
        a2.a();
        this.a(a4, false, -1);
        stringBuilder.append("Call to fake function which will always answer with US MCC");
        dji.pilot.countrycode.a.a.a((Context)this.c, (String)("Going to use fake function to always return US MCC: " + stringBuilder));
    }

also i modified the function which it calls.

Before:

 private boolean a(a parama, boolean paramBoolean, int paramInt)
  {
    String str = ((TelephonyManager)this.c.getSystemService("phone")).getNetworkCountryIso();
    if (!TextUtils.isEmpty(str))
    {
      this.b[b.c.ordinal()] = str.toUpperCase();
      parama.a(a(), "getFromMcc");
      return true;
    }
    if (paramBoolean) {
      parama.a(paramInt, "getFromMcc():CountryCode is empty !");
    }
    return false;
  }

After:

    private boolean a(a a2, boolean bl, int n) {
        if (!TextUtils.isEmpty((CharSequence)"us")) {
            this.b[b.c.ordinal()] = "us".toUpperCase();
            a2.a(this.a(), "getFromMcc");
            return true;
        }
        if (!bl) return false;
        a2.a(n, "getFromMcc():CountryCode is empty !");
        return false;
    }

 

So the new program flow is:

1.) call MCC function -> MCC function answers "us" :-) 

 

I've done the changes directly in the smali code and put it together again to a dex file, then i packed the dex file into the apk, removed the manifest.mf with its signatures and signed the whole file again with testkeys. 

You can find the modified apk (based on version 4.1.3) here if you don't want to put together your own version (you will have to remove the original apk first because this one is signed with a testkey and not with dji's key): 

!Downloadlink removed!

I have not had time to test the range yet, but i am pretty sure it should work if there is no other check involved. As far as i was able to understand this check should be the same for all dji products which use the DJIGo4 App, so if you have multiple products this should work for all of them at the same time ;)

I hope i was able to contribute here and would love to hear some of your thoughts. 

 

Best Regards

Bin4ry

Edited by Bin4ry
  • Like 1
Link to comment
Share on other sites

Ok, i keep adding posts until i can edit the first post. 

Due to request i did a search for the update functions and the forced update dji added. I found it in classes2.dex (com/dji/update), there were some interesting functions inside:

First there are these strings:

  private static final String j = "https://adhoc-staging.aasky.net/api/v1/go/auto_upgrade";
  private static final String k = "https://adhoc.djiservice.org/api/v1/go/auto_upgrade";

i changed them to 127.0.0.1:

  private static final String j = "https://127.0.0.1/api/v1/go/auto_upgrade";
  private static final String k = "https://127.0.0.1/api/v1/go/auto_upgrade";

also here

 private static void a(Context paramContext, String paramString1, final boolean paramBoolean1, final a parama, String paramString2, final boolean paramBoolean2)
  {
    if (a) {}
    for (String str = "https://adhoc-staging.aasky.net/api/v1/go/auto_upgrade";; str = "https://adhoc.djiservice.org/api/v1/go/auto_upgrade")
    {
      d.a(str, paramString2, paramString1, new d.a()
      {
        public void a(String paramAnonymousString)
        {
          Log.d("UpdateAgent", paramAnonymousString);
          OnlineConfig localOnlineConfig = (OnlineConfig)new Gson().fromJson(paramAnonymousString, OnlineConfig.class);
          try
          {
            localOnlineConfig.saveToFile(this.a, "Config.data");
            if (!a.a(localOnlineConfig))
            {
              if (parama != null) {
                parama.a("Data error:" + paramAnonymousString);
              }
              return;
            }
          }
          catch (IOException localIOException)
          {
            do
            {
              for (;;)
              {
                localIOException.printStackTrace();
              }
              if (parama != null) {
                parama.a("server success:" + paramAnonymousString, localOnlineConfig);
              }
            } while (paramBoolean2);
            a.a(localOnlineConfig, this.a, paramBoolean1);
          }
        }
        
        public void a(Throwable paramAnonymousThrowable, int paramAnonymousInt, String paramAnonymousString)
        {
          if (parama != null) {
            parama.a("server failed:" + paramAnonymousInt);
          }
        }
      });
      return;
    }
  }

did the same to the urls to make sure it cannot connect to the dji server.

 

inside another file called OnlineConfig i found

 

public boolean needForceUpdate()
  {
    return this.force_update;
  }
  
  public boolean needUpdate()
  {
    return this.update;
  }

where i changed it to:

public boolean needForceUpdate()
  {
    return false;
  }
  
  public boolean needUpdate()
  {
    return false;
  }

this should make sure that the other online functions (like maps etc. are still intact, but softwareupdates cannot work AND are not forced). 

 

 

Also i did find the "old" dialog where one was able to edit the CountryCode, so i did enable it too, this way you can switch to EU (if you really want to), also removed the 9 taps on the SN to open it, it opens on first touch. (To open this dialog connect your aircraft -> About device -> tap on SN of flightcontroller)

 

Here are the new versions:

!Downloadlink removed!

 

I hope this helps =)

Edited by Bin4ry
  • Upvote 1
Link to comment
Share on other sites

Thank you! I understand that alongside FCC in app there are a parameter BOOST that will at least dubble FCC power but until now could not be adjusted only triggering full BOOST power...and this is a problem because remote could overheat.

Link to comment
Share on other sites

if ( v18 & 1 )
objc_msgSend(v2, "setSdr_force_fcc:", 1LL);
if ( v18 & 2 )
objc_msgSend(v2, "setSdr_force_boost:", 1LL);
if ( v18 & 4 )
objc_msgSend(v2, "setSdr_force_2_3_G:", 1LL);
if ( v18 & 8 )
objc_msgSend(v2, "setSdr_force_2_5_G:", 1LL);

 

from jeb

Link to comment
Share on other sites

Thanks for your contribution. Can you explain where you did find this values so i don't have to go through all the 27k files manually? :) Even if i doubt i will force the boost (due to the overheat problem you mentioned) i would love to take a look what else is there ;)

 

Best Regards

Link to comment
Share on other sites

I don't have this producs, so what do you want modded there? Same thing? How do they work are they android based too? Do they also use the Dji Go4 app? If they use the DJI Go 4 app the same FCC hack should work automatically =)

Give me a few infos about this products as i am new to this stuff.

 

Best Regrads

Link to comment
Share on other sites

Thanks for all the work on the go app Bin4ry and everyone! One other thing I would like to see added would be to block the Here Maps to force the use of Google Maps. There is a service hack you can use but it requires root on your device. I have found Google to have a lot more detail and resolution. Another great option would be to be able to manually import Google Maps images into the app. Right now I have found you can cache the actual maps by viewing the location in the app and then disconnecting internet however I am not seeing that it is possible to cache the actual satellite imagery.

Link to comment
Share on other sites

Congratulations, I have the same progress as you for FCC switch

on disconnect the dji go app check TelephoneManager.getNetworkCountryIso() on android for mcc to set the RF power. That's the same behaviour for all dji goes.

 my trick is to set gsm.operator.iso-country properties to "us" when mobile network is disabled, then start dji go for FCC power. But only in ROOT and for Android only.

i have an app for this purpose https://pan.baidu.com/s/1jHPQdO6

  • Upvote 1
Link to comment
Share on other sites

Ok, here i am back again, sorry for not posting earlier but my account hit the posting limit like digininja explained. For google maps: I will look into it soon. 

 

This is the latest patch,in contrary to patch number 2 which should deactivate updates of the app and disables force updates this patch will not completely remove the UpgradeManagerService, or better said it will remove the start of the service. 

It can be found in classes5.dex -> dji/pilot/publics/object/DjiApplicationLike.class (which is part of the main activity starting process).

Here we see this code in it's onCreate function

    this.upgradeService = new Intent(getApplication(), DJIUpgradeService.class);
    getApplication().startService(this.upgradeService);

to remove this we need to remove this lines from smali code

.line 155
    new-instance v0, Landroid/content/Intent;

    invoke-virtual {p0}, Ldji/pilot/publics/objects/DJIApplicationLike;->getApplication()Landroid/app/Application;

    move-result-object v1

    const-class v2, Ldji/dbox/upgrade/p4/statemachine/DJIUpgradeService;

    invoke-direct {v0, v1, v2}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V

    iput-object v0, p0, Ldji/pilot/publics/objects/DJIApplicationLike;->upgradeService:Landroid/content/Intent;

    .line 156
    invoke-virtual {p0}, Ldji/pilot/publics/objects/DJIApplicationLike;->getApplication()Landroid/app/Application;

    move-result-object v0

    iget-object v1, p0, Ldji/pilot/publics/objects/DJIApplicationLike;->upgradeService:Landroid/content/Intent;

    invoke-virtual {v0, v1}, Landroid/app/Application;->startService(Landroid/content/Intent;)Landroid/content/ComponentName;

 

after the removal DJI Go will no longer check your firmware version and will not connect home to download Upgrades :)

This is the change for version 5 which can be downloaded here: 

!Downloadlink removed!

@Kyokushin:

I think i can enable P3 in DJI Go4, give me some time to pin it down. 

 

微风小杨:

Thanks for the infos 

 

Best Regards

Edited by Bin4ry
Link to comment
Share on other sites

Hello 

dji go 4.4.1.3

While trying to upload waypoints to the aircraft (0 % complete) I got the Failed to start Waypoints Mission warning. And then I got Cancel and Retry options.

earlier version working

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...