蓝天资源网
当前位置:蓝天资源网 / 汇编逆向 / 正文

疯读小说 简单去除签名校验

作者:忆笙发布时间:2021-10-10 01:16浏览数量:461次评论数量:0次

准备工具

1、as

2、ida

软件样品为最新版1.1.3.3,重签名后没有闪退,只是没有网络,也就是不能联网了,可能是遇到了网络校验。


搜索一下signatures,dex和so都有这个字符串,看了一下dex没什么关键位置。那就剩so了,这时用ida打开libeaster_egg.so,输出表搜索Java开头的内容,有2个。

疯读小说 简单去除签名校验  第1张

如上图,Java_com_cootek_library_core_EasterEgg_init和Java_com_cootek_library_core_EasterEgg_sign实际上就是校验的老巢了,可以顺着Java路径去看一下在哪。

首先init方法的类型是boolean,所以返回的值不是0就是1,从结果上来看肯定是1。伪代码如下:

jboolean __fastcall Java_com_cootek_library_core_EasterEgg_init(JNIEnv *env, jobject a2, jobject context_object)
{
  v5 = (*env)->GetObjectClass(env, context_object);
  v6 = getPackageManager(env, context_object, v5);
  if ( v6 )
  {
    v7 = v6;
    v8 = getPackageName(env, v5, context_object);
    if ( v8 )
    {
      v9 = v8;
      (*env)->DeleteLocalRef(env, v5);
      v10 = getPackageInfo(env, v7, v9);
      if ( v10 )
      {
        v11 = v10;
        (*env)->DeleteLocalRef(env, v7);
        v12 = getSignature(env, v11);
        if ( v12 )
        {
          v13 = v12;
          (*env)->DeleteLocalRef(env, v11);
          v14 = getSHA1(env, v13);
          v15 = digest(env, "SHA1", v14);
          if ( !strcmp(v15, "aa071286d8307ba8c28d13f88e8f53dbf9e5619a")
            || !strcmp(v15, "21ab588fc1114119fae40be76fd9f18b63a1ca48") )
          {
            v16 = (*env)->GetStringUTFChars(env, v9, 0);
            if ( !strcmp(v16, "com.cootek.crazyreader") )
            {
              v17 = 1;
              isInit = 1;
              secret = "B1w2OjLnERw6fXfl";
              _android_log_print(4, "APISECURITY", unk_14441);
              return v17;
            }
            _android_log_print(6, "APISECURITY", byte_14426, v16);
          }
          else
          {
            _android_log_print(6, "APISECURITY", unk_143E6, v15);
          }
        }
      }
    }
  }
  return 0;
}

21ab588fc1114119fae40be76fd9f18b63a1ca48就是正确sha1值,如果对比结果正确则运行到return v17,又因为v17=1,所以返回的结果会是1。可以把这个sha1值改成你自己的,也可以修改判断逻辑。

不过仅仅这样改好像这帖子太水了,所以换另一种改法,修改dex里面的native方法。

ida进入sign表,代码如下:

jstring __fastcall Java_com_cootek_library_core_EasterEgg_sign(JNIEnv *env, jobject a2, jstring str)
{
  if ( isInit )     //首先判断isInit的值,从上面可以知道应该为1
  {
    v4 = (*env)->GetStringUTFChars(env, str, 0);
    v5 = strlen(v4);
    v6 = strlen(secret) + v5 + 1;    //读取字符串长度,从上面可以知道secret的值
    v7 = operator new[](v6);
    memset(v7, 0, v6);
    v8 = strcat(v7, v4);            //strcat拼接,v8就是传入的字符串
    v9 = strcat(v8, secret);       //strcat拼接字符串,输出为v8加上secret
    v10 = strlen(v9);
    v11 = (*env)->NewByteArray(env, v10);
    (*env)->SetByteArrayRegion(env, v11, 0, v10, v7);
    v12 = digest(env, MD5, v11);     //进行md5加密
    v13 = (*env)->NewStringUTF;
  }
  else
  {
    _android_log_print(6, "APISECURITY", byte_14454);
    v13 = (*env)->NewStringUTF;
    v12 = &unk_14467;
  }
  return v13(env, v12);     //返回结果
}

双击digest进入,代码如下:

digest(JNIEnv *env, const unsigned __int8 *algorithm, jbyteArray cert_byte)
{
  v5 = (*env)->FindClass(env, "java/security/MessageDigest");
  v6 = (*env)->GetStaticMethodID(env, v5, "getInstance", "(Ljava/lang/String;)Ljava/security/MessageDigest;");
  (*env)->NewStringUTF(env, algorithm);
  v7 = _JNIEnv::CallStaticObjectMethod(env, v5, v6);
  v8 = (*env)->GetMethodID(env, v5, "digest", "([B)[B");
  v9 = _JNIEnv::CallObjectMethod(env, v7, v8);
  (*env)->DeleteLocalRef(env, v5);
  v10 = (*env)->GetArrayLength(env, v9);
  v11 = 0;
  v12 = (*env)->GetByteArrayElements(env, v9, 0);
  v13 = operator new[](2 * v10 + 1);
  memset(v13, 0, 2 * v10 + 1);
  v14 = v13;
  while ( v11 < v10 )
  {
    sprintf(v14, "%02x", v12[v11]);
    v14 += 2;
    ++v11;
  }
  return v13;
}

这是一个常规的md5加密方案,所以呢可以将c语言变成Java并剔除无用代码:

public static String sign(String str) throws Exception {
        MessageDigest MD5 = MessageDigest.getInstance("MD5");
        MD5.update((str + "B1w2OjLnERw6fXfl").getBytes());
        return new BigInteger(1, MD5.digest()).toString(16);
    }
.method public static sign(Ljava/lang/String;)Ljava/lang/String;
    .registers 5
    .annotation system Ldalvik/annotation/Throws;
        value = {
            Ljava/lang/Exception;
        }
    .end annotation

    .line 7
    const-string v1, "MD5"

    invoke-static {v1}, Ljava/security/MessageDigest;->getInstance(Ljava/lang/String;)Ljava/security/MessageDigest;

    move-result-object v0

    .line 8
    new-instance v1, Ljava/lang/StringBuilder;

    invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V

    invoke-virtual {v1, p0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v1

    const-string v2, "B1w2OjLnERw6fXfl"

    invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v1

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-virtual {v1}, Ljava/lang/String;->getBytes()[B

    move-result-object v1

    invoke-virtual {v0, v1}, Ljava/security/MessageDigest;->update([B)V

    .line 9
    new-instance v1, Ljava/math/BigInteger;

    const/4 v2, 0x1

    invoke-virtual {v0}, Ljava/security/MessageDigest;->digest()[B

    move-result-object v3

    invoke-direct {v1, v2, v3}, Ljava/math/BigInteger;-><init>(I[B)V

    const/16 v2, 0x10

    invoke-virtual {v1, v2}, Ljava/math/BigInteger;->toString(I)Ljava/lang/String;

    move-result-object v1

    return-object v1
.end method

将smali代码回填navati以后就可以正常浏览小说了

像去广告之类的教程我就不发了,因为以前有发过通杀方法,就不重复再说了。

忆笙

忆笙 主页 联系他吧

人间山河远阔,只想与你同行。

欢迎 发表评论: