Sandroid RAT analysis: Part I - synthetic communication

My first post is about Sandrorat, a fairly new RAT tool that was prominent for being a part of a Polish spam campaign. The analyzed sample hash is bed05d8eace6a7ebc5dec7141ea4b9cc559f1b2aab8848e2c79df7a79de39b9d. Sample was obtained thanks to The Honeynet Project.

Everything is synthetic

First part will be about a little known synthetic methods and the way Sandrorat uses them to obfuscate the code. This sample declared three different services:

<service android:name="com.zero1.sandrorat.Controller" android:enabled="true" />
<service android:name="com.zero1.sandrorat.GPSLocation" android:enabled="true" />
<service android:name="com.zero1.sandrorat.Toaster" android:enabled="true" />

First service is run when either the button on the main app screen is pressed or when the com.zero1.sandrorat.Connector (declaration below) receives a BOOT_COMPLETED intent.

<receiver android:name="com.zero1.sandrorat.Connector">
 <intent-filter>
  <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
  <action android:name="android.intent.action.BOOT_COMPLETED" />
 </intent-filter>

</receiver>

Starting the service by button is somewhat convoluted in such a way that jd-gui + dex2jar combo does not show the actual code. This obfuscation is done by the clever use of synthetic methods. These methods (and classes and variables) are supposed to be created by the Java compiler and only by the Java compiler. They have a specific purpose, which is discussed in this great writeup. However, in this case they are used to hide some of the functionality. Take a look. At first let's go to the onCreate method of the MainActivity (btw: really creative name for the class, right?).


You see that there is a listener put in place in case user clicks on the button. This listener is implemented in the ag class. So let's have a look there.


Well, there seems to be some kind of startService performed, but it's performed on the non-exiting class variable, right? What's up with that? It all starts to come together when we take a look at the smali code (thanks to the apktool). There is actually a variable called a, but it's marked as synthetic and for some reason does not come up in the jd-gui.

.field final synthetic a:Lcom/zero1/sandrorat/MainActivity;


But where is this variable value saved? The answer is: in the constructor. Smali code for the constructor is:

.method constructor <init>(Lcom/zero1/sandrorat/MainActivity;)V
    .locals 0

    iput-object p1, p0, Lcom/zero1/sandrorat/ag;->a:Lcom/zero1/sandrorat/MainActivity;

    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method


So, the a variable is actually an instance of the MainActivity class. Since this class extends the Activity class, it also extends a Context class, which means it has a startService method. Now we know what this.a means, but there is no static a method in MainActivity. When we take a look into the smali code we see that it's the same synthetic trick used, but this time it's used to hide a method, not a variable.

.method static synthetic a(Lcom/zero1/sandrorat/MainActivity;)Landroid/content/Intent;
    .locals 1

    iget-object v0, p0, Lcom/zero1/sandrorat/MainActivity;->c:Landroid/content/Intent;

    return-object v0

.end method

This method returns the c variable, which actually is the instance of the Controller class. Now everything makes sense. The only line of code in the onClick method is responsible for running the Controller service. This service is responsible, among other things, for the C&C communication.

It's worth noting that the service responsible for communication is not started automatically, but waits for a user to press a button (or for a phone to restart). This is done to prevent the automatic sandbox from capturing the network traffic.

C&C communication

When we start to browse different classes we eventually come to the class that seems to hold communication parameters. Class is presented below, it has only three static variables.


Educated guess will be that the first and last variables are C&C addresses, and the b variable is a port number. However, it seems that the first two variables are there as a decoy - false domain and port just to obfuscate the real C&C address. First, Sandrorat sends a register message (l class is responsible for this) via HTTP POST to the am.c + "DeviceManager.php?func=registerDevice" URL with a couple of device information and some other parameters. In response it should receive the registered string. Then, again using the synthetic tricks, the actual communication takes place.

Communication is handled by the n class, but the main switch instruction, responsible for the command execution, is in the Controller class private byte[] a(int, java.lang.String) method. Communication is pretty straightforward. First, it sends a HTTP POST to the am.c + "Linker.php?func=getCommand" with a device ID as one of the parameters. It then receives one line with a command or no command at all. This line has a following structure:

<command_number>#<parameters>#<answer_token>

Where <parameters> is a ~ delimited list of strings. Response to each of the commands is made via HTTP POST body to the am.c + "upload.php" URL with a filename parameter, which is composed of the device serial number, answer_token and the .dj string. Then some weird HTTP POST request to the am.c + "Linker.php?func=setResult" is made. I have no idea what is the purpose of this POST request.

Anyhow, that's all for this post, in the next one I will try to explain a couple of commands that Sandrorat can perform. Just a quick sneak peek: 1 is for ping and it always responds with the "Ack" string.

Comments

Popular posts from this blog

Having fun with AndroidManifest.xml

Android malware based on SMS encryption and with KitKat support

Android malware goes Mono (.NET) and Lua!