
在
上一篇文章中,我对OWASP Mobile TOP 10进行了回顾,然后我没有合适的案例来说明保护源代码的必要性。 一个有趣的示威案例直到最近才出现,并且有兴趣了解我们规避环境检查的经验的人,让我们深入探讨一下。
在评估其中一个项目的绩效时,我们的团队立即意识到这种情况并不容易。 开发人员很好地解决了程序中的信息安全性问题,并对执行环境的状态进行了检查。 在以下任何一种情况下,应用程序都无法启动:
- 该设备被车辙;
- 使用了仿真器;
- 通过USB连接的可用性;
- 使用开发人员模式。
开发人员没有混淆源代码,也没有内置的代码修改检查,这使我能够分析执行检查的方法并对其进行必要的操作。
因此,让我们开始吧。 根据OWASP Mobile TOP 10(我们在逆向工程学Hacken中用作基础测试方法),此漏洞包括分析二进制文件以确定源代码,库,算法等。 诸如IDA Pro,Hopper,otool和其他逆向工程工具之类的软件可以使您了解应用程序的内部操作。 这可用于搜索应用程序漏洞,提取关键信息,例如后端服务器,加密密钥或知识产权。
为了进行基本的静态分析,我使用了MobSF这样有趣的工具,该工具执行反编译和基本的静态分析。 反编译之后,我对程序的java和smali代码感兴趣。 分析需要Java代码,我们将对smali代码进行更改。 有关smali和java的关系的更多详细信息,请参见
此处 。
在查看类列表时,我发现了一个文件,该文件负责检查电话的例程(请参见图1)-rootingcheck / RootBeerNative.java。
图 1.应用程序类别列表在分析了该类之后,很明显,我们需要进一步查找对checkForRoot()和setLogDebugMessage()函数的调用(请参见图2)。
图 2.用于检查rutovanost的类的源代码使用grep命令,我们得到以下结果,该结果显示了哪些文件包含对checkForRoot()和setLogDebugMessage()方法的调用。
搜索结果:root @ kali:〜/桌面#grep -nr'RootBeerNative'******** _ v_0.9.2 /
********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:1:.class public Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:17: sput-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:28: sput-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:57: sget-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/o/CM.smali:591: new-instance v1, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:593: invoke-direct {v1}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:685: new-instance v0, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:687: invoke-direct {v0}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:689: invoke-static {}, Lrootingcheck/RootBeerNative;->?()Z ********_v_0.9.2/smali/o/CM.smali:753: new-instance v4, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:755: invoke-direct {v4}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:764: invoke-virtual {v4, v3}, Lrootingcheck/RootBeerNative;->checkForRoot([Ljava/lang/Object;)I ********_v_0.9.2/smali/o/xZ$5.smali:257: new-instance v1, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/xZ$5.smali:259: invoke-direct {v1}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/xZ$5.smali:261: invoke-static {}, Lrootingcheck/RootBeerNative;->?()Z
root @ kali:〜/桌面#grep -nr'setLogDebugMessages'******** _ v_0.9.2 / ********_v_0.9.2/smali/o/CM.smali:599: invoke-virtual {v1, v0}, Lrootingcheck/RootBeerNative;->setLogDebugMessages(Z)I ********_v_0.9.2/smali/o/CM.smali:761: invoke-virtual {v4, v0}, Lrootingcheck/RootBeerNative;->setLogDebugMessages(Z)I
但这并不是全部检查。 在分析了MainActivity.java类之后,我们发现了函数调用,在该函数调用中传递了字符串“ su”,“测试键”和“哪个”,并借助它们执行了检查(见图3)。
图3。 例行检查再次,使用grep命令,我们在smali文件中检查例程:
搜索结果:root @ kali:〜/桌面#grep -nr'su'******** _ v_0.9.2 / ********_v_0.9.2/smali/o/CM.smali:443: const-string v2, "su" ********_v_0.9.2/smali/o/CM.smali:706: const-string v2, "su" ********_v_0.9.2/smali/o/xZ$5.smali:172: const-string v1, "su" ********_v_0.9.2/smali/o/xZ$5.smali:347: const-string v0, "su"
root @ kali:〜/桌面#grep -nr'test-keys'******** _ v_0.9.2 / ********_v_0.9.2/smali/o/xZ$5.smali:141: const-string v1, "test-keys" ********_v_0.9.2/smali/o/xZ$5.smali:374: const-string v0, "test-keys"
root @ kali:〜/桌面#grep -nr'哪个'******** _ v_0.9.2 / ********_v_0.9.2/smali/o/CM.smali:437: const-string v2, "which"
在本文中,我将仅显示找到的对常规检查的一种修改。 经过一点操作,即从1更改为0,便删除了常规检查。
图 4.如果手机已植根,则变量的值等于一
图 5.现在,如果手机已植根,则变量的值为零之后-可以组装程序,使用释放键签名并在手机上运行。 但是,如果不是两个但! 即:
- USB连接检查;
- 检查是否包含开发人员模式-USB连接和随附的开发人员模式允许动态分析。
通过与常规检查相同的方式关闭开发人员模式检查-通过将检查中的单位更改为零
在MainActivity.java类中,我们找到负责检查Developer模式的行(请参见图6)。 之后,请查找其中包含字符串“ development_settings_enabled”的文件,然后修改检查-将1更改为0(见图7和8)。
图 6.检查手机上是否启用了开发人员模式搜索结果:grep -nr“ development_settings_enabled” ******** _ v_0.9.2 \ Binary file ********_v_0.9.2\/build/apk/classes.dex matches ********_v_0.9.2\/smali/o/xZ$1.smali:49: const-string v1, "development_settings_enabled"
图 7.您需要进行修改的地方
图 8.修改完成所有操作后,您可以在开发人员模式下运行该程序。
接下来,关闭USB连接检查。 该检查在MainActivity.java类中(请参见图9)。 如果没有grep,则在MainActivity.smali中找到该行,然后找到包含带有USB检查的行的行-android.hardware.usb.action.USB_STATE。 之后,在smali代码中,我们将行修改为其他任何返回“ false”的权限(请参见图10)。
图 9.在MainActivity.java代码中检查USB连接
图 10. MainActivity.smali中要删除的代码行现在剩下的工作就是生成发布密钥并使用它对应用程序进行签名。 这样做如下:
- 您需要安装两个应用程序:Keytool和Jarsinger。
- 运行命令以组装应用程序:
- apktool b C:\用户\用户\桌面\ ********
- 下一个:cd ******** \ dist \
- 下一步:Keytool.exe -genkey -alias key.keystore -keyalg RSA -validity 20000 -keystore key.keystore
- 下一步:Jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore key.keystore ********。apk key.keystore
- 下一步:jarsigner -verify -verbose -certs ********。Apk
原则上,这里所有的操作都已完成。 现在,我们使用adb install或从智能手机目录在手机上安装该应用程序,您可以进行动态漏洞测试。
安装应用程序后,运行它(请参见图11和图12)。
结论在一个实际的示例中,我展示了如何禁用运行时状态的某些检查。 此外,在其他工具的帮助下,我们对漏洞进行了分析,但这是另一回事……
对代码保护的疏忽态度可能导致:
- 这些是程序中嵌入的某些检查的规避
- 实施第三方代码,之后该程序可以发布并用作恶意代码
我该如何保护自己? 在
ByteCode,我们决定不重新发明轮子,建议客户端混淆源代码并使用检查源代码修改的功能。
聚苯乙烯
您可以使用更高级的分析方法-这是smali调试。 您可以在
手册中了解更多信息。
作为参考,我制定了一个行列表以用于检查例程:
- “测试键”;
- “ /system/app/Superuser.apk”;
- “ / sbin / su”;
- “ / system / bin / su”;
- “ / system / xbin / su”;
- “ /数据/本地/ xbin / su”;
- “ /数据/本地/ bin / su”;
- “ / system / sd / xbin / su”;
- “ /系统/箱/故障安全/苏”;
- “ /数据/本地/ su”;
- “ / su / bin / su”;
- “ / system / xbin /其中”;
- “苏”;
- “哪个”。