Locus Pro v3.20国内无法使用的修改办法

Locus Pro v3.20 修改方法

目标

  • 解决国内无法动态下载so文件导致无法启动的问题
    • 使用Apk的全部功能

使用工具

  • apktools

    这里不详细介绍apktools的用法。需要注意的一点是:因为Locus的代码在混淆过程中使用了不可见utf-8字符,apktools工具(实际使用的android的自带的资源打包工具aapt)无法把解开的资源重新打包,所以在解包时建议需要使用-r参数。

修改步骤

  • 解除签名校验

Android apk都需要进行证书签名。Locus在代码中检查了签名证书的hash值,来判断apk是不是被二次打包。

目前Locus内部检查了3个证书的hash值

  1. 0x1a222754

  2. -0x100cbe4d

  3. -0x53ad97d7

用全文查找工具,在smali代码中寻找包含上述字符串的文件。v3.20.1中是o/aoj.3.smali。

找到如下

1
2
3
4
invoke-virtual {v0}, Landroid/content/pm/Signature;->hashCode()I
move-result v0
const v1, 0x1a222754
if-ne v0, v1, :cond_2

把上述代码修改为

1
2
3
4
5
invoke-virtual {v0}, Landroid/content/pm/Signature;->hashCode()I
move-result v0
const v0, 0x1a222754
const v1, 0x1a222754
if-ne v0, v1, :cond_2

因为三个证书任何一个匹配即可,所以这里修改一处即可以了。

  • 修改so库的加载方式

    因为Locus会动态更新so库。所以代码中使用了从App包中加载so库的方式。

    locus 动态加载了两个库: “libproj”和”libjsqlite”。

    用全文搜索工具搜索”proj”和“jsqlite”。为了更容易的找到目标,搜索时记得不要忘记引号。

    比如搜索字符串”jsqlite”,找到文件jsqlite/Database.smali。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    .method static constructor <clinit>()V
    .locals 5

    .line 1122
    const-string v3, "proj"

    .line 1134
    const-string v0, "lib"

    :try_start_0
    invoke-static {v0, v3}, Lo/Ὶ;->ᐝ(Ljava/lang/String;Ljava/lang/String;)Ljava/io/File;

    move-result-object v4

    .line 1135
    invoke-static {v4}, Lo/ﮋ;->ˌ(Ljava/io/File;)Z

    move-result v0

    if-eqz v0, :cond_0

    .line 1136
    invoke-virtual {v4}, Ljava/io/File;->getAbsolutePath()Ljava/lang/String;

    move-result-object v0

    invoke-static {v0}, Ljava/lang/System;->load(Ljava/lang/String;)V

    goto :goto_0

    .line 1138
    :cond_0
    invoke-static {v3}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

    .line 2128
    :goto_0
    const-string v3, "jsqlite"

    .line 2134
    const-string v0, "lib"

    省略部分代码
    ......

    .line 959
    return-void
    .end method

    现在修改为直接从apk包中加载。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    .method static constructor <clinit>()V
    .locals 5
    .line 1122
    const-string v0, "proj"
    invoke-static {v0}, Ljava/lang/System;->load(Ljava/lang/String;)V

    const-string v0, "jsqlite"
    invoke-static {v0}, Ljava/lang/System;->load(Ljava/lang/String;)V
    .line 959
    return-void
    .end method

    这里需要注意,不要忘记修改临时变量(v0, v1),使调用保持一致。

不要忘了搜索”proj”, 做相应处理。

  • 寻找启动时下载so文件的地方

    全文搜索”_libraries.conf”字符串,找到相应文件。v3.20.1里面该文件名不可见utf-8字符o/Ὶ.1.smali。

    3.19以前的版本,这个文件和加载libproj.so和libjsqlite.so的文件是同一个文件。

    3.20开始,分布到3个文件当中了。

    找到包涵”_libraries.conf”的方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    .method public static ᵊ()Z
    .locals 11

    .line 1047
    new-instance v4, Ljava/io/File;

    invoke-static {}, Lo/aly;->getContext()Landroid/content/Context;

    move-result-object v0

    invoke-virtual {v0}, Landroid/content/Context;->getFilesDir()Ljava/io/File;

    move-result-object v0

    const-string v1, "_libraries.conf"

    invoke-direct {v4, v0, v1}, Ljava/io/File;-><init>(Ljava/io/File;Ljava/lang/String;)V

    .line 1048
    invoke-virtual {v4}, Ljava/io/File;->exists()Z

    这里省略了部分代码
    ......
    .line 1104
    invoke-static {v4}, Lo/ﮋ;->゙(Ljava/io/File;)Z

    .line 1107
    const/4 v0, 0x1

    return v0
    .end method

    修改为:

    1
    2
    3
    4
    5
    .method public static ᵊ()Z 
    .locals 11
    const/4 v0, 0x1
    return v0
    .end method
  • 隐藏数据下载界面

    进入smali/com/asamm/locus/core/目录

    打开所有StartScreen$开头的smali文件。

    在里面查找字符串”public ʽ(ZZ)Z”(不包含引号)。

    在找到的文件里面,寻找public ʽ(ZZ)Z调用了上一步修改的函数方法的文件。

    v3.20.1版本中找到的方法如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    .method public ʽ(ZZ)Z
    .locals 2

    .line 1405
    if-eqz p1, :cond_0

    .line 1406
    const/4 v0, 0x1

    return v0

    .line 1410
    :cond_0
    invoke-static {}, Lo/Ὶ;->ᵊ()Z

    move-result v0

    if-nez v0, :cond_1

    .line 1411
    const/4 v0, 0x1

    return v0

    .line 1415
    :cond_1
    if-eqz p2, :cond_2

    invoke-static {}, Lo/arq;->alG()Z

    move-result v0

    if-eqz v0, :cond_2

    invoke-static {}, Lcom/asamm/locus/core/StartScreen;->fT()Lcom/asamm/locus/core/StartScreen$ˏ;

    move-result-object v0

    invoke-virtual {v0}, Lcom/asamm/locus/core/StartScreen$ˏ;->gd()I

    move-result v0

    const/16 v1, 0xa

    if-ge v0, v1, :cond_2

    .line 1417
    const/4 v0, 0x1

    return v0

    .line 1421
    :cond_2
    const-string v0, "com.asamm.locus.utils.Const"

    invoke-static {v0}, Lo/anE;->ˋ(Ljava/lang/String;)Ljava/lang/Class;

    move-result-object v0

    const-string v1, "cKz"

    invoke-virtual {v0, v1}, Ljava/lang/Class;->getField(Ljava/lang/String;)Ljava/lang/reflect/Field;

    move-result-object v0

    const/4 v1, 0x0

    invoke-virtual {v0, v1}, Ljava/lang/reflect/Field;->getBoolean(Ljava/lang/Object;)Z

    move-result v0

    return v0
    .end method

    注意第10行(不包含空行)

    1
    invoke-static {}, Lo/Ὶ;->ᵊ()Z

    如果幸运的话,上一步找到的文件的文件名是可见的utf-8字符,这里更容易确认。

    把上述方法中的

    1
    const/4 v0, 0x1

    修改为

    1
    const/4 v0, 0x0
  • 替换so文件

    把v3.20.1修改版本中的so文件替换到新版本中覆盖。删除lib下的armeabi、mips和x86目录。因为我们没有这3类CPU对应的so文件。所以修改版,在这3类CPU下面是不能运行的。

  • 修改libmacore.so

    本文不作讨论。直接使用旧修改版本中的替换即可。

至此,修改工作完成。