freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

回村三天,chatGPT教会了我如何简单逆向app并解密数据包
2023-01-18 13:29:00
所属地 湖南省

最近休年假提前返湘了,回村这几天冻的直打哆嗦,突然很怀恋北方温暖的暖气片。

微信公众号收到老哥私信,求助逆向一个app并对解密某个数据包。说干就干,掏出我的Google亲儿子开整。

不过这个App有一半是荤的,内容都是些虎狼之词,就不放出来了。

先看老哥的需求

1674013071_63c7698faa44d14e81e7d.png!small

图中说的 data.php 抓包看到内容是长这样子的:

1674013218_63c76a22a7163c05586d6.png!small

查壳发现目标app使用360加固了,回村匆忙没来得急带家伙事,又让老哥提供了一份脱壳后的dex文件。

拿到dex文件后,先用 d2j-dex2jar.sh 把dex还原成jar包,再把jar包拖到 jadx-gui,后面还是以前的那些三脚猫功夫。在 jadx-gui 中不断 Ctrl + F搜索关键词:Request、Response 中出现的字段和 encrypt、decrypt、AES、secretkey 等关键词。

定位到一处解密代码:

1674013933_63c76ced9ba0cba86a667.png!small

接下来就要对这段代码进行 hook ,看看它都干了些啥。如果不会使用 Frida 或者不熟练,可以像我一样多问问 chatGPT


1674012578_63c767a27a29ffa4f9e6f.png!small

对以下源码就行 hook

public static String a(String str, String str2) {
        try {
            if (str2 == null) {
                System.out.print("Key為空null");
                return null;
            } else if (str2.length() != 16) {
                System.out.print("Key長度不是16位");
                return null;
            } else {
                SecretKeySpec secretKeySpec = new SecretKeySpec(str2.getBytes("utf-8"), "AES");
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                cipher.init(2, secretKeySpec);
                try {
                    return new String(cipher.doFinal(Base64.decode(str, 0)), "utf-8");
                } catch (Exception e) {
                    System.out.println(e.toString());
                    return null;
                }
            }
        } catch (Exception e2) {
            System.out.println(e2.toString());
            return null;
        }
    }

先问问chatGPT 怎么对就函数进行hook

1674015177_63c771c9768a185e8021f.png!small

整理后(其实是jadx-gui 直接右键导出的)的hook代码:

let perform = Java.perform(() =>{
        let C0158a = Java.use("cn.tv.player.a");
        C0158a["a"].overload('java.lang.String', 'java.lang.String').implementation = function (str, str2) {
        console.log('a is called' + ', ' + 'str: ' + str + ', ' + 'str2: ' + str2);
        console.log("str2: ",str2)
        let ret = this.a(str, str2);
        console.log('a ret value is ' + ret);
        return ret;
};

frida -U -f tw.qvod.new -l frida.js --no-pause -o a.txt

1674015554_63c77342b5964e72b56b7.png!small

图中的方法应该是一个AES ECB 的解密算法,str 是密文,str2 是秘钥。

结合burpsuite抓的包进行分析,终端截图中对应的请求应该是:

1674015858_63c7747284744fd3bae8d.png!small

这串密文复制到AES在线解密网站,使用ECB模式 PKCS5padding 填充,秘钥 4f3742c93218f004 

能正确解开,内容就是终端截图中所示明文。

秘钥是怎么生成的,就不具体去分析了,还是以解密data.php 内容为主。

接接看data.php 解密对应的逻辑在哪里。看看都有谁调用了 cn.tv.player.a.a 这个方法 一通搜索后,应该是下面没跑:

1674016648_63c777881f3290dbdfd39.png!small

如果看不懂Java,那就请 chatGPT , 解释解释神马踏马的叫.......

1674017036_63c7790c1222cd8a7fcd3.png!small

美滋滋,一下子就看明白这里是啥意思了。

跟进一下下列代码找那个的 a 函数是个什么东西。

this.jsonString = new String(a(Base64.decode(this.jsonString, 0)), "UTF-8");


1674017234_63c779d24bc8235cd5ae4.png!small

1674017435_63c77a9b63f57ab081e72.png!small

之前hook到的数据保存到了 txt 中,使用对应的秘钥解出来也是一串 乱七八杂的东西,不可读。

分析后确认,他和上述代码中的 new String(a(Base64.decode(this.jsonString, 0)), "UTF-8"); 有关系。

对 data.php 数据的整个解密逻辑是:

  1. ChannelDatas 传进来一上下文
  2. 通过 this.mySettings = new MySettings(context); 拿到设置内容
  3. 通过String substring = C0158a.b(SplashActivity.z + new MySettings(PlayerActivity.f1635a).c("rand")).substring(7, 23); 设置生成AES密钥
  4. C0186z.a 操作文件
  5. 一系列替换操作,调用AES进行解密
  6. 使用bade64 进行decode ,在调用a方法进行解压缩解码

打开之前保存的 a.txt 文件,找到 data.php 那段解密后的数据。

密文:

1674017538_63c77b02c8a0f5b7b8734.png!small

明文:

1674018339_63c77e231d5e25a4cd3d0.png!small?1674018340349

编写python解密对这段不可读明文进行处理;

import base64
from io import BytesIO
from zlib import decompress

def a(bArr):
"""
new String(a(Base64.decode(this.jsonString, 0)), "UTF-8");
"""
byte_stream = BytesIO(bArr) try: result = decompress(byte_stream.read()) except Exception as e: print(e) result = None byte_stream.close() return result str = "解密后不可读的明文.........."

decoded_data = base64.b64decode(str)

decoded_data = a(decoded_data)

print(decoded_data.decode("utf-8"))

1674018806_63c77ff600f8e69e413f3.png!small?1674018807600

另一种更快的方法

直接 hook cn.tv.player.model.ChannelDatas 中substring 的值

frida -U -f tw.qvod.new -l frida.js --no-pause -o data.php.txt

frida 带上 -o  参数,将结果保存下来

// cn.tv.player.model.ChannelDatas
function main(){
    let perform = Java.perform(() => {
        //对象 实例
        Java.choose("cn.tv.player.model.ChannelDatas",
        {
            onMatch:function(instance){
                console.log(instance.substring.value)
            },
            onComplete:function(){
                console.log("over........")
            }
        }
        );
    });
}
setImmediate(main)

1674019112_63c78128c9f2c2997878c.png!small?1674019114613

chatGPT 以后就是亲二舅了,回村三天,二舅治好了我的精神内耗,哈哈哈哈。

# web安全 # 加密解密 # Frida # android逆向
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者