Below are the original limited permissions of a clean sample of the app:

android.permission.INTERNET

android.permission.ACCESS_COARSE_LOCATION

android.permission.READ_PHONE_STATE

android.permission.VIBRATE

Compare to the

infectedsample, carrying the following permissions:

android.permission.INTERNET

android.permission.ACCESS_COARSE_LOCATION

android.permission.READ_PHONE_STATE

android.permission.VIBRATE

com.android.launcher.permission.INSTALL_SHORTCUT

android.permission.ACCESS_FINE_LOCATION

android.permission.CALL_PHONE

android.permission.MOUNT_UNMOUNT_FILESYSTEMS

android.permission.READ_CONTACTS

android.permission.READ_SMS

android.permission.SEND_SMS

android.permission.SET_WALLPAPER

android.permission.WRITE_CONTACTS

android.permission.WRITE_EXTERNAL_STORAGE

com.android.browser.permission.READ_HISTORY_BOOKMARKS

com.android.browser.permission.WRITE_HISTORY_BOOKMARKS

android.permission.ACCESS_GPS

android.permission.ACCESS_LOCATION

android.permission.RESTART_PACKAGES

android.permission.RECEIVE_SMS

android.permission.WRITE_SMS

When the author(s) infect a file, they ensure Geinimi starts via two different declaredentry pointsthe Android Manifest. The default application activity is overwritten with anew activity that launches the Geinimi service. Additionally, a broadcast receiver listensfor the“BOOT_COMPLETED”

and“SMS_RECEIVED”

intents.

<!--

Default activity-->

<activity

android:theme="@android:01030009"

android:label="@7F050000"

android:name="com.dseffects.MonkeyJump2.jump2.c.rufCuAtj">

<intent-filter>

<action

android:name="android.intent.action.MAIN"></action>

<category

android:name="android.intent.category.LAUNCHER"></category>

</intent-filter>

</activity>

<!--

Broadcast receiver-->

<receiver

android:name="com.dseffects.MonkeyJump2.jump2.f">

<intent-filter>

<action

android:name="android.intent.action.BOOT_COMPLETED"></action>

<category

android:name="android.intent.category.LAUNCHER"></category>

</intent-filter>

<intent-filter

android:priority="65535">

<action

android:name="android.provider.Telephony.SMS_RECEIVED">

</action>

</intent-filter>

</receiver>

Lookout Mobile Security:

GeinimiTrojanTechnical Teardown

3

Both entry points execute the method“startServiceIfMust”, which attempts to connectto the local Geinimi service. If the service is running, it will request the SDK version andsee whether it is equal to or newer than itself. Depending on the answer it starts a newservice or remains inactive.

Communication with the service happens over a TCP socket on ports 5432, 4501 or6543. This is most likely done so that multiple instances of Geinimi can co-exist on thesame device, without knowing the others’ class paths and without accessing eachothers’ services directly. A running service will create a thread to manage the socket.On connection to the socket it listens for a challenge string of“hi,are you online?"

andresponds with"yes,I'm online!". The client then sends the Geinimi SDK major andminorversion, and the server responds with it’s own major and minor version. An excerptfromjump2.h.isRunningServices

It’s clear through this communication that multiple variants of Geinimi havebeencreated and designed to work with each other on the same device. If a newer variant ofGeinimi is installed on the device, the oldervariant surrenders control to it. This is arather interesting method since it will minimize duplicating traffic and keep the device“updated” and using the latest Trojan code.

Lookout Mobile Security:

GeinimiTrojanTechnical Teardown

7

Once the Geinimi service is started, it performs a check-in with the C&C server. Thecheck-in between the server and Trojan is also encrypted, resulting in less conspicuousnetwork traffic. This check-in request occurs every five minutes by default, but can bechanged by the server. When checking it, the Trojan may receive new commands toperform. This is illustrated in the request for commands below:

We can seeabovethat the C&C server can easily identify each infected device uniquely.ThePTID,SALESID,DID

andCPID

all appear to be uniqueper

infected package,possiblyindicating

what infected application the user is running. The IMEI and IMSI canbe used to uniquely identifythe user, as no phone should have the same values foreither of these fields. The longitude and latitude can then be used to track this specificuser,and potentially their movements in 5-minute intervals.

Finally,

the“sdkver”and“autosdkver”

appear toidentify the version of the Trojan. With all this information theperson controlling the C&C server can uniquely identify the location of each infectedphone, what version of Geinimi

they are running, the infected application they haveinstalled

and potentially issue targeted commands to the device.

These are the main methods of communication used byGeinimi, in the encryption andcommand and control section we will dive deeper into how the server can issuecommands.

Lookout Mobile Security:

GeinimiTrojanTechnical Teardown

8

Encryption

The crypto used in Geinimiis straight forward, and falls quickly. 56-bit DES is used witha key of0x0102030405060708. This is found insidejump2.e.k, invoked early in theinitialization:

.method static constructor <clinit>()V

…

// Load the array and say it to this.b;

this.b =new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 };

const/16 v0, 0x8

new-array v0, v0, [B

fill-array-data v0, :array_8c

sput-object v0, Lcom/dseffects/MonkeyJump2/jump2/e/k;->b:[B

…

:array_8c

.array-data 0x1

0x1t

0x2t

0x3t

0x4t

0x5t

0x6t

0x7t

0x8t

.end array-data

…

.end method

This key is used throughout the Geinimi code for several things, such asencrypting/decrypting communications to and from the C&C

server, hiding clear-textcommands and other strings within the binary, and hiding values in the sharedpreferences.

As we illustrated in the previous section the communications with the C&C server areencrypted. The encryption and decryption methods are

very simple functions, andeasily mimicked as follows:

/**

* Encrypt/Decrypt

aGeinimi

byte array

*

*@param

array

* the byte array to encrypt/decrypt

*@param

mode

* Cipher.ENCRYPT_MODE / Cipher.DECRYPT_MODE

*@return

the resulting byte array or null if failed

*/

public

static

byte[]crypto(byte[] array,int

mode)

{

Cipher cipher =null;

DESKeySpeckeySpec

=null;

try

{

if

(cipher ==null) {

byte[] key =new

byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 };

SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");

SecretKey secret = factory.generateSecret(new

DESKeySpec(key));

cipher = Cipher.getInstance("DES");

cipher.init(mode, secret);

}

byte[] result = cipher.doFinal(array);

return

result;

}catch

(Exception exception) {

Lookout Mobile Security:

GeinimiTrojanTechnical Teardown

9

System.err.println(exception.toString());

return

null;

}

}

Using the code above we can decrypt Geinimi’s strings and communication, and canencrypt payloads to sendto the Trojan itself. There is one minor adjustment

that mustbe done to payloads

sent from the C&C server to a Geinimi client, asthe clientexpects

astatic 4 byte header in its response received

from the C&C server.Thisspecialheader is

outlined

in the check-in task, found in

jump2.e.n a(String server, Map parameters,ByteArrayBuffer response)

function;

.method public statica(Ljava/lang/String;Ljava/util/Map;Lorg/apache/http/util/ByteArrayBuffer;)V

const/16 v9, 0x69

…

//

Connect to the server passed in as a parameter, post parameters from the Map

Knowing this, we can now communicate with the Geinimi client ourselves. If we canpoint Geinimi to our own server,we candeliver commands that the client can consume.

A second use of crypto in Geinimi is to make reverse engineering more challenging.BecauseGeinimi encrypts many of it’s strings, they don’t appear directly in the stringstable ofthe application’sclasses.dex

Finally, Geinimi also encrypts contents of its shared preferences file. After an initial runof the Geinimi service, values are saved into the shared-preferences. Here we find a listof servers Geinimi will rotate through,aswell as data saved by a few of its commandhandlers. An example shared preference file from MonkeyJump2 is below:

Some commands deliver a response to the server as the final step in thetransact

state.

Commands

Geinimi supports

avariety

of commands, making it an extremely interesting target for

analysis. Many of the commands

analyzed are fully functional, thougha few do notappear to work, and we speculate that it remains under development.Commandsimplement a common interface and typically have a constructor, an argument parser,and an execution method that implements the command logic.

As, wepreviously mentioned,

the“sms”

command is capable of sending a server-supplied string to a server-controlled destination. The following

are examples of otherviable commands that we have observed in execution by means of a mockserver.

dsms

–

Delete SMS(es)

“dsms”

will delete all messages to or from a specified target number or containing asupplied keyword.

Examples ofsome“dsms”

commands:

<!--

Command to delete a message from 555-LOOKOUT that contains the message “SPAM”-->

<?xml

version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>

<Root>

<Action>

Lookout Mobile Security:

GeinimiTrojanTechnical Teardown

15

<CmdID>2</CmdID>

<AdID>12</AdID>

<dsms>5555665688;SPAM</dsms>

</Action>

</Root>

<!--

Command to delete a message that contains “spamalot” in the body, regardless ofnumber-->

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<Root>

<Action>

<CmdID>2</CmdID>

<AdID>12</AdID>

<dsms>null;goodness</dsms>

</Action>

</Root>

The“dsms”

commandoffers the operator of the servercontrol over the device’sinbox.Not only canthe operator

send messages to anyone, but they can also delete anyevidence of this happening. The code that performs this can be found injump.b.h.b(),commented below:

results in the posting of SMS messages dated between2010-01-01:01:01and 2011-01-01:01:01

to the supplied URI. The command objectexecute callback handsthe bulk of the work tojump2.e.i.a(String server, String afterDate, String beforeDate).Ittags the SMS as sent/received, gathers its data andpipes it out to the specified URI as inthe following HTTP POST body:

The end result is anIntent that is placed in the notification bar.Thus,

we think ofinstall://

a “suggested install” command.

It requires the user to actively click on thenotification and agree to theprompts to complete the installation.

Contrast this with theCmdID=2 variant of the“install”

command. This commandhas adifferent and seemingly more suspicious implementation, though we have not beenable to observe it fully in action as it relies on a loopback network service that we havenot observed operating. This commandfirstproceeds to download as in the“suggested” version; however, the commands

from the server, returning an indication of success/failure to the caller.Note that this is the same backing

implementation for theshell

reinforcing

ourpresumed purpose of the server.

We have observed additional commands in action, but leave investigation as anexercise to the reader.To highlight others we have triggered from a mock server andobserved todate:

updateHost–

Updates the server list with a new list supplied by the server.

changeFrequency–

Changes the frequency preference for checking into the server.

skipTime–

Controls the delay between command execution.

applist

–

Delivers a list of installed applications to the server.

contactlist

–

Dumps contact information including display name, last access time, andphone number about all device contacts to the server.

Conclusion

Geinimi is certainly not the first piece of mobile malware to exhibit many of its traits. Itdoes, however, represent a significant jump in sophistication and capabilities from itspredecessors on the Android platform.It represents the first piece of Android malwareto employ abytecode obfuscator and internal encryption to obfuscate its purpose. It isthe first case ofAndroid malware

grafted onto alegitimate application and,

though themost sophisticated Spyware applications have come close, Geinimiis accepting thebroadest array of commands from a server under the control of an unknown party thatwe have seen to date.

There has been much speculation as to the intent of Geinimi. It couldbe nothing morethan aTrojan

advertising platform with overbearing promotional hooks by ourstandards.At the extreme, the array of capabilities under 3rd

party controlcould

amount to an attempt to build a botnet. These are widely different assessments that

Lookout Mobile Security:

GeinimiTrojanTechnical Teardown

24

rely on knowing the intent ofGeinimi’sauthors,

a perspectivethat we don’t

haveavailableto analyze. What is clear, however,

is that Geinimi is something thatnobodyin their right mind wants installed on their mobile device.