拼多多anti-token分析

前言:拼多多charles抓包分析发现跟商品相关的请求头里都带了一个anti-token的字段且每次都不一样,那么下面的操作就从分析anti-token开始了

1.jadx反编译直接搜索

选中跟http相关的类对这个方法进行打印堆栈

结合堆栈方法调用的情况找到具体anti-token是由拦截器类f.a方法调用的,在http.a.c()方法中生成并且http.p.e()方法中加入请求头

在http.a.c()方法中有个一个判断条件如果为true则走d.a().e()方法生成anti-token

如果为false则走j()方法生成anti-token

hook这个i()方法返回值可知获取商品详情接口返回值为false所以走的是j()方法进行计算anti-token。

SecureNative.deviceInfo3()方法生成,传入的str为pdd生成的固定id 一个字符串.

根据hook_libart 得到info3()方法是在libodd_secure.so中,那么ida打开看看这个so包

2.这部分我们采用unidbg+jnitrace+frida相结合的方式

unidbg前期准备的代码这里就不发了直接调用这个info3方法

这里提示调用gad()方法返回一个字符串那么frida hook这个方法拿到这个值 如下图 一个固定的字符串

16位长度看着像AES的密钥 

继续补环境 这里简单补环境就不发了

补完简单的环境代码后,再次运行报这个错误 看错误应该是缺少文件 ,那么看看日志需要补那个文件

继续运行,没有返回值报空指针。execve()函数执行的时候程序exit了这里我们返回对象本身.

execve()函数执行的时候程序exit了

execve filename=/system/bin/sh, args=[sh, -c, cat /proc/sys/kernel/random/boot_id]

这个函数相当于查看 boot_id这个文件信息

捋顺下逻辑应该就是先fork进程 然后在子进程中读取这个文件 然后把他写入pip中

那么自定义syscallhandler后 再次运行成功拿到结果

 

全部代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

package pdd;

import com.github.unidbg.AndroidEmulator;

import com.github.unidbg.Emulator;

import com.github.unidbg.Module;

import com.github.unidbg.file.FileResult;

import com.github.unidbg.file.IOResolver;

import com.github.unidbg.file.linux.AndroidFileIO;

import com.github.unidbg.linux.android.AndroidARMEmulator;

import com.github.unidbg.linux.android.AndroidEmulatorBuilder;

import com.github.unidbg.linux.android.AndroidResolver;

import com.github.unidbg.linux.android.dvm.*;

import com.github.unidbg.linux.file.ByteArrayFileIO;

import com.github.unidbg.memory.Memory;

import com.github.unidbg.memory.SvcMemory;

import com.github.unidbg.spi.SyscallHandler;

import com.github.unidbg.unix.UnixSyscallHandler;

import java.io.File;

import java.nio.charset.StandardCharsets;

import java.util.ArrayList;

import java.util.List;

import java.util.UUID;

public class Pddmain extends AbstractJni implements IOResolver<AndroidFileIO> {

    private AndroidEmulator androidEmulator;

    private static final String APK_PATH = "/Users/Downloads/com.xunmeng.pinduoduo_6.7.0_60700.apk";

    private static final String SO_PATH = "/Users/Downloads/com.xunmeng.pinduoduo_6.7.0_60700/lib/armeabi-v7a/libpdd_secure.so";

    private Module moduleModule;

    private VM dalvikVM;

    public static void main(String[] args) {

        Pddmain main = new Pddmain();

        main.create();

    }

    private void create() {

        AndroidEmulatorBuilder androidEmulatorBuilder = new AndroidEmulatorBuilder(false) {

            @Override

            public AndroidEmulator build() {

                return new AndroidARMEmulator("com.xunmeng.pinduoduo",rootDir,backendFactories) {

                    @Override

                    protected UnixSyscallHandler<AndroidFileIO> createSyscallHandler(SvcMemory svcMemory) {

                        return new PddArmSysCallHand(svcMemory);

                    }

                };

            }

        };

        androidEmulator = androidEmulatorBuilder.setProcessName("").build();

        androidEmulator.getSyscallHandler().addIOResolver(this);

        Memory androidEmulatorMemory = androidEmulator.getMemory();

        androidEmulatorMemory.setLibraryResolver(new AndroidResolver(23));

        dalvikVM = androidEmulator.createDalvikVM(new File(APK_PATH));

        DalvikModule module = dalvikVM.loadLibrary(new File(SO_PATH), true);

        moduleModule = module.getModule();

        dalvikVM.setJni(this);

        dalvikVM.setVerbose(true);

        dalvikVM.callJNI_OnLoad(androidEmulator, moduleModule);

        callInfo3();

    }

    @Override

    public void callStaticVoidMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {

        if ("com/tencent/mars/xlog/PLog->i(Ljava/lang/String;Ljava/lang/String;)V".equals(signature)) {

            return;

        }

        super.callStaticVoidMethodV(vm, dvmClass, signature, vaList);

    }

    private void callInfo3() {

        List<Object> argList = new ArrayList<>();

        argList.add(dalvikVM.getJNIEnv());

        argList.add(0);

        DvmObject<?> context = dalvikVM.resolveClass("android/content/Context").newObject(null);

        argList.add(dalvikVM.addLocalObject(context));

        argList.add(dalvikVM.addLocalObject(new StringObject(dalvikVM, "api/oak/integration/render")));

        argList.add(dalvikVM.addLocalObject(new StringObject(dalvikVM, "dIrjGpkC")));

        Number number = moduleModule.callFunction(androidEmulator, 0xb6f9, argList.toArray())[0];

        String toString = dalvikVM.getObject(number.intValue()).getValue().toString();

        System.out.println(toString);

    }

    @Override

    public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {

        if ("com/xunmeng/pinduoduo/secure/EU->gad()Ljava/lang/String;".equals(signature)) {

            return new StringObject(vm, "cb14a9e76b72a627");

        else if ("java/util/UUID->randomUUID()Ljava/util/UUID;".equals(signature)) {

            UUID uuid = UUID.randomUUID();

            DvmObject<?> dvmObject = vm.resolveClass("java/util/UUID").newObject(uuid);

            return dvmObject;

        }

        return super.callStaticObjectMethodV(vm, dvmClass, signature, vaList);

    }

    @Override

    public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {

        if ("java/util/UUID->toString()Ljava/lang/String;".equals(signature)) {

            UUID uuid = (UUID) dvmObject.getValue();

            return new StringObject(vm, uuid.toString());

        else if ("java/lang/String->replaceAll(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;".equals(signature)) {

            String obj = dvmObject.getValue().toString();

            String arg0 = vaList.getObjectArg(0).toString();

            String arg1 = vaList.getObjectArg(1).toString();

            String replaceAll = obj.replaceAll(arg0, arg1);

            return new StringObject(vm, replaceAll);

        }

        return super.callObjectMethodV(vm, dvmObject, signature, vaList);

    }

    @Override

    public int callIntMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {

        if ("java/lang/String->hashCode()I".equals(signature)) {

            return dvmObject.getValue().toString().hashCode();

        }

        return super.callIntMethodV(vm, dvmObject, signature, vaList);

    }

    @Override

    public FileResult<AndroidFileIO> resolve(Emulator<AndroidFileIO> emulator, String pathname, int oflags) {

        if ("/proc/stat".equals(pathname)) {

            String info = "cpu  15884810 499865 12934024 24971554 59427 3231204 945931 0 0 0\n" +

                    "cpu0 6702550 170428 5497985 19277857 45380 1821584 529454 0 0 0\n" +

                    "cpu1 4438333 121907 3285784 1799772 3702 504395 255852 0 0 0\n" +

                    "cpu2 2735453 133666 2450712 1812564 4626 538114 93763 0 0 0\n" +

                    "cpu3 2008473 73862 1699542 2081360 5716 367109 66860 0 0 0\n" +

                    "intr 1022419954 0 0 0 159719900 0 16265892 4846825 5 5 5 6 0 0 497 24817167 17 176595 1352 0 28375276 0 0 0 0 5239 698 0 0 0 0 0 0 3212852 0 12195284 0 0 0 0 0 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12513 2743129 375 12477726 0 0 0 0 37 1351794 0 36 8 0 0 0 0 0 0 5846 0 0 0 0 0 0 0 0 0 141 32 0 55 0 0 0 0 0 0 0 0 18 0 18 0 0 0 0 0 0 66 0 0 0 0 0 0 0 77 0 166 0 0 0 0 0 394 0 0 0 0 0 1339137 0 0 0 0 0 0 313 0 0 0 55759 7 7 7 0 0 0 0 0 0 0 0 3066136 0 47 0 0 0 2 2 0 0 0 6 8 0 0 0 2 0 462 2952327 35420 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 495589 0 0 0 0 3 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 37662 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4760 0 0 97 0 0 0 0 0 0 0 0 0 243 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4649 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22355451 0 0 0 14 0 24449357 96 49415 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 17067 780222 3211 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 649346 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +

                    "ctxt 1572087931\n" +

                    "btime 1649910663\n" +

                    "processes 230673\n" +

                    "procs_running 6\n" +

                    "procs_blocked 0\n" +

                    "softirq 374327567 12481657 139161248 204829 7276312 2275183 26796 12851725 80988196 1422751 117638870";

            return FileResult.success(new ByteArrayFileIO(oflags, pathname, info.getBytes(StandardCharsets.UTF_8)));

        }

        return null;

    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/56320.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring 容器启动耗时统计

为了了解 Spring 为什么会启动那么久&#xff0c;于是看了看怎么统计一下加载 Bean 的耗时。 极简版 几行代码搞定。 import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor;import java.util.HashMap; imp…

k8s挂载映射操作详解

k8s投射数据卷 Projected Volume 在 k8s 中&#xff0c;有几种特殊的 Volume&#xff0c;它们的意义不是为了存放容器里的数据&#xff0c;也不是用来进行容器和宿主机之间的数据交换。"而是为容器提供预先定义好的数据。" 从容器的角度来看&#xff0c;这些 Volume…

SQL 错误 [22007]: ERROR: invalid input syntax for type date: ““

0. 背景 PG数据库一张表有这样一个varchar类型的字段end_date,存储的值是格式化后的年月日日期如 2024-08-10 现在我需要根据当前日期与end_date的差值作为where条件过滤,我的写法 select …… from my_table_name where current_date - cast (end_date as date) >100报错…

五度易链最新“产业大数据服务解决方案”亮相,打造数据引擎,构建智慧产业

快来五度易链官网 点击网址【http://www.wdsk.net/】 看看我们都发布了哪些新功能!!! 自2015年布局产业大数据服务行业以来&#xff0c;“五度易链”作为全国产业大数据服务行业先锋企业&#xff0c;以“让数据引领决策&#xff0c;以智慧驾驭未来”为愿景&#xff0c;肩负“打…

linux中互斥锁,自旋锁,条件变量,信号量,与freeRTOS中的消息队列,信号量,互斥量,事件的区别

RTOS 对于目前主流的RTOS的任务&#xff0c;大部分都属于并发的线程。 因为MCU上的资源每个任务都是共享的&#xff0c;可以认为是单进程多线程模型。 【freertos】003-任务基础知识 在没有操作系统的时候两个应用程序进行消息传递一般使用全局变量的方式&#xff0c;但是如…

基于Java+SpringBoot+Vue前后端分离社区医院管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

优化Python代理爬虫的应用

当我们在资源受限的环境中使用Python代理爬虫时&#xff0c;我们需要采取一些优化措施&#xff0c;以确保程序的高效性和稳定性。在本文中&#xff0c;我将分享一些关于如何优化Python代理爬虫在资源受限环境下的应用的实用技巧。 首先我们来了解&#xff0c;哪些情况算是资源…

【位运算进阶之----右移(>>)】

&#x1f604;嘻嘻&#xff0c;朋友们&#xff0c;大家好&#xff01;昨天我们学习了左移&#xff0c;今天我们来谈谈右移>>。 ⭐️简单来说&#xff0c;右移就是将一个数二进制表达整体向右移动&#xff0c;也就是去掉一个数的二进制表达的末位&#xff0c;右移一位就去…

Kaniko在containerd中无特权快速构建并推送容器镜像

目录 一、kaniko是什么 二、kaniko工作原理 三、kanijo工作在Containerd上 基于serverless的考虑&#xff0c;我们选择了kaniko作为镜像打包工具&#xff0c;它是google提供了一种不需要特权就可以构建的docker镜像构建工具。 一、kaniko是什么 kaniko 是一种在容器或 Kube…

字符集(Latin1,GBK,utf8,utf8mb4)

Latin1 1个字符占一个字节GBK 1个字符占两个字节utf8utfmb3 1个字节占三个字节utf8mb4 1个字符占四个字节

前端(十五)——GitHub开源一个react封装的图片预览组件

&#x1f475;博主&#xff1a;小猫娃来啦 &#x1f475;文章核心&#xff1a;GitHub开源一个react封装的图片预览组件 文章目录 组件开源代码下载地址运行效果展示实现思路使用思路和api实现的功能数据和入口部分代码展示 组件开源代码下载地址 Gitee&#xff1a;点此跳转下载…

Java入职第十一天,深入了解静态代理和动态代理(jdk、cglib)

一、代理模式 一个类代表另一个类去完成扩展功能,在主体类的基础上,新增一个代理类,扩展主体类功能,不影响主体,完成额外功能。比如买车票,可以去代理点买,不用去火车站,主要包括静态代理和动态代理两种模式。 代理类中包含了主体类 二、静态代理 无法根据业务扩展,…

C++Qt堆叠窗体的使用案例

本博文源于笔者最近学习的Qt&#xff0c;内容讲解堆叠窗体QStackedWidget案例&#xff0c;效果是选择左侧列表框中不同的选项时&#xff0c;右侧显示所选的不同的窗体。 案例效果 案例书写过程 控件都是动态创建的&#xff0c;因此.h文件需要创建控件&#xff0c;.cpp书写业务…

四层负载均衡的NAT模型与DR模型推导 | 京东物流技术团队

导读 本文首先讲述四层负载均衡技术的特点&#xff0c;然后通过提问的方式推导出四层负载均衡器的NAT模型和DR模型的工作原理。通过本文可以了解到四层负载均衡的技术特点、NAT模型和DR模型的工作原理、以及NAT模型和DR模型的优缺点。读者可以重点关注NAT模型到DR模型演进的原…

vue table合并行 动态列名

需求: 1.合并行,相同数据合并 2,根据后端返回数据动态显示列名, 我这个业务需求是,每年增加一列,也就是列名不是固定的,后端返回数据每年会多一条数据,根据返回数据显示列名 实现: html <el-table v-loading"loading" :data"dataList" :span-metho…

视频汇聚平台EasyCVR安防视频监控平台新增经纬度选取功能的详细介绍

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。音视频流媒体视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、…

ios ipa包上传需要什么工具

目录 ios ipa包上传需要什么工具 前言 一、IPA包的原理 二、IPA包上传的步骤 1.注册开发者账号 2.apk软件制作工具创建应用程序 3.构建应用程序 4.生成证书和配置文件 5.打包IPA包 6.上传IPA包 三、总结 前言 iOS IPA包是iOS应用程序的安装包&#xff0c;可以通过iT…

12. Oracle中case when详解

格式&#xff1a; case expression when condition_01 then result_01 when condition_02 then result_02 ...... when condition_n then result_n else result_default end 表达式expression符合条件condition_01&#xff0c;则返回…

性能测试流程? 怎么做性能测试?

一、前期准备 性能测试虽然是核心功能稳定后才开始压测&#xff0c;但是在需求阶段就应该参与&#xff0c;这样可以深入了解系统业务、重要功能的业务逻辑&#xff0c;为后续做准备。 二、性能需求分析&#xff08;评审&#xff09; 评审时&#xff0c;要明确性能测试范围、目…

[足式机器人]Part3机构运动微分几何学分析与综合Ch03-1 空间约束曲线与约束曲面微分几何学——【读书笔记】

本文仅供学习使用 本文参考&#xff1a; 《机构运动微分几何学分析与综合》-王德伦、汪伟 《微分几何》吴大任 Ch01-4 平面运动微分几何学 3.1 空间曲线微分几何学概述3.1.1 矢量表示3.1.2 Frenet标架 连杆机构中的连杆与连架杆构成运动副&#xff0c;该运动副元素的特征点或特…