Please select Into the mobile phone version | Continue to access the computer ver.
How to reverse engineer the S1 Application - and have some fun :)
Uploading and Loding Picture ...(0/1)
o(^-^)o
sevreNniarB
lvl.4
Germany
Offline

We still don't have (m)any reliable documentation for our beloved Robomaster S1 and I think it is time to provide some more in-depth reverse engineering methods & tools for the community. If you are not familiar with some basic C# knowledge this post is probably not for you.

To my current knowledge the Robomaster S1 application is the only way to access, program & control the S1. So let's start and have some fun with it, shall we?

  
Some background information
  
The Robomaster S1 (PC-)Application is created with a tool called Unity. Unity is a cross-platform game engine like the Unreal Engine from Epic. If you play computer games you probably know what I'm talking about.

Compiled Unity code is almost not optimized/protected in any way and very easy to decompile. Don't worry, we don't have to mess around with Assembly language - it's nice C# or IL code. Intermediate language (IL) is an object-oriented programming language designed to be used by compilers for the .NET Framework before static or dynamic compilation to machine code.

Most of the Robomaster application magic happens in the ...\RoboMaster_Data\Managed\Assembly-CSharp.dll. That's just how Unity works. All the DJI developers hard work is compiled and dumped into this single dynamic-link library. Very nice, thank you DJI & Unity Technologies

On a side note: If you are interested in the Robomaster S1 application Audio, Mesh, Textures, etc. you are able to extract this stuff as well. You will find freeware Unity asset extractors all over the internet.


How to decompile the heart of the S1 application
To take a closer look under the hood you'll need a decompiler like ILSpy or dnSpy (both are freeware). I'm not entirely sure if it is allowed to link the GitHub repositories here, but a little Google search will do the trick. There are not many forks and both tools should be relatively easy to find.

In my opinion dnSpy is more advanced. It allows you to debug the application while it is running (set breakpoints, get values of variables, ... you name it). Please be aware that you'll need the patched Unity mono.dll & mono-2.0-bdwgc.dll for the real-time debugging stuff with dnSpy. The GitHub repository also provides the corresponding links (the latest 2019 version worked fine for me). If you want to mod the existing S1 code give ILSpy with the Reflexil extention a try.

For the basic decompilation process start ILSpy/dnSpy and load (or drag & drop) the mentioned Assembly-CSharp.dll. Simple as that and in all its glory:

Closer look

Closer look

The provided screenshot shows the MotorAddress Module as an C# example, but there is so much more to explore... Please be aware that there are some limitations regarding the decompiled source code. Especially the search functions of ILSpy/dnSpy are a bit confusing and sometime don't work in the way they should. For source code analysis I personally prefer to decompile the DLL with ILSpy and export it as C# project (File -> Save Code…)

Feel free to dig around, reverse engineer and do whatever you want. I'm sure our great community will soon release some cool tools and solutions for the DJI Robomaster S1.

Cheers
2019-11-6
Use props
Montfrooij
Captain
Flight distance : 2560453 ft
  • >>>
Netherlands
Offline

Very cool!
2019-11-6
Use props
gpvillamil
Second Officer
Flight distance : 210226 ft
United States
Offline

Great post! I have most of these tools, very intrigued by the possibility of having the app as an editable project.

Have you been able to tell if the code for the various ports (ios, Android) is in the same project?
2019-11-6
Use props
sevreNniarB
lvl.4
Germany
Offline

gpvillamil Posted at 11-6 06:00
Great post! I have most of these tools, very intrigued by the possibility of having the app as an editable project.

Have you been able to tell if the code for the various ports (ios, Android) is in the same project?

Yes & maybe - you can find it in the code in there

namespace DJI
{
        // Token: 0x0200059F RID: 1439
        public enum DJIAppSupportedDevice
        {
                // Token: 0x04001944 RID: 6468
                iPhone,
                // Token: 0x04001945 RID: 6469
                Android,
                // Token: 0x04001946 RID: 6470
                MacOS,
                // Token: 0x04001947 RID: 6471
                Windows,
                // Token: 0x04001948 RID: 6472
                iPad
        }
}

Unity is cross-plattform, but we don't know if DJI internally uses different projects for each OS.

Cheers
2019-11-6
Use props
BGA
Captain
United States
Offline

Nice one. I am specially interested on how the Lab encodes saved programs. I guess I will give it a go this weekend.
2019-11-6
Use props
BGA
Captain
United States
Offline

Found a decompiler for Linux so I can actually try it at work. Here is the .dsp decryption function:

// Module.InnerTools.View.ViewLab
using Base.AppService;
using COMMON;
using System.IO;
using UnityEngine;

public void DecryptDsp()
{
        string text = Common.GetPersistentDataPath + "/dsp_projects";
        string text2 = text + "/decrypted_project";
        string dspEncryptKey = GetDspEncryptKey();
        string dspEncryptVector = GetDspEncryptVector();
        Directory.CreateDirectory(text2);
        string[] files = Directory.GetFiles(text);
        foreach (string path in files)
        {
                if (Path.GetFileName(path).Contains("dsp") || Path.GetFileName(path).Contains("DSP"))
                {
                        string contents = AESCrypt.decryptAES(File.ReadAllText(path), dspEncryptKey, dspEncryptVector, fromHexCode: false);
                        string text3 = text2 + "/" + Path.GetFileName(path);
                        File.WriteAllText(text3, contents);
                        Debug.Log("Decrypt:decryptFilePath:" + text3);
                }
        }
        Debug.Log("Decrypt:Complete");
}

The keys seem to be managed by Unity itself and I am not familiar with how it is done. But it I can modify and regenerate the Assembly_CSharp.DLL file, it should be trivial to figure it out.

Other than that, lots of interesting stuff there. Now trying to figure out if I can find any undocumented things that might be useful.


2019-11-6
Use props
sevreNniarB
lvl.4
Germany
Offline

BGA Posted at 11-6 09:46
Found a decompiler for Linux so I can actually try it at work. Here is the .dsp decryption function:

// Module.InnerTools.View.ViewLab

The decryption of a dsp file worked for me

Used dnSpy on my Windows Machine and created a breakpoint in the save module... long story short the result is this (I blurred the 2nd half of the key & vector, don't know if it is system/account specific or something global):

Crypt_Key

Crypt_Key


To verify our thesis is used https://www.devglan.com/online-tools/aes-encryption-decryption, opened a local .dsp file with a text editor, pasted the text, entered the key & vector. The decrypted result looks like this:

<dji><attribute><creation_date>2019/03/27</creation_date><sign>***********</sign><modify_time>11/6/2019 7:45:34 PM</modify_time><guid>************</guid><creator>Anonymous</creator><firmware_version_dependency>00.00.0000</firmware_version_dependency><title>Dodge</title><code_type>python</code_type><app_min_version></app_min_version></attribute><code><python_code><![CDATA[variable_Tranlation = 0variable_Spin = 0variable_Offer = 0def user_defined_Move():    global variable_Tranlation    global variable_Spin    global variable_Offer    variable_Spin = -1 * variable_Spin    variable_Tranlation = -1 * variable_Tranlation    chassis_ctrl.set_wheel_speed((variable_Tranlation - variable_Spin) + variable_Offer,(variable_Spin - variable_Tranlation) + variable_Offer,(-1 * variable_Tranlation - variable_Spin) + variable_Offer,(variable_Tranlation + variable_Spin) + variable_Offer)def start():    global variable_Tranlation    global variable_Spin    global variable_Offer    robot_ctrl.set_mode(rm_define.robot_mode_free)    gimbal_ctrl.enable_stick_overlay()    variable_Offer = 120    variable_Spin = 60    variable_Tranlation = 250    user_defined_Move()    time.sleep(0.5)    user_defined_Move()    time.sleep(1)    user_defined_Move()    time.sleep(0.7)]]></python_code><scratch_description><![CDATA[]]></scratch_description></code></dji>



Cheers

2019-11-6
Use props
BGA
Captain
United States
Offline

sevreNniarB Posted at 11-6 12:38
The decryption of a dsp file worked for me

Used dnSpy on my Windows Machine and created a breakpoint in the save module... long story short the result is this (I blurred the 2nd half of the key & vector, don't know if it is system/account specific or something global):

The keys have to be global as dsp files can be shared between machines. It would be great if you could let us know what those are. Otherwise I will try dnSpy when i am home.

In any case, what I want to do is write a program to encapsulate an arbitrary python program in a dsp file. This will help creating S1 programs outside of the Robomaster app.
2019-11-6
Use props
sevreNniarB
lvl.4
Germany
Offline

BGA Posted at 11-6 12:55
The keys have to be global as dsp files can be shared between machines. It would be great if you could let us know what those are. Otherwise I will try dnSpy when i am home.

In any case, what I want to do is write a program to encapsulate an arbitrary python program in a dsp file. This will help creating S1 programs outside of the Robomaster app.

Send you a PM, please test it.

Cheers

Terry
2019-11-6
Use props
BGA
Captain
United States
Offline

sevreNniarB Posted at 11-6 13:06
Send you a PM, please test it.

Cheers

Thanks. While we are at it, another question: Looking at the .dsp file, it seems to be base64 encoded. Did you actually feed the file as is to that online tool or did you base64-decoded it?
2019-11-6
Use props
sevreNniarB
lvl.4
Germany
Offline

BGA Posted at 11-6 13:12
Thanks. While we are at it, another question: Looking at the .dsp file, it seems to be base64 encoded. Did you actually feed the file as is to that online tool or did you base64-decoded it?

As it is (cut & paste from the .dsp file) ... use the following parameters in the online tool:

2019-11-06 22_19_17-Online Tool for AES Encryption and Decryption.jpg
2019-11-6
Use props
BGA
Captain
United States
Offline

Thanks! I now have working encoding and decoding of DSP files! I will commit this code to my repository soon. your post resulted in a very nice breakthrough in enabling external development! Thanks again.
2019-11-6
Use props
sevreNniarB
lvl.4
Germany
Offline

Great, thank you BGA


Please be aware thet the .dsp code also seems to be signed (<sign>ValueGoesHere</sign>, I don't know the reason for it, because the .dsp files work without valid signature). The MD5 signature inlucdes:

mKey (yes, another one: wwxnMmF8)
CreatDate,
Title,
Creeator,
FirmwareDependencyVersion,
GuidNum,
PythonCode
ScratchDescription,
CodeType

The C# code looks like this:

private void RegenerateSign()
        
{
            
string text = FilesHelper.md5(string.Concat(new object[]
            
{
               
this.mKey,
               
this.CreatDate,
               
this.Title,
               
this.Creeator,
               
this.FirmwareDependencyVersion,
               
this.GuidNum,
               
this.PythonCode,
               
this.ScratchDescription,
               
this.CodeType
            
}));
            
if (text.Length == 32)
            
{
               
this.Sign = text.Substring(7, 16);
            
}
        
}

It should be easy to debug/reverse engineer with the above mentioned entry point, but you will need your Windows VM/Machine to get there.


Cheers & GL


2019-11-7
Use props
BGA
Captain
United States
Offline

sevreNniarB Posted at 11-7 05:07
Great, thank you BGA



Thanks. Yes, I saw that. It is just the md5sum of a string generated based on the contents.

But it is never checked anywhere it seems so not setting it is ok.
2019-11-7
Use props
DJI Stephen
DJI team
Offline

Hello and good day sevreNniarB. Thank you for reaching out and for sharing these informative information with us. Thank you for your support.
2019-11-8
Use props
sevreNniarB
lvl.4
Germany
Offline

DJI Stephen Posted at 11-8 08:47
Hello and good day sevreNniarB. Thank you for reaching out and for sharing these informative information with us. Thank you for your support.

Thank you Stephen

Why do your DJI developers give us such a hard time with these things? Imho there is no reason to e.g. AES encrypt .DSP files at all - it should be already plaintext in the first place. It shouldn't be necessary that users like BGA, albertr, Duane Degn, g1107 and all the other fellow members here have to reverse engineer your product...

But I really, really appreciate that DJI is not censoring this kind of hacking related knowledge sharing on the forum. This information exchange is very important for the more advanced S1 users out there. Thank you!

My friendly appeal is: Don't be afraid, DJI. Pretty up your internal documentation & share it, open up the API, lift all the unnecessary restrictions (like the whitelist only Python library import... come on, really?) there is nothing to be afraid of.

Don't get me wrong. For normal S1 users your sandbox approach is the right way. Easy to use, a fun way to explore and learn. For the more robotics hacking/programming orientated users the current restrictions are just a pain in the ***


One day it will happen anyway... someone will find a way to break out of the S1 sandbox - it's just a matter of time. Why wait? The community is begging DJI for months and months to show us more S1 documentation related love (CAN bus, etc.). We love your product and want to get it to the next level. It's already getting boring to see the hundredth YouTube video showing a S1 chasing a blue line on the floor. How cool would it be (also from a marketing point of view) to see a S1 using e.g. TensorFlow und do some really crazy stuff?


Cheers
2019-11-8
Use props
xlla
lvl.1

China
Offline

sevreNniarB Posted at 2019-11-8 15:55
Thank you Stephen

Why do your DJI developers give us such a hard time with these things? Imho there is no reason to e.g. AES encrypt .DSP files at all - it should be already plaintext in the first place. It shouldn't be necessary that users like BGA, albertr, Duane Degn, g1107 and all the other fellow members here have to reverse engineer your product...

DJI certainly like to see how cool would it be, but they are consider profit previously.
2021-1-3
Use props
Advanced
You need to log in before you can reply Login | Register now

Credit Rules