吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2574|回复: 7
收起左侧

[Android 原创] 基于Frida的锁机软件算法分析

  [复制链接]
fengchuan 发表于 2023-8-20 12:44

!!!锁机软件有一定风险,一定要在模拟器上打开,千万不要用自己的手机安装!!!
这个软件会有关闭usb调试、调大声音、不健康画面等。解压密码:52pojie

image.png
拿到样本之后,首先进行静态分析,将软件拖入到jadx和jeb中。从AndroidManifest.xml文件中可以看到软件的包名、申请的权限以及程序的入口。
image.png
然后我们跳到MainActivity类中,也就是程序的入口。代码如下,代码很简单,主要就说注册了一个服务,服务主要的功能就是启动了名为com.shimeng.qq2693533893.MyServiceOne的服务类。

public class MainActivity extends Activity {
    @Override // android.app.Activity
    protected void onCreate(Bundle bundle) {
        LogCatBroadcaster.start(this);
        super.onCreate(bundle);
        try {
            startService(new Intent(this, Class.forName("com.shimeng.qq2693533893.MyServiceOne")));
        } catch (ClassNotFoundException e) {
            throw new NoClassDefFoundError(e.getMessage());
        }
    }
}

那么接下来就跳到启动的服务类中去看看,MyServiceOne代码量就很大了,从一些关键词之类的东西可以分析出来这里就是主要的锁机部分了,看源码可以看出作者的攻击性还是很强的 - -|||。
分析到这其实静态分析就差不多了,接下来就结合Frida和Objection进行动态分析。
首先,因为程序一开始就只是启动了一个服务,那我们就使用objection从services来入手进行分析。
列出程序的所有services,可以看到只有一个,那我们就对这个类进行hook

#查看所有的services
com.shimeng.qq2693533893 on (vivo: 9) [usb] # android hooking list services
com.shimeng.qq2693533893.MyServiceOne
#hook com.shimeng.qq2693533893.MyServiceOne 类
com.shimeng.qq2693533893 on (vivo: 9) [usb] # android hooking watch class com.shimeng.qq2693533893.MyServiceOne --dump-
args --dump-backtrace --dump-return

hook了MyserviceOne类之后,我们可以看到程序一直在调用access$L1000018方法,我们来看看这个方法具体是什么。因为在jadx中没有找到这个方法,就使用jeb来进行分析。
image.png
这样我们就找到了程序真正做事情的地方了,可以看到这里设置了音量等。
接下来我们继续分析解锁按钮做了什么事情,我们在输入框中随便输入一些东西,然后点击解锁,可以看到objection显示出了调用的一些函数,我们排除掉access$L1000018,这里的调用是从上往下的调用,可以看到首先调用了颜如玉这个函数。

(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.颜如玉(java.lang.String)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.SHA1(java.util.Map)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.getOrderByLexicographic(java.util.Map)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.getParamsName(java.util.Map)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.lexicographicOrder(java.util.List)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.splitParams(java.util.List, java.util.Map)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.颜如玉(java.lang.String)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.SHA1(java.util.Map)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.getOrderByLexicographic(java.util.Map)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.getParamsName(java.util.Map)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.lexicographicOrder(java.util.List)
(agent) [867288] Called com.shimeng.qq2693533893.MyServiceOne.splitParams(java.util.List, java.util.Map)

image.png
首先我们先静态分析一下源码,找到这个函数,进行交叉引用,可以看到只有com.shimeng.qq2693533893.MyServiceOne$100000002.onClick()这个函数调用了这个方法,然后那么接下来我们再对这个函数进行hook,看看它的调用堆栈情况。结果如下,和我们静态分析的结果是一样的。

com.shimeng.qq2693533893 on (vivo: 9) [usb] # android hooking watch class_method com.shimeng.qq2693533893.MyServiceOne.
颜如玉 --dump-args --dump-backtrace --dump-return
(agent) Attempting to watch class com.shimeng.qq2693533893.MyServiceOne and method 颜如玉.
(agent) Hooking com.shimeng.qq2693533893.MyServiceOne.颜如玉(java.lang.String)
(agent) Registering job 350829. Type: watch-method for: com.shimeng.qq2693533893.MyServiceOne.颜如玉
com.shimeng.qq2693533893 on (vivo: 9) [usb] # (agent) [350829] Called com.shimeng.qq2693533893.MyServiceOne.颜如玉(java.lang.String)
(agent) [350829] Backtrace:
        com.shimeng.qq2693533893.MyServiceOne.颜如玉(Native Method)
        com.shimeng.qq2693533893.MyServiceOne$100000002.onClick(MyServiceOne.java:186)
        android.view.View.performClick(View.java:6599)
        android.view.View.performClickInternal(View.java:6576)
        android.view.View.access$3100(View.java:780)
        android.view.View$PerformClick.run(View.java:25899)
        android.os.Handler.handleCallback(Handler.java:873)
        android.os.Handler.dispatchMessage(Handler.java:99)
        android.os.Looper.loop(Looper.java:193)
        android.app.ActivityThread.main(ActivityThread.java:6730)
        java.lang.reflect.Method.invoke(Native Method)
        com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        com.android.internal.os.ZygoteInit.main(ZygoteInit.java:860)

(agent) [350829] Arguments com.shimeng.qq2693533893.MyServiceOne.颜如玉(9B480C226E220FA9CD301C87D64FB3B9)
(agent) [350829] Return Value: 7A2AADD4840E0AF67E2F86A387E099418DB118E1

我们在jeb中找到这个函数,可以看到这里就是解锁的主体部分了,其中,onclick函数在100000002类中,100000002类是由sm函数调用的。
image.png
通过源码可以得出结论,如果想要解锁,就要使得下面这串代码结果为真。

if(颜如玉QQ2693533893.getSaltMD5(MyServiceOne.颜如玉(v2.substring(0, 3))) + v2.substring(3, v2.length()).equals("9DDEB743E935CE399F1DFAF080775366" + v3_1))

我们来分析其中的参数都是从哪里来的,具体见下图,可以看到主要由两部分组成,一部分是我们的输入,一部分是随机值。我们的输入的前三位通过颜如玉MD5函数的处理之后,应该需要等于9DDEB743E935CE399F1DFAF080775366这个值。颜如玉这个函数我们前面已经分析过了,主要就是取了一个sha1,那么由此我们可以推断要求我们输入的前3位应该是固定的。具体的值我们就需要跑一下了。
image.png
通过这个函数我们就可以获取前三位的值了,结果是358。有了前三位,接下来我们就分析后面的部分。

function md5(){
    Java.perform(function(){
        var javaStr = Java.use('java.lang.String')
        for(var i = 100;i<1000;i++){
            var i_str = javaStr.$new(String(i));
            var MyServiceOne = Java.use('com.shimeng.qq2693533893.MyServiceOne');
            var yry = Java.use('com.shimeng.颜如玉.颜如玉QQ2693533893');
            var sha1 = MyServiceOne.颜如玉(i_str);
            var md5 = yry.getSaltMD5(sha1);
            if(md5 == '9DDEB743E935CE399F1DFAF080775366'){
                console.log(i);
                break;
            }
        }
    })
}

后半部分需要让输入中的第4位到最后一位等于通过将随机数加密后截取0-9位的值,在sm函数中可以看到,生成的随机数通过颜如玉QQ2693533893.get函数变成了屏幕上的识别码,所以我们这里还要遍历一下来获取随机数。具体做法如下,得到我们的识别码为5035。有了这些,我们就可以来生成解密的密钥了

function random(){
    Java.perform(function(){
        var javaStr = Java.use('java.lang.String')
        for(var i = 1000;i<10000;i++){
            var i_str = javaStr.$new(String(i));
            var yry = Java.use('com.shimeng.颜如玉.颜如玉QQ2693533893');
            var code = yry.get(i_str);
            if(code == '©嘻∷©'){//识别码随机
                console.log(i);
                break;
            }
        }
    })
}

生成密钥:

function getKey1(){
    Java.perform(function(){
        var javaStr = Java.use('java.lang.String')
        var i_str = javaStr.$new(String(5035 ^ 1288));
        var yry = Java.use('com.shimeng.颜如玉.颜如玉QQ2693533893');
        var MyServiceOne = Java.use('com.shimeng.qq2693533893.MyServiceOne');
        var code = yry.getSaltMD5(i_str);
        var v3 = MyServiceOne.颜如玉(code);
        var v3_1 = javaStr.$new(v3).replaceAll("\\D+", "").substring(0, 9);
        console.log('358' + v3_1);
    })
}

生成密钥,输入,解锁,一气呵。。。???还没完。。还有第二层,mmp
image.png
好吧,那就继续吧。有了之前的经验,第二层其实很容易,从第一层可以分析出,第二层是从sm2函数来进行的。和第一层的识别码如出一辙,只需要把之前的脚本在跑一遍得出识别码的随机数。
image.png
这样我们就得到了第二层的密钥。

function getKey2(){
    Java.perform(function(){
        var javaStr = Java.use('java.lang.String')
        var i_str = javaStr.$new(String(2750));//随机数
        var yry = null;
        var v2 = '';
        Java.choose("com.shimeng.颜如玉.颜如玉QQ2693533893",{
            onMatch: function(instance){
                console.log("find instance",instance);
                yry = instance;
            },
            onComplete: function(){}
        })
        var code = yry.getTwiceMD5ofString(i_str);
        var v3 = yry.hex_sha1(code);
        var v3_1 = javaStr.$new(v3).replaceAll("\\D+", "").substring(0, 9);
        for(var i=100;i<1000;i++){
            var i_str = javaStr.$new(String(i));
            code = yry.getTwiceMD5ofString(yry.hex_sha1(i_str));
            if(code == '8D4FF507DCDA63C201EB8B99D4170900'){
                v2 = i_str;
            }
        }
        console.log(v2 + v3_1);
    })
}

生成密钥,输入,解锁,一气呵。。。呵呵???还没完。。还有第三层
image.png
好吧,那就继续!小东西!
通过第二层的解锁代码部分,我们可以看到调用的是诗梦这个函数,这个函数的解锁部分如下:
image.png
两个条件满足一个即可

  • MyServiceOne.this.坐等前往世界的尽头的小船 = 187724addd757b99a9dc1eb570c65f32c33f5941
  • 颜如玉QQ2693533893.hex_sha1(v0.val$fuck.getText().toString()).equals(MyServiceOne.this.坐等前往世界的尽头的小船)
    这个其实很简单了,第一种我们直接使用frida查找MyServiceOne的实例,然后把坐等前往世界的尽头的小船这个变量赋值即可。第二种我们就需要把坐等前往世界的尽头的小船这个值赋值为我们指定的值取sha1。
    两种解决方案的脚本如下:
    function hookGet(){
    Java.perform(function(){
        var javaStr = Java.use('java.lang.String');
        var passwd = javaStr.$new(String(123456));
        var passwdSign = Java.use('com.shimeng.颜如玉.颜如玉QQ2693533893').hex_sha1(passwd);
        //第一种
        Java.choose("com.shimeng.qq2693533893.MyServiceOne",{
            onMatch: function(instance){
                console.log('find instance',instance);
                instance.坐等前往世界的尽头的小船.value = passwdSign;
            },
            onComplete: function(){
                console.log('search completed!')
            }
        });
        //第二种
        Java.choose("com.shimeng.qq2693533893.MyServiceOne",{
            onMatch: function(instance){
                console.log('find instance',instance);
                instance.坐等前往世界的尽头的小船.value = '187724addd757b99a9dc1eb570c65f32c33f5941';
            },
            onComplete: function(){
                console.log('search completed!')
            }
        });
    })
    }

    点击,解锁,一气呵成!!终于没有了!!搞定!!
    通过分析这个锁机软件,让初入Frida的我学习到了很多,希望自己能够坚持学习下去。最后,本应该感谢这个软件的作者,不是他写这个软件,我也不能学习到这么多的知识,但是我还是忍不住问候他,CSB,CNMD,祸害人的G东西。

demo.zip

131.39 KB, 下载次数: 32, 下载积分: 吾爱币 -1 CB

解压密码:52pojie

免费评分

参与人数 9威望 +1 吾爱币 +27 热心值 +9 收起 理由
junjia215 + 1 + 1 谢谢@Thanks!
fengbolee + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
正己 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
seekasky + 1 谢谢@Thanks!
ByLQX + 1 + 1 我很赞同!
Some + 1 + 1 用心讨论,共获提升!
afhack + 1 + 1 谢谢@Thanks!楼主的学习能力值得敬佩!
宝明软件作者 + 1 + 1 谢谢@Thanks!
icebeans + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

yyyao2008 发表于 2023-8-21 14:00
楼主很牛啊,高
PJOne666 发表于 2023-8-21 15:46
哈哈哈 我那个手机一开机就在乱叫 感谢大佬帖子
wesley1224 发表于 2023-8-21 16:10
伤城幻化 发表于 2023-8-21 18:12
很强,初入Frida就能看加密的东西(我反正看得头大),我可能就直接选择尝试调用removeView了
名shu 发表于 2023-8-22 10:06
这个锁机狗是从PDD出来的吧
wystudio 发表于 2023-8-22 13:36
图片怎么加载不出来。。
 楼主| fengchuan 发表于 2023-8-22 16:05
wystudio 发表于 2023-8-22 13:36
图片怎么加载不出来。。

我用的github做图床,可能需要科学
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-28 05:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表