畸轻畸重网

百度知道APP心跳包分析-MD5字段(gzip + CRC32)

百度知道APP心跳包分析-MD5字段(gzip + CRC32)

百度知道app有个心跳包检测机制,百度看下这个接口

在这里插入图片描述
POST:https://kstj.baidu.com/ctj/iknow?知道字段v=737&i=0E046D49CA01C9B2177F109C170A6C60%7CVDWE3WI7K&s=1440*2392&fr=android&c=baiduzhushou&mc=Pixel+XL&ie=&op=&aid=9&av=9.1.5.2&sv=7.1.2

我们在模拟请求的时候发现headers有个参数进行加密。

在这里插入图片描述

MD5,跳包需要解决该字段。分析

md5,百度猜测盲猜一波,知道字段真的跳包是MD5???

md5长度一般为32位或者16位,我们看这个10位的分析长度是啥情况?

难道是截取前十位?

算了直接反编译看吧,反编译搜关键词?
我们今天换种快速的百度方法,直接用算法助手hook吧。知道字段

在这里插入图片描述

直接hook了该 请求url,跳包并将堆栈打印出来了。分析

调用堆栈:        at com.baidu.common.klog.KBaseStatWorker.getUploadUrl()        at com.baidu.common.klog.core.KBaseWorker.getSignUrl(SourceFile:1)        at com.baidu.common.klog.core.i$a.a(SourceFile:9)        at com.baidu.common.klog.core.i$a.a(SourceFile:28)        at com.baidu.common.klog.core.i$a.a(SourceFile:1)        at com.baidu.asynctask.CommonAsyncTask$a.call(SourceFile:2)        at java.util.concurrent.FutureTask.run(FutureTask.java:237)        at com.baidu.asynctask.d.k(SourceFile:1)        at com.baidu.asynctask.e$c.run(SourceFile:8)        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)        at java.lang.Thread.run(Thread.java:761)

直接找 com.baidu.common.klog.core.i$a.a 方法看下
在这里插入图片描述
定位到了。百度

直接扣:

byte[] processItem = this.f7349o.processItem(list);    byte[] a = m8627a(processItem);    CRC32 crc32 = new CRC32();    StringBuilder sb = new StringBuilder();    sb.append(processItem.length);    sb.append("%");    sb.append(a.length);    crc32.update(sb.toString().getBytes());    String valueOf = String.valueOf(crc32.getValue());

frida 勾一下

# -*- coding: utf-8 -*-# @Author  : Codeooo# @Time    : 2022/9/21import frida,知道字段 sys# JSON.stringify(baidu.common.klog.KBaseStatWorker$a */#     public class C2693a implements Callable{ #Response解密Response1 = """Java.perform(function () {     var utils = Java.use('com.baidu.common.klog.KBaseStatWorker');    //var utils = Java.use('com.baidu.common.klog.KDebugWorker');    utils.processHeader.implementation = function (arg0,arg1,arg2) { 		console.log("arg0 ->" + arg0);		//console.log("arg1 ->" + arg1);        console.log("result ->" + this.processHeader(arg0,arg1,arg2));        return this.processHeader(arg0,arg1,arg2);    }});"""Response = """Java.perform(function () {     var utils = Java.use('com.baidu.common.klog.core.i$a');    utils.a.overload().implementation = function (arg0) {         console.log("arg0 ->" + arg0);        console.log("result ->" + this.a(arg0));        return this.a(arg0);    }});"""process = frida.get_remote_device().attach('com.baidu.iknow')script = process.create_script(Response)script.load()sys.stdin.read()

整体加密思路:

将请求体转换为字节集, 然后把字节集进行gzip压缩,跳包
字节集取一次长度为:a,压碎后的为:b,然后把这俩长度进行CRC32算法编码输出就出来md5了

在这里插入图片描述
888341776 没错

1050: 则是bArr.length 也就是 length | Content-Length 字段 也是请求体的长度

CRC(Cyclic Redundancy Check)校验实用程序库在数据存储和数据通讯领域,为了保证数据的正确,就不得不采用检错的手段。在诸多检错手段中,CRC是最著名的一种。CRC的全称是循环冗余校验。

在这里插入图片描述

所以看来此MD5非MD5算法哈哈哈哈~

直接贴代码:

import java.io.IOException;import java.util.zip.CRC32;import java.util.zip.GZIPOutputStream;import java.io.ByteArrayOutputStream;public class MD5 {     public static void main(String[] args) {         /*请求体 每一小节后面跟\n换行*/        String str = "act=view&l=wifi&seq=1&ts=30f55&sid=l8bc21246qqx&t=1663752141189&sampleToken=941&name=logTodayAnswerCardShow\n" +                "seq=1&l=wifi&act=view&ts=30f5s&sid=l8bc21246qqx&t=1663752141212&sampleToken=941&name=logVoteCardContainerShow&qid=1375810357052180219\n" +                "seq=1&l=wifi&act=view&ts=30f6i&sid=l8bc21246qqx&t=1663752141238&sampleToken=941&name=logHomeBannerShow\n" +                "seq=1&l=wifi&act=view&ts=30f7a&sid=l8bc21246qqx&t=1663752141266&sampleToken=941&name=logContentOfFeedAllShow\n" +                "seq=1&l=wifi&act=view&ts=30fgs&sid=l8bc21246qqx&t=1663752141608&sampleToken=941&name=logTimeLimitAnswerCardShow&qid=1455695397450803940\n" +                "seq=1&l=wifi&act=view&ts=30fhs&sid=l8bc21246qqx&t=1663752141644&sampleToken=941&name=logQuestionItemShow&statId=33&qid=1869336249901253347\n" +                "seq=1&l=wifi&act=view&ts=30fie&display_time=1663752141&sid=l8bc21246qqx&t=1663752141666&sampleToken=941&name=logQuestionFeedCellShow&request_page=na_answertab_tag&product=qengine_question&qid=1869336249901253347\n" +                "seq=1&l=wifi&act=view&ts=30fip&sid=l8bc21246qqx&t=1663752141677&sampleToken=941&name=logContentOfFeedAllShow\n";        //将请求体字符串转化为byte        byte[] bArr = str.getBytes();        System.out.println(bArr.length);        //将转化后byte再传入gzip压缩算法里        byte[] bArr2 = m8627a(bArr);        System.out.println(bArr2.length);        //将两次的byte长度传入StringBuilder (bArr.length + "%" + bArr2.length)        CRC32 crc32 = new CRC32();        StringBuilder sb = new StringBuilder();        sb.append(bArr.length);        sb.append("%");        sb.append(bArr2.length);        //转Str后进行CRC32算法编码输出结果        crc32.update(sb.toString().getBytes());        System.out.println(crc32.getValue());    }    //gzip压缩    public static byte[] m8627a(byte[] bArr) {         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();        try {             GZIPOutputStream gZIPOutputStream = new GZIPOutputStream(byteArrayOutputStream);            gZIPOutputStream.write(bArr);            gZIPOutputStream.flush();            gZIPOutputStream.close();        } catch (IOException e) {             e.printStackTrace();        }        return byteArrayOutputStream.toByteArray();    }}

其实有个地方也可以这样写哈,都一样~
在这里插入图片描述

未经允许不得转载:畸轻畸重网 » 百度知道APP心跳包分析-MD5字段(gzip + CRC32)