Though we have removed the 盗版 dialog in How to crack momo?(1), there is another issue, “账号安全验证“。

$ grep 账号安全 com.immomo.momo -r com.immomo.momo/res/layout/activity_securitycheck.xml: < android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="10.0dip" android:layout_marginTop="8.0dip" android:layout_marginRight="10.0dip" android:layout_marginBottom="8.0dip" android:text="为了你的账号安全,需要主动发送短信,激活账号。此操作只收取通信费。" tyle="@style/register_label" />

$ grep -r activity_securitycheck com.immomo.momo

com.immomo.momo/res/values/public.xml:    <public type="layout" name="activity_securitycheck" id="0x7f03009e" />

crocodile@C1OG ~/raw
$ grep -r 0x7f03009e com.immomo.momo
com.immomo.momo/res/values/public.xml:    <public type="layout" name="activity_securitycheck" id="0x7f03009e" />
com.immomo.momo/smali/com/immomo/momo/android/activity/account/SecurityCheckActivity.smali:    const v0, 0x7f03009e

So there must be a call to start SecurityCheckActivity.

$ grep -r SecurityCheckActivity com.immomo.momo|grep -v "smali/com/immomo/momo/
android/activity/account/SecurityCheckActi"|awk -F: '{print $1}'|sort -u

Remove the possibility of au,aw,av,ax, let us focus on com.immomo.momo/smali/com/immomo/momo/android/activity/account/LoginActivity.smali.

LoginActivity;->f() is called to start this activity.

who call LoginActivity;->f()?

$ grep -rn "LoginActivity;->f()" com.immomo.momo
com.immomo.momo/smali/com/immomo/momo/android/activity/account/h.smali:325:    invoke-virtual {v0}, Lcom/immomo/momo/android/activity/account/LoginActivity;->f(
com.immomo.momo/smali/com/immomo/momo/android/activity/account/h.smali:336:    invoke-virtual {v0}, Lcom/immomo/momo/android/activity/account/LoginActivity;->f(
com.immomo.momo/smali/com/immomo/momo/android/activity/account/k.smali:172:    invoke-virtual {v0}, Lcom/immomo/momo/android/activity/account/LoginActivity;->f(
com.immomo.momo/smali/com/immomo/momo/android/activity/account/k.smali:183:    invoke-virtual {v0}, Lcom/immomo/momo/android/activity/account/LoginActivity;->f(

Place trace codes to these 4 points. And we know it is account.h(325) that call LoginActivity;->f().

Look at account.h, it is somewhat similar to account.k, both being a child class of android.c.d. Its key method a([Ljava/lang/Object;)Ljava/lang/Object which is overriden by account.h, needed to added trace code for its phase. Repack and run it again, and we see

    invoke-virtual {v1, v2, v3, v4, v0}, Lcom/immomo/momo/protocol/a/ac;->a(Lcom/immomo/momo/service/bean/bq;Ljava/lang/String;ILjava/lang/String;)V

never returns.

Look at ac;->a(Lcom/immomo/momo/service/bean/bq;Ljava/lang/String;ILjava/lang/String;)V, and find that it call

invoke-virtual {p0, v4, v0, v5, v3}, Lcom/immomo/momo/protocol/a/ac;->a(Ljava/lang/String;Ljava/util/Map;[Lcom/immomo/momo/protocol/a/o;Ljava/util/Map;)Ljava/lang/String; 

And started to get fields like “data”,”profile”etc。So we can add codes to print v4, v0, v3 before calling ac;->a(…). What do we see?

07-06 19:36:50.323: I/LogUtils.printLog(12853): com/immomo/momo/protocol/a/ac;->a(Lcom/immomo/momo/service/bean/bq;Ljava/lang/String;ILjava/lang/String;)V  v0:: {timestamp=1404646791, time=1404646791, code=AF304744B244584489B16C438D680686C4441D88B9E888B08812DCC8CD066386889A6660C80AB182534E8A4827D4281BE4A0720EC80DA9E4078847226E441644DEAD7B6B5CF65BDEADADA5C5B6BDB1448E88DA1B850E888522666823666686912A6E240C6407A81546A2D0198450C850C1C4A6118813C6641A447444234BC822DE}

The point lie in the fact what does the code=AF30… mean?

    invoke-virtual {v0, v3, v4}, Ljava/util/HashMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;

    const-string v3, "code"

    invoke-virtual {v0, v3, p4}, Ljava/util/HashMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;

p4 is the “code”value. Back to account.h, p4 is the v0 of

    invoke-virtual {v1, v2, v3, v4, v0}, Lcom/immomo/momo/protocol/a/ac;->a(Lcom/immomo/momo/service/bean/bq;Ljava/lang/String;ILjava/lang/String;)V

How is v0 set?

    invoke-static {v0, v1}, Lcom/immomo/momo/util/jni/Codec;->gdwititwie(Ljava/lang/Object;I)[B 

    move-result-object v0

So a jni function gdwititwie(…) is called get “code” value?

Ah, gdwititwie is implemented in a so.  which so?

$ grep gdwititwie  com.immomo.momo -r|grep so

匹配到二进制文件 com.immomo.momo/lib/armeabi/

Idapro can be used to open a so file. But Idapro 6.1 has issues to dynamically debug a so. I have no higher version than 6.1. gikdbg.arg is a great alternative, though it is being developed and not stable now.

Using idapro we know gdwititwie is at offset 34cc. And Alt+M tell us that is loaded at 51397000



image         image 

One from, one from idapro.  They are identical, so we can conclude that we identify the correct breakpoint for gdwititwie.

If u have difficulty to do static analysi for gdwititwei|, u now can do dynamic analysis for gdwititwie| with the help of

The logic of gdwititwie is to construct a string of format:

{“did”:”<did>hexmd5sum”,”pack”:”<pack>”,”s”:”<signature>hexmd5sum”,“ts”:”<ts>”, “e”:”<e>”}

So the point is to locate the place where <signature>hexmd5sum is calculated.

And we can send the original apk’s signature to momo server. How do we calculate the original apk’s signature?

There are 2 ways to calculate apk’s signature.

  1. using PackageManger



  2. using PackageParser

    look at com/immomo/momo/f;->ad()
  3. It can take an apk’s path and caculate the signature.

So we can use way2 to calculate legal momo’s signature, then do a md5 sum, and send it to momo server. It is “4F3A531CAFF3E37C278659CC78BFAECC”.

3E02 is the place where current apk’s signature string is got, and prepare to calculate its md5sum.

3E02-3E43 are the codes to get md5sum. and jump to 3C12 to get the md5sum hex.

So we know 3E02-3E43 can be patched to set the legal apk’s md5sumhex, then jump to 3C18 to continue the normal code calculation process.

Here is our patched code.

.text:00003E02                 ADD     R0, SP, #0x248+dest ; dest
.text:00003E04                 LDR     R1, =(a4f3a531caff3e3 - 0x3E0A)
.text:00003E06                 ADD     R1, PC          ; "4F3A531CAFF3E37C278659CC78BFAECC"
.text:00003E08                 BLX     strcpy
.text:00003E0C                 LDR     R0, =(a4f3a531caff3e3 - 0x3E12)
.text:00003E0E                 ADD     R0, PC          ; "4F3A531CAFF3E37C278659CC78BFAECC"
.text:00003E10                 B       loc_3C18
.text:00003E10 ; ---------------------------------------------------------------------------
.text:00003E12 a4f3a531caff3e3 DCB "4F3A531CAFF3E37C278659CC78BFAECC",0
.text:00003E12                                         ; DATA XREF: Java_com_immomo_momo_util_jni_Codec_gdwititwie+93Ao
.text:00003E12                                         ; Java_com_immomo_momo_util_jni_Codec_gdwititwie+942o ...
.text:00003E33                 DCB 0
.text:00003E34 off_3E34        DCD a4f3a531caff3e3 - 0x3E12
.text:00003E34                                         ; DATA XREF: Java_com_immomo_momo_util_jni_Codec_gdwititwie+940r
.text:00003E34                                         ; "4F3A531CAFF3E37C278659CC78BFAECC"
.text:00003E38 off_3E38        DCD a4f3a531caff3e3 - 0x3E0A
.text:00003E38                                         ; DATA XREF: Java_com_immomo_momo_util_jni_Codec_gdwititwie+938r
.text:00003E38                                         ; "4F3A531CAFF3E37C278659CC78BFAECC"
.text:00003E3C                 DCD 0, 0

Until now is modified and is used to replace the original

No “账号安全验证”is required。

It is done!