Skip to content
This repository has been archived by the owner on Feb 17, 2024. It is now read-only.

client_id 是否应当在本地生成 #150

Closed
lumina37 opened this issue Jan 24, 2023 · 41 comments
Closed

client_id 是否应当在本地生成 #150

lumina37 opened this issue Jan 24, 2023 · 41 comments
Labels
enhancement New feature or request

Comments

@lumina37
Copy link

lumina37 commented Jan 24, 2023

今早研究极速版9.1.0.0的反编译源码时发现client_idRetrofitTiebaApi.kt#L45)似乎并不像cuid_galaxy2那样可以在本地随机生成

cuidcuid_galaxy2都在com.baidu.tbadk.core.TbadkCoreApplicationinit函数中生成,而client_id在此仅有一个读缓存的动作
搜狗截图20230124104758

查找ClientId的被调位置可以发现一个setClientId函数
搜狗截图20230124105214

再追踪这个setClientId函数可以发现它在一个初始化任务中被调用
搜狗截图20230124105534

其中bfD.m15998Iq函数可以理解为post request,而请求任务bfD所对应的正是c/s/sync接口,其余红框都是json解析的配套函数

看到c/s/sync的返回数据确实包含client_id
搜狗截图20230124110104

如果不在请求参数中包含本地的client_id,那么云端会自动生成和返回一个基于当前时间戳的client_id
搜狗截图20230124103506

注:c/s/sync接口仅需要BDUSS,使用post并需要tbclient!!!签名

@n0099
Copy link

n0099 commented Jan 24, 2023

事实核查:根本不携带_client_id request param服务端也会给出相同的正常response

@HuanCheng65
Copy link
Owner

嗯,那下版本会改一下...现在比较搞不清的是新版有个参数z_id

@n0099
Copy link

n0099 commented Jan 24, 2023

@n0099
Copy link

n0099 commented Jan 24, 2023

#145 (comment) 中引用的 https://bbs.tiebazs.com/593-1-1.html 声称c.tieba.baidu.com/c/s/sync系统公告 系统贴吧推荐
阁下提到这个接口需要BDUSS,也就是说贴吧客户端的行为是基于BDUSS从贴吧服务端获得一个神必高信息熵字符串,然后在后续的几乎所有请求(不论该接口要不要BDUSS)中都会携带common.三大件之_client_(type|id|version)https://github.com/n0099/tbclient.protobuf/blob/d58493a70dad553b86d96c402deee8601733a903/proto/CommonReq.proto#L4

因此完全可以合理假设这是贴吧服务端用于实现其在一段时间内(嵌入了unix timestamp因此可能有时效性)追踪同一个唯一贴吧客户端用户的罪恶遥测行径
建议立即致电四叶信安底层壬上壬上海贵族FSF EFF精神会员杨博文阁下 @yangbowen 前来评估此神必字符串的排列组合可能取值总量

@HuanCheng65
Copy link
Owner

HuanCheng65 commented Jan 24, 2023

@HuanCheng65 阁下给3大帖子接口加_client_type了吗?#149 (comment) z_id是这个? https://github.com/n0099/tbclient.protobuf/blob/d58493a70dad553b86d96c402deee8601733a903/proto/CommonReq.proto#L34

是这个,从抓包看是访问一个url不知道怎么得到的地址然后解密得出来的...域名是sofire.baidu.com
_client_type应该是加了的

@HuanCheng65
Copy link
Owner

@lumina37
Copy link
Author

lumina37 commented Jan 24, 2023

sofire应该是一个类似sqlite的本地数据库,在app内部通过content://以及安卓的ContentProvider实现交互。z_id的生成逻辑被放在sofire里了,这部分我还在研究

@yangbowen
Copy link

建议立即致电四叶信安底层壬上壬上海贵族FSF EFF精神会员杨博文阁下 @yangbowen 前来评估此神必字符串的排列组合可能取值总量

我好像没什么能评价的,毕竟我完全不懂贴吧相关的。
关于“基于时间戳的唯一标识符有多大取值空间”,可以参考 1 类 UUID 。

@HuanCheng65 HuanCheng65 added the enhancement New feature or request label Jan 24, 2023
@lumina37
Copy link
Author

lumina37 commented Jan 25, 2023

用frida操作了一波,发现z_id就是context.getSharedPreferences("leroadcfg", 0)中的xytk。暂时不知道这个值是不是在安装时就确定的,因为没发现赋值位置

SharedPreference的位置在/data/data/com.baidu.tieba_mini/shared_prefs/leroadcfg.xml

测试环境:
夜神模拟器7.0.5.0 Android9 x86_64
frida16.0.8

import sys

import frida

jscode = """
Java.perform(function () {
  var current_application = Java.use('android.app.ActivityThread').currentApplication();
  var context = current_application.getApplicationContext();

  let C2628g = Java.use("com.baidu.sofire.g");
  var inst_g = C2628g.$new(context)
  var xytk = inst_g.a();
  console.log(xytk);
});
"""


def on_message(message, data):
    print(message)


process = frida.get_remote_device().attach('贴吧极速版')
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()

输出

Z4HrG0sphczjIeE2jD-1L1pVVueGoM9TiQ4X1BweRY8YWf696TXW4iaEfhEwmW4DMoqjYMyfVBsgnXm113cSoEw

@n0099
Copy link

n0099 commented Jan 25, 2023

所以z_id有什么用,服务端必须要这个吗?提供他可以返回更多字段值吗?建议挥舞奥卡姆剃刀

@HuanCheng65
Copy link
Owner

@Starry-OvO 之前反编译11.10.8.6的时候看貌似是获取到之后整个写入这个sp...但是具体在哪忘记了,我抽空再看看

@lumina37
Copy link
Author

所以z_id有什么用,服务端必须要这个吗?提供他可以返回更多字段值吗?建议挥舞奥卡姆剃刀

未雨绸缪,而且发帖和私信接口都与这个有关

@n0099
Copy link

n0099 commented Jan 25, 2023

所以z_id有什么用,服务端必须要这个吗?提供他可以返回更多字段值吗?建议挥舞奥卡姆剃刀

未雨绸缪,而且发帖和私信接口都与这个有关

#starry神步鸡血神后尘进军贴吧黑灰产行业生产广告机

那我盲猜是用于在发帖/私信后方便后续接收百度慧推服务端推送通知时找出客户端的唯一id,也就是说还是属于tracing遥测跟踪

@HuanCheng65
Copy link
Owner

所以z_id有什么用,服务端必须要这个吗?提供他可以返回更多字段值吗?建议挥舞奥卡姆剃刀

未雨绸缪,而且发帖和私信接口都与这个有关

#starry神步鸡血神后尘进军贴吧黑灰产行业生产广告机

那我盲猜是用于在发帖/私信后方便后续接收百度慧推服务端推送通知时找出客户端的唯一id,也就是说还是属于tracing遥测跟踪

Screenshot_2023-01-25-15-03-48-283_bin mt plus
z_id这个参数是由SP里的android_safe_sdk_open来决定是否携带的

@n0099
Copy link

n0099 commented Jan 25, 2023

经典阅读理解jvm bytecode时间

@lumina37
Copy link
Author

现在最关键的问题是不知道leroadcfg.xml是何时生成的

@n0099
Copy link

n0099 commented Jan 25, 2023

#starry神发威了! https://github.com/Starry-OvO/aiotieba/releases/tag/v3.1.2

@lumina37
Copy link
Author

lumina37 commented Jan 26, 2023

极速版不具备独立生成新版cuid_galaxy2的能力
它会优先使用com.baidu.tieba里的cuid_galaxy2
具体表现是,如果将/data/data/com.baidu.tieba_mini/shared_perfs/common_settings.xml和缓存文件/data/data/com.baidu.tieba_mini/files/libcuid.so同时删除的话,就只会输出形如693C07281680E73DEE0939642B459E59|0的以0结尾的旧版cuid_galaxy2

使用以下frida脚本hook贴吧12.35.1.0的初始化过程可以发现,新版cuid_galaxy2的生成只与这两个函数有关

frida -U -l hook_new.js -f com.baidu.tieba
// hook_new.js
Java.perform(function () {

  let z00 = Java.use("com.baidu.tieba.z00");
  z00["b"].implementation = function (bArr) {
    console.log('m22480b is called' + ', ' + 'bArr: ' + bArr);
    let ret = this.b(bArr);
    console.log('m22480b ret value is ' + ret);
    return ret;
  };

  let C17942pz = Java.use("com.baidu.tieba.pz");
  C17942pz["a"].implementation = function (bArr) {
    console.log('m49465a is called' + ', ' + 'bArr: ' + bArr);
    let ret = this.a(bArr);
    console.log('m49465a ret value is ' + ret);
    return ret;
  };

});

输出

[SM-G988N::com.baidu.tieba ]-> m49465a is called, bArr: 54,57,51,67,48,55,50,56,49,54,56,48,69,55,51,68,69,69,48,57,51,57,54,52,50,66,52,53,57,69,53,57
m49465a ret value is -78,27,22,-23,76
m22480b is called, bArr: -78,27,22,-23,76
m22480b ret value is WINRN2KM

生成的cuid_galaxy2693C07281680E73DEE0939642B459E59|VWINRN2KM
其中WINRN2KM正是由693C07281680E73DEE0939642B459E59经过m49465am22480b的计算得出

所以想问问你能不能看出这两个函数长得像什么摘要算法

搜狗截图20230126193834

搜狗截图20230126193946

@HuanCheng65
Copy link
Owner

@Starry-OvO 后面这一坨是跟com/baidu/helios包里的有几个方法有关系

@lumina37
Copy link
Author

@Starry-OvO 后面这一坨是跟com/baidu/helios包里的有几个方法有关系

如果不是什么通用算法的话我就手搓了

@HuanCheng65
Copy link
Owner

HuanCheng65 commented Jan 26, 2023

@Starry-OvO 后面这一坨是跟com/baidu/helios包里的有几个方法有关系

如果不是什么通用算法的话我就手搓了

应该说挺复杂的...一大坨...我没看出来2333(菜.jpg
这边基于11.10.8.6版本反编译得到大概是这样的过程:
|前面的部分是MD5计算的结果,原文根据Android版本的不同略有差别,Android M以下是IMEI+Android ID+一串UUID,Android M及以上则是com.baidu+Android ID
|后面的部分第一个字母固定为V,后面的部分是由|前面的部分经过比较复杂的计算得到的...我这边暂且没搞明白所以直接复制了反编译回来的代码...但大致就是先通过Lcom/baidu/helios/common/cc/b;->y([B)[B这个方法运算得到一个ByteArray然后再用Lcom/baidu/helios/common/b/a/b;->encode([B)Ljava/lang/String;这个方法得到最终的String...
1674737846066

@lumina37
Copy link
Author

emmm,这两个方法我都没找到
我在com.baidu.helios.common.cc里只找到了an,没找到b,也没找到encode函数,你用的客户端版本号是多少?

搜狗截图20230126225222

@HuanCheng65
Copy link
Owner

@Starry-OvO 11.10.8.6

@lumina37
Copy link
Author

可能在12.35.1.0已经不是helios负责生成了,12.35.1.0的客户端的helios下面有个DummyProvider,原本的逻辑应该是转到了混淆更复杂的com.baidu.tieba.*里面

@HuanCheng65
Copy link
Owner

刚下了个12.35.1.0的包看了下,应该是变成了Lcom/baidu/tieba/l40;->a([B)[BLcom/baidu/tieba/g50;->c([B)Ljava/lang/String;
另外可以来咱的telegram群组这边讨论233333
https://t.me/tblite_discuss

@n0099
Copy link

n0099 commented Jan 26, 2023

这两个函数长得像什么摘要算法

建议立即致电位运算中级高手 n0099/open-tbm#24 (comment) 四叶信安底层壬上壬上海贵族 FSF EFF 精神会员杨博文阁下 @yangbowen
image

来咱的telegram群组这边讨论

经典搞v圈小团体

lumina37/aiotieba@1f2c248

#starry神正式进军c/cpp/rust底层系统语言领域

@n0099
Copy link

n0099 commented Jan 26, 2023

也就是说还是属于tracing遥测跟踪

cuid_galaxy2百度统计用的跨域跟踪url querystring,就像阿里系网站spm https://www.gairuo.com/p/spmgoogle analyticsutm_*
他以前还会被追加到网页端出站链接上:
image
例如某google search index之

https://www.perfare.net/
?cuid=baidutiebaapp266d7d86-6f18-42b5-b61b-d716cdb23991
&cuid_galaxy2=6CF3E8B6E635CD3AE1E72C082ED9963A%7CO
&cuid_gid
&timestamp=1577203677573
&_client_version=10.3.8.41
&nohead=1

https://blog.csdn.net/lovesmiles/article/details/102685514
还有一个神必jsonp: http://unionsug.baidu.com/su?ie=UTF-8&wd=libcuid

@yangbowen
Copy link

yangbowen commented Jan 27, 2023

这两个函数长得像什么摘要算法

建议立即致电位运算中级高手 n0099/TiebaMonitor#24 (comment) 四叶信安底层壬上壬上海贵族 FSF EFF 精神会员杨博文阁下 @yangbowen image

诶,我看看……

iArr[0] = (byte) ((sArr[0] >> 3) & 31);
iArr[1] = (byte) (((sArr[0] & 7) << 2) | ((sArr[1] >> 6) & 3));
iArr[2] = (byte) ((sArr[1] >> 1) & 31);
iArr[3] = (byte) (((sArr[1] & 1) << 4) | ((sArr[2] >> 4) & 15));
iArr[4] = (byte) (((sArr[2] & 15) << 1) | ((sArr[3] >> 7) & 1));
iArr[5] = (byte) ((sArr[3] >> 2) & 31);
iArr[6] = (byte) (((sArr[4] >> 5) & 7) | ((sArr[3] & 3) << 3));
iArr[7] = (byte) (sArr[4] & 31);

感觉是 Base32 之类的东西。这段位运算的功能其实是,把 sArr 里的 5 个字节拆成 40 个位然后每 5 位塞到 iArr 的一个 byte 里面。 sArr 元素的范围是 0~255 , iArr 则是 0~31 。


image

外循环i2每次遍历bArr的 5 个字节,(bArr.length + 4) / 5的意思是除以 5 向上取整。内循环i4遍历这 5 个字节,依次填入sArr的 5 个元素当中。(末尾)空缺部分填 0 ,i3表示这个 5 字节块里实际有几个非填充字节。

image

sArr里的 5 个字节里每 5 个位放进iArr的一个元素,刚好放满 8 个元素。

image

不妨把这个while改写成for

int i6;
for (i6 = 0; i6 < 8 - m22481a; ++i6) {
   // this.f90491a 应该就是 Base32 alphabet
   // 根据 alphabet 可以区分它是 Base32 的哪种变种
   char charAt = this.f90491a.charAt(iArr[i6]);
   // this.f90493c 为真的情况下转为小写
   if (this.f90493c) charAt = Character.toLowerCase(charAt);
   byteArrayOutputStream.write(charAt);
}
// this.f90492b 为真的情况下末尾填充等号字符
if (this.f90492b) for (; i6 < 8; ++i6) byteArrayOutputStream.write('=');

结合上面的int m22481a = m22481a(i3)m22481a的功能应是,根据这个 5 字节块实际占了几个字节,计算对应的 8 个 Base32 符号里实际需要几个。所以这部分就是先输出确实被原输入用到的部分的 Base32 字符,然后可能末尾填充等号字符。

@n0099
Copy link

n0099 commented Jan 27, 2023

经典baseXX n0099/open-tbm#24 (comment)
回顾经典之 https://github.com/qntm/base65536

@lumina37
Copy link
Author

@yangbowen 感谢解读,刚验证了一下发现m22480b确实就是base32

import base64

src = b''.join(i.to_bytes(1, 'big', signed=True) for i in [-78, 27, 22, -23, 76])

print(base64.b32encode(src).decode('ascii'))

输出

WINRN2KM

@yangbowen
Copy link

顺带一提,代码不要发图片就好了……因为文本方便一点点手动变换,图片就只能看着。

@lumina37
Copy link
Author

记个笔记

使用以下frida脚本追踪12.x版本中生成cuid_galaxy2的关键函数com.baidu.tieba.pz.a(byte[])->byte[]
用于校验第三方实现的正确性

import sys

import frida

jscode = """
Java.perform(function () {
  var C19380sz = Java.use("com.baidu.tieba.sz");
  C19380sz["a"].implementation = function (c3121b, i, i2, i3) {
    console.log('a is called ' + 'i: ' + i + ', ' + 'i2: ' + i2 + ', ' + 'i3: ' + i3);
    console.log('c3121b:');
    logc3121b(c3121b);
    var ret = this.a(c3121b, i, i2, i3);
    console.log('a ret value is ' + ret);
    return ret;
  };

  var C17942pz = Java.use("com.baidu.tieba.pz");
  var inst_pz = C17942pz.$new();
  var buffer = Java.array('byte', [54, 57, 51, 67, 48, 55, 50, 56, 49, 54, 56, 48, 69, 55, 51, 68, 69, 69, 48, 57, 51, 57, 54, 52, 50, 66, 52, 53, 57, 69, 53, 57]);
  var res = inst_pz.a(buffer);
  console.log('res is ' + res);

  function logc3121b(c3121b) {
    var a_field = c3121b.getClass().getField('a');
    var a = a_field.get(c3121b);
    var buffer = Java.array('long', a);
    for (var i = 0; i < buffer.length; ++i) {
      console.log('a: ' + buffer[i]);
    }
    var b_field = c3121b.getClass().getField('b');
    var b = b_field.get(c3121b);
    console.log('b: ' + b);
    var c_field = c3121b.getClass().getField('c');
    var c = c_field.get(c3121b);
    console.log('c: ' + c);
  };
}
);"""


def on_message(message, data):
    print(message)


process = frida.get_remote_device().attach('百度贴吧')
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()

期望输出

m41293a is called i: 8, i2: 32, i3: 0
c3121b:
a: 283472090
b: 1
c: false

m41293a is called i: 0, i2: 32, i3: 1
c3121b:
a: 4164714771
b: 1
c: false

m41293a is called i: 1, i2: 32, i3: 1
c3121b:
a: 2539511983
b: 1
c: false

m41293a is called i: 7, i2: 32, i3: 1
c3121b:
a: 3149251330
b: 1
c: false

res is -78,27,22,-23,76

@n0099
Copy link

n0099 commented Jan 27, 2023

所以到底什么是-78, 27, 22, -23, 76或者说b2 1b 16 e9 4c或者说WINRN2KM百度统计拿这个固定的magic num来跨域tracing吗?

顺带一提,代码不要发图片就好了……因为文本方便一点点手动变换,图片就只能看着。

建议立即使用 https://open.youtu.qq.com
与此同时我还在研究如何使用百度paddleocr/imagemagick/opencv赋能google tesseract从而实现对tbm中5.25m张存量图片的ocr任务

@lumina37
Copy link
Author

所以到底什么是-78, 27, 22, -23, 76或者说b2 1b 16 e9 4c或者说WINRN2KM百度统计拿这个固定的magic num来跨域tracing吗?

只是一个测试用例

@lumina37
Copy link
Author

cuid_galaxy2c3_aid 的C实现 _cuid.c

@HuanCheng65
Copy link
Owner

@Starry-OvO 您

@n0099
Copy link

n0099 commented Jan 29, 2023

Starry-OvO/aiotieba@d916647 (#95) starry神发威了!

@lumina37
Copy link
Author

lumina37 commented Jan 30, 2023

z_id来源于一个动态加载的dex

使用如下frida脚本跟踪xytk的写入位置

setImmediate(function () {
  Java.perform(function () {

    function printStack() {
      Java.perform(function () {
        var Exception = Java.use("java.lang.Exception");
        var ins = Exception.$new("Exception");
        var straces = ins.getStackTrace();
        if (straces != undefined && straces != null) {
          var strace = straces.toString();
          var replaceStr = strace.replace(/,/g, "\r\n");
          console.log("=============================Stack strat=======================");
          console.log(replaceStr);
          console.log("=============================Stack end=======================\r\n");
          Exception.$dispose();
        }
      });
    }

    var sp = Java.use("android.app.SharedPreferencesImpl$EditorImpl");
    sp.putString.overload('java.lang.String', 'java.lang.String').implementation = function (arg1, arg2) {
      if (arg1 == "xytk") {
        console.log("[SharedPreferencesImpl] putString -> key: " + arg1 + " = " + arg2);
        printStack();
      }
      return this.putString(arg1, arg2);
    }

  });
}
)

命令行执行

frida -U -l .\hook_sp.js -f com.baidu.tieba_mini

期望结果

[SM-G988N::com.baidu.tieba_mini ]-> [SharedPreferencesImpl] putString -> key: xytk = 0557B1C261E824D33D06755C3E0F12019B
=============================Stack strat=======================
android.app.SharedPreferencesImpl$EditorImpl.putString(Native Method)
com.baidu.sofire.x0.cCooCCCcCoCc.CcooOoocOOo.OoccOCcoCCcC(SofirePreferences.java:234)
com.baidu.sofire.x0.occOOOOOoOo.CcoOOcCOOo.CcooOoocOOo(CommonUtilPartC.java:252)
com.baidu.sofire.x0.occOOOOOoOo.ccOcCOooOOcO.OoccOCcoCCcC(CommonUtilPartG.java:76)
com.baidu.sofire.x0.OCoOCOoOoO.CcooOoocOOo.OcCOcOOoCC(NetworkEngine.java:418)
com.baidu.sofire.x0.OCoOCOoOoO.CcooOoocOOo.OoccOCcoCCcC(NetworkEngine.java:876)
com.baidu.sofire.x0.oocOcccccoo.OoccOCcoCCcC$4.doRun(EnvironmentDetector.java:381)
com.baidu.sofire.x0.occOOOOOoOo.OoccOCcoCCcC.OcCOcOOoCC.run(SecRunnable.java:28)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
java.lang.Thread.run(Thread.java:764)
=============================Stack end=======================

[SharedPreferencesImpl] putString -> key: xytk = WD_wOVfkMMmJuGnfuZp1UPzOQktsyALDjZmB6X8O-OyLB2seIIIefMBVt2DaHkor4a996ny0ExBFNBIve2IANIg
=============================Stack strat=======================
android.app.SharedPreferencesImpl$EditorImpl.putString(Native Method)
com.baidu.sofire.x6.OoccOCcoCCcC.ccoooCoooOoO.OoccOCcoCCcC(SofirePreferences.java:98)
com.baidu.sofire.x6.oCOCcooCCoC.CoOOccCoooOO.OoccOCcoCCcC(PolicyUtil.java:282)
com.baidu.sofire.x6.occOOOOOoOo.OOCoOOOoOo.OoccOCcoCCcC(HandleZidChecktor.java:192)
com.baidu.sofire.x6.occOOOOOoOo.CcoOOcCOOo$7.OoccOCcoCCcC(RpSD.java:343)
com.baidu.sofire.x6.oCOCcooCCoC.OcCOcOOoCC.OoccOCcoCCcC.run(FinRunnable.java:28)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
java.lang.Thread.run(Thread.java:764)
=============================Stack end=======================

[SharedPreferencesImpl] putString -> key: xytk = WD_wOVfkMMmJuGnfuZp1UPzOQktsyALDjZmB6X8O-OyIBQ8Zk8ovoGfiqZfHiPuBae_yTWe-AQ6v4X1y5WT5mTw
=============================Stack strat=======================
android.app.SharedPreferencesImpl$EditorImpl.putString(Native Method)
com.baidu.sofire.x6.OoccOCcoCCcC.ccoooCoooOoO.OoccOCcoCCcC(SofirePreferences.java:98)
com.baidu.sofire.x6.oCOCcooCCoC.CoOOccCoooOO.OoccOCcoCCcC(PolicyUtil.java:282)
com.baidu.sofire.x6.occOOOOOoOo.OOCoOOOoOo.OoccOCcoCCcC(HandleZidChecktor.java:192)
com.baidu.sofire.x6.occOOOOOoOo.CcoOOcCOOo$4.OoccOCcoCCcC(RpSD.java:245)
com.baidu.sofire.x6.oCOCcooCCoC.OcCOcOOoCC.OoccOCcoCCcC.run(FinRunnable.java:28)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
java.lang.Thread.run(Thread.java:764)
=============================Stack end=======================

@lumina37
Copy link
Author

lumina37 commented Feb 1, 2023

留档

我的评价是:客户端参数还原的最后一座高峰

动态加载的dex位于/data/data/{PackageName}/files/.tmp/1-4.1.4.2.zip改成apk之后直接jadx打开,组装逻辑位于函数com.baidu.sofire.x6.occOOOOOoOo.OOCoOOOoOo.OoccOCcoCCcC

xytk的赋值位置有两个,不要搞混了,上面这个才对应permanent zid

zid的原始请求json

{
    "1": "",
    "2": "com.baidu.tieba_mini",
    "3": "",
    "4": "3B92F4025F6181B37BC2CEF5F2129E67|0",
    "5": "1007113",
    "6": 1675172431954,
    "7": "",
    "8": "740017",
    "9": "x6",
    "10": "4.1.4.2",
    "11": "",
    "12": "",
    "13": 1,
    "14": 1,
    "module_section": [
        {
            "token": "3B92F4025F6181B37BC2CEF5F2129E6782",
            "ut": "3B92F4025F6181B37BC2CEF5F2129E6782",
            "magic": "wwqlDj6YyE4ApMIxMZ71EnutjiF7T8TV5yFxuJDK5cW6/4qlvKK/NcaeTe75bkx5B",
            "token_rt": "",
            "mz": "3B92F4025F6181B37BC2CEF5F2129E67|0",
            "ds": "2",
            "zid": "3B92F4025F6181B37BC2CEF5F2129E67|0",
            "act_st": "0",
            "chn_st": "0",
            "os_ver": "28",
            "reason": {
                "1": 1,
                "2": 0,
                "3": 1675172431951,
                "4": 3
            },
            "tp": "3",
            "tk": "3B92F4025F6181B37BC2CEF5F2129E6782#",
            "pd": "2956",
            "lrc": "0",
            "cc": "",
            "lre": "",
            "ipo": "1",
            "rmf": "00116751724240000201190040869",
            "15091": "0",
            "15082": "00116751724240000201190040869",
            "15083": "f6rdan-CDAkamjZZ7dCC9qVOJRAyY4IWYEPabHpcPLmufa_UWcV8zo8X3PdqiFA3IsHJSdnyHhvH7YMba9hOyaAScKB42zHlJ6qyU56xkFSB0kd_K_ac1HnzQ-j4L7K75x1WN1KBlulNfnKdcmEbcm2xfXhD8Fo0UD4e37iPnKY=",
            "15006": "1",
            "cuid": "693C07281680E73DEE0939642B459E59|VWINRN2KM"
        }
    ]
}

返回

{
    "token": "r92Z-2hhGHdoYCdoL9R18qAF6RX2s9wPlercbXOz2CYyjiSg2T6kNQChNaR4tarmYcaeax52Eqp_99DtsINspOg",
    "st": "56",
    "ver": "4.0.1",
    "nc": "0",
    "nt": 5,
    "op": 4,
    "da": [
        1,
        6,
        1
    ],
    "saws": "",
    "mts": "",
    "rmf": {
        "1": "",
        "2": "00116752376740010102449993047",
        "3": "cjm5Cxku3MV7co8HruoUQdFLrAk50M_sQxqjOM64vGEZTiL0FJldgebGDOMjuOBgaNapHDJCadFeM7xlV83ceoZk2v267GAF3urTv2KXV50="
    }
}

完整头部

  | POST /c/11/z/100/740017/1675172431/20a5e64ec9f17dd99c54c2ae7c514154?skey=%2F9YOITK4o%2FXrqthrWLm2%2Bg%3D%3D%0A HTTP/1.1
-- | --
x-device-id | 76e4d5ab08d1ec631f79e881095e0dfe
x-client-src | jar
User-Agent | x6/740017//4.1.4.2
Pragma | no-cache
Accept | */*
Content-Type | application/x-www-form-urlencoded
Accept-Encoding | gzip
Accept-Language | zh
x-sdk-ver | sofire/3.3.9.8.2
x-plu-ver | x6/4.1.4.2
x-app-ver | com.baidu.tieba_mini/
x-api-ver | 28
Host | sofire.baidu.com
Connection | Keep-Alive
Content-Length | 608

@n0099
Copy link

n0099 commented Feb 5, 2023

com.baidu.sofire.x6

https://github.com/n0099/open-tbclient/commits/src/com/baidu/sofire 在哪儿?

动态加载的dex位于/data/data/{PackageName}/files/.tmp/1-4.1.4.2.zip

所以是要运行时启动客户端后才会在app-specific storage里生成这个.zip.dex?疑似jvm元编程之asm hack
但即便是元编程他也会有藏在某处的生成代码如 https://en.wikipedia.org/wiki/Quine_(computing) ,除非他直接从百度服务端下载一个.zip.dex文件,那用户断网时首次启动客户端怎么办?

另外我已经基于starry神所提及的jadx对210个历史版本客户端提取了.proto文件,对260个客户端提取了所有.java文件以供阁下方便通过git toolchain查阅参考代码变迁

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants