java 文件 md5_记一次APP的java层算法逆向(四)

 前言:初学逆向 请多多指教

学习:

1、Xposed hook加密库,通过打印堆栈函数调用链来进行定位加密函数

2、通过jadx来反编译dex文件,通过java伪代码实现加密

3、利用python来实现调用jar包来进行加密

01

登陆页面如下:

5233bbd9f2c880d4cdc9ad6ac012952e.png

数据包内容如下:

POST https://www.xiaohongshu.com/api/sns/v2/user/login HTTP/1.1User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; oppo a53 Build/LMY49I) Resolution/900*1600 Version/5.14.0 Build/5140002 Device/(oppo;oppo a53)Content-Type: application/x-www-form-urlencodedContent-Length: 378Host: www.xiaohongshu.comConnection: Keep-AliveAccept-Encoding: gzipphone=19817353426&password=e9bc0e13a8a16cbb07b175d92a113126&imei=865166028043985&zone=86&type=phone&android_id=3713bd6ec5e73711&lang=zh&platform=Android&deviceId=011646e1-5369-3f84-a611-13d9040b233b&device_fingerprint=2020101022192919d790ae4ed4f679e56a072f7ff237a50103f6b42f75de75&versionName=5.14.0&channel=Store360&lang=zh-CN&t=1602339666&sign=7609509f23b97c68d41744c185f98626

Xposed hook加密库 打印堆栈函数调用链:

06-05 21:42:32.696: E/xiaojianbang(1684): Stack:06-05 21:42:32.696: E/xiaojianbang(1684): java.lang.Throwable: stack dump06-05 21:42:32.696: E/xiaojianbang(1684):     at com.xposed.Hook$8.afterHookedMethod(Hook.java:162)06-05 21:42:32.696: E/xiaojianbang(1684):     at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:645)06-05 21:42:32.696: E/xiaojianbang(1684):     at java.security.MessageDigest.digest(Native Method)06-05 21:42:32.696: E/xiaojianbang(1684):     at com.xingin.common.util.MD5Util.a(SourceFile:29)06-05 21:42:32.696: E/xiaojianbang(1684):     at com.xingin.common.util.MD5Util.a(SourceFile:15)06-05 21:42:32.696: E/xiaojianbang(1684):     at com.xingin.skynet.XYValueRewrite.a(SourceFile:124)06-05 21:42:32.696: E/xiaojianbang(1684):     at com.xingin.skynet.XYValueRewrite.a(SourceFile:91)06-05 21:42:32.696: E/xiaojianbang(1684):     at retrofit2.RequestBuilder.a(SourceFile:216)06-05 21:42:32.696: E/xiaojianbang(1684):     at retrofit2.ServiceMethod.a(SourceFile:114)06-05 21:42:32.696: E/xiaojianbang(1684):     at retrofit2.OkHttpCall.f(SourceFile:178)06-05 21:42:32.696: E/xiaojianbang(1684):     at retrofit2.OkHttpCall.a(SourceFile:162)06-05 21:42:32.696: E/xiaojianbang(1684):     at retrofit2.adapter.rxjava.CallOnSubscribe.a(SourceFile:45)06-05 21:42:32.696: E/xiaojianbang(1684):     at retrofit2.adapter.rxjava.CallOnSubscribe.call(SourceFile:29)06-05 21:42:32.696: E/xiaojianbang(1684):     at retrofit2.adapter.rxjava.BodyOnSubscribe.a(SourceFile:33)06-05 21:42:32.696: E/xiaojianbang(1684):     at retrofit2.adapter.rxjava.BodyOnSubscribe.call(SourceFile:25)06-05 21:42:32.696: E/xiaojianbang(1684):     at rx.Observable.unsafeSubscribe(SourceFile:10144)06-05 21:42:32.696: E/xiaojianbang(1684):     at rx.internal.operators.OperatorSubscribeOn$1.call(SourceFile:94)06-05 21:42:32.696: E/xiaojianbang(1684):     at rx.internal.schedulers.ScheduledAction.run(SourceFile:55)06-05 21:42:32.696: E/xiaojianbang(1684):     at rx.internal.schedulers.ExecutorScheduler$ExecutorSchedulerWorker.run(SourceFile:107)06-05 21:42:32.696: E/xiaojianbang(1684):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)06-05 21:42:32.696: E/xiaojianbang(1684):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)06-05 21:42:32.696: E/xiaojianbang(1684):     at java.lang.Thread.run(Thread.java:841)06-05 21:42:32.696: D/xiaojianbang(1684): MD5  resultHex:68dff3a7e390ecd192575c91d6216e5506-05 21:42:32.700: D/xiaojianbang(1684): MD5  resultB64:aN/zp+OQ7NGSV1yR1iFuVQ==

直接定位到com.xingin.skynet.XYValueRewrite.a的地方:

    public static String a(Map arg8) {        String v0_1;        byte[] v1_2;  // 进行urlencode        int v2 = 0;        if(arg8 != null && !arg8.isEmpty()) {            Object v0 = arg8.get("deviceId");            ArrayList v1 = new ArrayList();            ((List)v1).addAll(arg8.keySet());            Collections.sort(((List)v1));            StringBuilder v3 = new StringBuilder();  // 存储            String v4 = "=";            Iterator v5 = ((List)v1).iterator();            while(v5.hasNext()) {                Object v1_1 = v5.next();                v3.append(((String)v1_1));                v3.append(v4);                v3.append(arg8.get(v1_1));            }            new byte[1];            try {                v1_2 = URLEncoder.a(v3.toString(),  "UTF-8").getBytes();  // 进行urlencode,这里的v3可以进行打印一次观察,是所有参数进行拼接的            }            catch(UnsupportedEncodingException v3_1) {                v3_1.printStackTrace();            }            byte[] v4_1 = ((String)v0).getBytes();            StringBuilder v5_1 = new StringBuilder();            int v3_2 = 0;            while(v2 < v1_2.length) {                v5_1.append(v1_2[v2] ^ v4_1[v3_2]);                v3_2 = (v3_2 + 1) % v4_1.length;                ++v2;            }            v0_1 =  MD5Util.a(MD5Util.a(v5_1.toString()).toLowerCase() +  (((String)v0))).toLowerCase();        }        else {            v0_1 = "";        }        return v0_1;    }

JEB console调试寄存器输出,结果如下:

f6776f6f92c34d0a1094df56f29c7a28.png

拼接http参数的结果:

VM> readvar v3 string"android_id=3713bd6ec5e73711channel=Store360deviceId=011646e1-5369-3f84-a611-13d9040b233bdevice_fingerprint=2020101022192919d790ae4ed4f679e56a072f7ff237a50103f6b42f75de75imei=865166028043985lang=zh-CNpassword=e9bc0e13a8a16cbb07b175d92a113126phone=19817353426platform=Androidt=1602343133type=phoneversionName=5.14.0zone=86"

23e4b8139fbef9f9927de13c8df428e6.png

进行while循环 异或之后的结果:

VM> readvar v2 string"819585689195111068812251253048711867387838247260838187883929386142121171016489238430338292919059312573685117128058015855298715107938792258783028242593203828863182583857271907921118289128586651866889566175333297379283841052083150873610848885085668558598440856823752858011304713428815877795121458085857909478920211412080027334129785112241387958682119308129119126188364642195678519711408798638383082948952728483126832831284132332083276594918802030113215128485137258306593766985117593173381159387169588856617533027515133028511648417832021056591118785668516659092121268092831753343472498792893173037147"

8263be289ff70968cf86ff5f885e9268.png

最后进行两次md5的结果:

VM> readvar v0 string"d88e4966a60cc07f2f662d4f68001edb"

上面提到的加密中,异或的算法,内容如下:

3c75c0a9a34721e095677ab40ef55011.png

0821b71032c84a4cea47b2d1acad1f9b.png

public class Utils {    public static String getSign(String sb, String v0) throws Exception {        byte[] bArr = URLEncoder.a(sb, "UTF-8").getBytes();        byte[] bytes = v0.getBytes();        StringBuilder sb2 = new StringBuilder();        int i = 0;        for (byte b2 : bArr) {            sb2.append(b2 ^ bytes[i]);            i = (i + 1) % bytes.length;        }        return sb2.toString();    }    public static void main(String[] args) throws Exception {        System.out.println(Utils.getSign(args[0], args[1]));    }}

ad8fdedd624f520765199c64b4c850b4.png

python调用jar包(这里主要实现二次MD5的功能,顺便学习如何通过python来调用jar包):

import subprocessimport chardetimport sysimport hashlibclass Java2Encrypt(object):    def __init__(self, data1, data2):        self.data1 = data1        self.data2 = data2    def encrypt(self):        command = "java -jar reverse_xiaohongshu.jar"        arg0 = self.data1        arg1 = self.data2        cmd = [command, arg0, arg1]        new_cmd = " ".join(cmd)        stdout, stderr = subprocess.Popen(new_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()        encoding = chardet.detect(stdout)["encoding"]        result = stdout.decode(encoding)        MD5 = hashlib.md5()        MD5.update(bytes("819585689195111068812251253048711867387838247260838187883929386142121171016489238430338292919059312573685117128058015855298715107938792258783028242593203828863182583857271907921118289128586651866889566175333297379283841052083150873610848885085668558598440856823752858011304713428815877795121458085857909478920211412080027334129785112241387958682119308129119126188364642195678519711408798638383082948952728483126832831284132332083276594918802030113215128485137258306593766985117593173381159387169588856617533027515133028511648417832021056591118785668516659092121268092831753343472498792893173037147", encoding='UTF-8'))        md5_1 = MD5.hexdigest()        MD5 = hashlib.md5()        MD5.update(bytes(md5_1 + data2, encoding='UTF-8'))        md5_2 = MD5.hexdigest()        return md5_2if __name__ == '__main__':    data1 = sys.argv[1]    data2 = sys.argv[2]    myEncrypt = Java2Encrypt(data1, data2)    print(myEncrypt.encrypt())

最终的结果如下,跟上面的调试最后输出的md5结果一样

d88e4966a60cc07f2f662d4f68001edb

adc73444ea96b3a118b552c5ae4c43d6.png

参考文章:

  • https://www.jb51.net/article/193082.htm

1bf7159f76165f34f89f87d3353e4132.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值