某站平台的签名算法分享

  • 先charles抓包,api.xxxxxx.com域名的包

  • 分析包 看到路径参数如下

  • appkey=1d8b6e7d45233436&build=5531000&channel=dw056&mobi_app=android&mode=0&oid=326052200&plat=2&platform=android&ps=20&statistics=%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%225.53.1%22%2C%22abtest%22%3A%22%22%7D&ts=1705305495&type=1&sign=2c9086d4acc853a017ec087699902634
    可以看到一个sign,是个32字符,128位,直觉告诉我可能是个md5签名

  • 然后用jadx打开xxx.apk包,全局搜索sign字符串,在众多函数方法中,找到一个SignedQuery函数,跟进去看,发现又个loadLibrary(xxx),那么直接告诉我是在一个so里

  • 用apktool把xxx.apk decode出来,拿到libxxx.so

  • 用ida打开该libxxx.so,直接看JNI_OnLoad函数,找到这一行

    if ( (*v5)->RegisterNatives(v5, v4, (const JNINativeMethod *)&register_native_struct, 5) < 0

  • register_native_struct跟进去

 

  • 每个函数进去看下,有惊喜,确实是个md5算法,找到 md5_impl,跟进去看看算法参数

    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

    140

    141

    142

    143

    144

    145

    146

    147

    148

    149

    150

    151

    152

    153

    154

    155

    156

    157

    158

    159

    160

    161

    162

    163

    164

    165

    166

    167

    168

    int __fastcall md5_impl(JNIEnv *a1, jobject (*a2)(JNIEnv *, jclass, jmethodID, ...))

    {

    JNIEnv *v2; // r11

    jobject (*v3)(JNIEnv *, jclass, jmethodID, ...); // r6

    const char *v4; // r2

    const char *v5; // r1

    int result; // r0

    int v7; // r0

    JNIEnv v8; // r1

    int v9; // r0

    int v10; // r4

    int v11; // r0

    int v12; // r10

    signed int v13; // r9

    int v14; // r5

    int v15; // r8

    time_t v16; // r0

    int v17; // r6

    int v18; // r5

    const char *input_str; // r8

    _DWORD *v20; // r10

    int v21; // r4

    _DWORD *v22; // r0

    int v23; // r1

    int v24; // r2

    int v25; // r0

    unsigned int input_len; // r5

    signed int v27; // r4

    char *v28; // r5

    int v29; // r4

    const char *v30; // [sp+8h] [bp-C0h]

    int v31; // [sp+8h] [bp-C0h]

    int v32; // [sp+Ch] [bp-BCh]

    char v33; // [sp+10h] [bp-B8h]

    int s; // [sp+38h] [bp-90h]

    int v35; // [sp+3Ch] [bp-8Ch]

    int v36; // [sp+40h] [bp-88h]

    int v37; // [sp+44h] [bp-84h]

    char v38[24]; // [sp+90h] [bp-38h]

    int v39; // [sp+A8h] [bp-20h]

    v2 = a1;

    v3 = a2;

    if ( !sub_2D20((int)a1) )

    goto LABEL_5;

    v4 = "com.xxxxxxxx.nativelibrary.SignedQuery";

    v5 = "java/lang/ClassNotFoundException";

    LABEL_3:

    sub_401C((int)v2, (int)v5, (int)v4);

    result = 0;

    while ( _stack_chk_guard != v39 )

    {

    LABEL_5:

    if ( !v3 )

    {

      v5 = "java/lang/NullPointerException";

      v4 = "Null params!";

      goto LABEL_3;

    }

    v7 = is_empty(v2, (int)v3);

    v8 = *v2;

    if ( v7 )

    {

      v3 = v8->NewObject;

      result = ((int (__fastcall *)(JNIEnv *, int, int, _DWORD, _DWORD))v3)(

                 v2,

                 cls_signed_query,

                 signed_query_init,

                 0,

                 0);

    }

    else

    {

      v9 = ((int (__fastcall *)(JNIEnv *, const char *))v8->NewStringUTF)(v2, "appkey");

      v10 = v9;

      v11 = sub_60CC(v2, (int)v3, v9);          // // 校验appkey

      v12 = v11;

      if ( v11 )

      {

        v30 = (const char *)((int (__fastcall *)(JNIEnv *, int, _DWORD))(*v2)->GetStringUTFChars)(v2, v11, 0);

        v13 = check_app_key_get_type(v30);

      }

      else

      {

        v13 = -1;

        v30 = 0;

      }

      v14 = ((int (__fastcall *)(JNIEnv *, const char *))(*v2)->NewStringUTF)(v2, "ts");

      v15 = sub_60CC(v2, (int)v3, v14);

      if ( !v15 )

      {

        v36 = 0;

        v37 = 0;

        s = 0;

        v35 = 0;

        v16 = time(0);

        sprintf((char *)&s, "%ld", v16);

        ((void (__fastcall *)(JNIEnv *, int *))(*v2)->NewStringUTF)(v2, &s);

        sub_6188((int)v2);

      }

      sub_41D0(v2, v14);

      sub_41D0(v2, v15);

      v17 = ((int (__fastcall *)(JNIEnv *, int, int, jobject (*)(JNIEnv *, jclass, jmethodID, ...)))(*v2)->CallStaticObjectMethod)(

              v2,

              cls_signed_query,

              method_signed_query_r,

              v3);

      v18 = 0;

      if ( sub_3F70((int)v2) )

        v17 = 0;

      v32 = v17;

      input_str = (const char *)((int (__fastcall *)(JNIEnv *, int, _DWORD))(*v2)->GetStringUTFChars)(v2, v17, 0);

      if ( v13 != -1 )

      {

        ((void (__fastcall *)(JNIEnv *, int, const char *))(*v2)->ReleaseStringUTFChars)(v2, v12, v30);

        v20 = malloc(0x10u);

        if ( v20 )

        {

          v31 = v10;

          v21 = global_key[v13];

          v22 = &global_key[v13];

          v23 = v22[5];

          v24 = v22[10];

          v25 = v22[15];

          *v20 = v21;

          v20[1] = v23;

          v20[2] = v24;

          v20[3] = v25;

          _aeabi_memclr8(&v33, 33);

          input_len = strlen(input_str);

          _aeabi_memclr8(v38, 24);

          _aeabi_memclr8(&s, 88);

          md5_init(&s);

          md5_update((int)&s, (int)input_str, input_len);

          sprintf(v38, "%08x", v21);

          md5_update((int)&s, (int)v38, 8u);

          v27 = 1;

          do

          {

            sprintf(v38, "%08x", v20[v27]);

            md5_update((int)&s, (int)v38, 8u);

            ++v27;

          }

          while ( v27 != 4 );

          md5_final((int)v38, (int)&s);

          v28 = &v33;

          v29 = 0;

          do

          {

            sprintf(v28, "%02x", (unsigned __int8)v38[v29++]);

            v28 += 2;

          }

          while ( v29 != 16 );

          free(v20);

          v10 = v31;

          v18 = ((int (__fastcall *)(JNIEnv *, char *))(*v2)->NewStringUTF)(v2, &v33);

        }

        else

        {

          v18 = 0;

        }

      }

      sub_41D0(v2, v10);

      v3 = (*v2)->NewObject;

      result = ((int (__fastcall *)(JNIEnv *, int, int, int, int))v3)(v2, cls_signed_query, signed_query_init, v32, v18);

    }

    }

    return result;} 

  • 分析代码,发现关键在 check_app_key_get_type和global_key,一个是app key获取type,还有一个存着类似于secret key的 global key

  • 整体看下来,结论就是 md5加密,按参数字典序排序,然后拼接SecretKey,再md5得到sign,取其中一个type来验证下:

  • 图片描述


    和app请求生成的sign一样,secret key打码,如果想要,可以按步骤自己去试试,实测成功,关键地方都写清楚了

 最后,写个python脚本试试,确实都能访问,这里脚本就不放了,求赞求加精,求账号升级,感谢

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

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

相关文章

Unity Meta Quest MR 开发(三):Scene API 配置+实现虚拟与现实之间的碰撞

文章目录 &#x1f4d5;教程说明&#x1f4d5; Scene 配置⭐开启场景理解功能和应用访问空间数据的权限⭐OVRSceneManager⭐制作 Plane Prefab 和 Volume Prefab⭐运行场景⭐添加透视材质 &#x1f4d5;虚拟与现实物体的碰撞&#xff08;弹球 Demo&#xff09;&#x1f4d5;Mes…

TCP/IP协议以及TCP/IP邮件详细介绍

目录 1. TCP/IP 协议 2. 协议族 3. TCP - 传输控制协议 4. IP - 网际协议&#xff08;Internet Protocol&#xff09; 5. HTTP - 超文本传输协议(Hyper Text Transfer Protocol) 6. HTTPS - 安全的 HTTP&#xff08;HTTP Secure&#xff09; 7. SSL - 安全套接字…

LISN究竟是什么?有什么作用?

在电子领域中&#xff0c;LISN是一个充满神秘感的工具&#xff0c;常常被用于电磁兼容性测试。本文将深入探讨LISN的本质是什么&#xff0c;以及它在电子领域中扮演的关键角色。 1. 认识LISN LISN&#xff0c;全称为Line Impedance Stabilization Network&#xff0c;即线路阻…

CTF特训(二):青少年CTF-MISC部分WP

FLAG&#xff1a;当觉得自己很菜的时候&#xff0c;就静下心来学习 专研方向:MISC&#xff0c;CTF 每日emo&#xff1a;听一千遍反方向的钟&#xff0c;我们能回到过去吗&#xff1f; CTF特训(二)&#xff1a;青少年CTF-MISC部分WP&#xff1a; 文章目录 CTF特训(二)&#xff1…

vue——实现多行粘贴到table事件——技能提升

最近在写后台管理系统时&#xff0c;遇到一个需求&#xff0c;就是要从excel表格中复制多行内容&#xff0c;然后粘贴到后台系统中的table表格中。 如下图所示&#xff1a;一次性复制三行内容&#xff0c;光标放在红框中的第一个框中&#xff0c;然后按ctrlv粘贴事件&#xff0…

简单实践 java spring boot 自动配置模拟

1.概要 1.1 需求&#xff0c;自己写一个redis-spring-boot-starter模拟自动配置 自动配置就是在引入*-starter坐标后&#xff0c;可以已经spring框架的规则实现一些Bean的自动注入&#xff0c;并设置一些参数的默认值&#xff0c;且也可以在引入的工程中修改这些配置的值。这…

FANUC机器人示教器的菜单变成了图标,如何改成列表的形式?

FANUC机器人示教器的菜单变成了图标&#xff0c;如何改成列表的形式&#xff1f; 如下图所示&#xff0c;开机后按下MENU菜单键时&#xff0c;发现原来的列表形式变成了菜单图标的形式&#xff0c;同时在按F1-F5键时&#xff0c;提示&#xff1a;HMI模式-键不可用&#xff0c; …

企业申请sectigo ip https证书

Sectigo&#xff08;原名Comodo&#xff0c;在整合https证书业务后改名为Sectigo&#xff09;是一家知名的数字证书提供商&#xff0c;拥有多种类型的数字证书&#xff0c;例如单域名https证书、多域名https证书、通配符https证书、IP https证书和代码签名证书等满足各类用户的…

使用VScode编译betaflight固件--基于ubuntu平台

使用VScode编译betaflight固件--基于ubuntu平台 1、使用git克隆betaflight的开源代码2、配置编译环境3、使用VScode编译代码 window平台的见上一篇文章 使用VScode编译betaflight固件–基于windows平台 本文主要介绍在linux系统 ubuntu平台下使用VScode编译betaflight固件的方法…

某宝 bx-pp参数 反编译wasm还原算法

声明: 本文章中所有内容仅供学习交流&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; 前言: 听说最近某宝水果滑块出了一个bx-pp参数 是wasm加密,抱着好奇的心态打开的网…

TCP 连接掉线自动重连

文章目录 TCP 连接掉线自动重连定义使用连接效果 TCP 接收数据时防止掉线。TCP 连接掉线自动重连。多线程环境下TCP掉线自动重连。 欢迎讨论更好的方法&#xff01; TCP 连接掉线自动重连 定义 定义一个类&#xff0c;以编写TCP连接函数Connect()&#xff0c;并且&#xff1a…

MySQL原理(五)事务

一、介绍&#xff1a; 1、介绍&#xff1a; 在计算机术语中&#xff0c;事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务是恢复和并发控制的基本单位。 2、事务的4大特性 原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性…