吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2927|回复: 14
上一主题 下一主题
收起左侧

[移动样本分析] frida HOOK实战,对移动欺诈家族逆向分析

  [复制链接]
跳转到指定楼层
楼主
fengyutongzhou 发表于 2024-5-7 16:52 回帖奖励
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
前沿:今天拿到一个恶意软件样本,属于BOOMSLANG(树蚺)移动欺诈家族。引用文章:https://www.4hou.com/posts/m04A,文章里提到了这类家族使用了TG(电报)安卓端源代码,并且为了防止拦截在网络配置里引入 DoH 技术,随着时间线慢慢进化现在到我手里的已经没那么简单了。咱们今天登场的主角,我给他定为DOH变种+(OSS混淆+server)变种升级版。这类软件主要技术就是运用在反拦截上,所以在这里咱们只分析网络行为。还是老样子过程写的比较啰嗦,主要是分享思路和研究成果,讨论技术问题。此文章无向导,无结论。样本不传,只展示目录结构。环境及工具:夜神模拟器Android9、frIDA16.2.1、面具、LSP、算法助手、JADX、charles、Proxifier。
APP界面


看一眼目录结构。im.xsgxqmfdca.tgnet目录里有个NetworkConfig类。用来初始化网络配置,这里可以看到默认连接地址和DOH服务地址以及DOH用来解析的域名。阿里云DOH说明书:https://www.alibabacloud.com/help/zh/dns/dns-over-https
算法助手HOOK一下,发现解密出一堆URL这里就是OSS服务里存的server配置文件,看到调用堆栈是get0ssUrl。


定位一下方法get0ssUrl,发现反编译失败了。不过没关系看看其他版本反编译,Smali有点难就不看了,这里点击Simple。由于我没做过开发所以不太懂这里的原因,为什么反编译JAVA失败了,Simple里就没问题,有懂得大佬给解释一下。

回到正文看get0Url方法,这段代码通过构建URL、发起HTTP请求、读取和解析响应数据,来创建一个OSS存储服务请求解析过程。阿里云oss域名是经过混淆的,刚好最近在学frida一把梭哈今天就实战一把。

打开安卓逆向第十三节教学视频,定位到2155秒这里拷贝代码。

插一条信息,版号固定写在这里。
package im.xsgxqmfdca.ui.hui.friendscircle.okhttphelper;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/* loaded from: classes43.dex */
public class MD5Utils {
    protected static char[ hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    protected static MessageDigest messagedigest;

    static {
        messagedigest = null;
        try {
            messagedigest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException nsaex) {
            System.err.println(MD5Utils.class.getName() + "初始化失败,MessageDigest不支持MD5Util。");
            nsaex.printStackTrace();
        }
    }

    public static String getMD5String(String s) {
        return getMD5String(s.getBytes());
    }

    public static boolean checkPassword(String password, String md5PwdStr) {
        String s = getMD5String(password);
        return s.equals(md5PwdStr);
    }

    public static String getFileMD5String(File file) throws IOException {
        InputStream fis = new FileInputStream(file);
        byte[ buffer = new byte[1024;
        while (true) {
            int numRead = fis.read(buffer);
            if (numRead > 0) {
                messagedigest.update(buffer, 0, numRead);
            } else {
                fis.close();
                return bufferToHex(messagedigest.digest());
            }
        }
    }

    public static String getFileMD5String_old(File file) throws IOException {
        FileInputStream in = new FileInputStream(file);
        FileChannel ch = in.getChannel();
        MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0L, file.length());
        messagedigest.update(byteBuffer);
        in.close();
        return bufferToHex(messagedigest.digest());
    }

    public static String getMD5String(byte[ bytes) {
        messagedigest.update(bytes);
        return bufferToHex(messagedigest.digest());
    }

    private static String bufferToHex(byte[ bytes) {
        return bufferToHex(bytes, 0, bytes.length);
    }

    private static String bufferToHex(byte[ bytes, int m, int n) {
        StringBuffer stringbuffer = new StringBuffer(n * 2);
        int k = m + n;
        for (int l = m; l < k; l++) {
            appendHexPair(bytes[l, stringbuffer);
        }
        return stringbuffer.toString();
    }

    private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
        char[ cArr = hexDigits;
        char c0 = cArr[(bt & 240) >> 4;
        char c1 = cArr[bt & 15;
        stringbuffer.append(c0);
        stringbuffer.append(c1);
    }

    public static void main(String[ args) throws IOException {
        long begin = System.currentTimeMillis();
        File file = new File("C:/test.txt");
        if (!file.exists()) {
            System.out.println("不存在");
        }
        String md5 = getFileMD5String(file);
        long end = System.currentTimeMillis();
        PrintStream printStream = System.out;
        printStream.println("md5:" + md5 + " time:" + ((end - begin) / 1000) + "s");
        System.out.println(file.getPath());
    }
}


填好信息,注意这里有个重载,要标注我们这个方法传入的值是String类型。
输出结果看到传入的str值结构,版号+日期+字符1或空或Android。后面返回的MD5值是三级域名。需要注意的是子域名是由时间戳因素哈希来的所以每天请求的OSS域名是一直在变化的。最后通过每天及时在OSS更新资源的方法来维持连接。题外话:如果放到C2木马身上是不是对情报工作也有很大挑战。

免费评分

参与人数 2威望 +1 吾爱币 +21 热心值 +1 收起 理由
nyazhou + 1 热心回复!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

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

推荐
ohyeah521 发表于 2024-6-3 19:26
本帖最后由 ohyeah521 于 2024-6-3 19:43 编辑
dwiafi 发表于 2024-5-23 11:15
最近也遇到类似的样本,但对frida还是不太熟悉, 感谢分享!

这种类型样本分析没啥用,没有好办法封堵和定位,一般在线分析的平台应该都可以自动化分析出C2,但是都是云服务的IP,没法拦截,例如:https://www.zhihuaspace.cn:8888/static_analyzer/0014c723b87633fa93031170afc0b210/
推荐
yinsel 发表于 2024-5-8 22:19
我目前有很多这种样本,也在这种类型的APP对抗,但是介于技术能力实在不足,能建立个交流技术群吗方面讨论相关样本的技术
4#
isolands 发表于 2024-5-8 11:16
5#
absktv 发表于 2024-5-8 12:44
这对于我一个小白来说,有点深奥,更要努力学习了
6#
wengl123 发表于 2024-5-9 08:27
正在看公众号推的视频,刚好看到这个贴学习下,感谢大佬分享
7#
141847901 发表于 2024-5-9 10:12
跟着学习下,感谢大佬分享
8#
N1nE7 发表于 2024-5-15 22:19
跟着学习一下
9#
wuweiwuwei 发表于 2024-5-23 09:11
感谢分享
10#
wh1tefi1sh 发表于 2024-6-3 20:40
感谢佬的分享,学习中
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-24 05:09

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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