首页
社区
课程
招聘
实战:某会员商店App的api接口分析
发表于: 2024-4-1 11:32 30606

实战:某会员商店App的api接口分析

2024-4-1 11:32
30606

1、目的

探索学习app接口的加解密机制,并通过api模拟调用的方式,发起业务请求。仅供学习。

2、工具准备

样本App版本:v5.0.80,v5.0.90

设备:Oppo R9s(Android7.1.1)+ MacOS Big Sur(Intel)

注入框架:xposed、frida(hluda 15.2.2)

反编译&其他:JEB、jadx、Charles

3、过程

大致分为抓包、脱壳、反编译、动态调试/加解密算法探索,构造模拟请求几个步骤,每个步骤都可能有不同的异常出现,本文主要记录在过程中的主体脉络和流程,过程中会附上关键代码。

3.1 抓包

首先尝试在手机上配置wifi代理,但Charles中无法看到相应的包记录。猜测是因为App屏蔽了网络代理,因此改用其他方式。手机上安装Drony,并开启手机全局网络代理(类型选择:socks5),代理地址指向Chares,此时就可以愉快的看到请求记录了。

image-20240326145803810

如果是通过iOS抓包,直接通过小火箭抓包也是灰常方便。另外下载Drony App可能需要TZ,解决无法访问的问题。

在抓到的报文中,可以看到每次请求中,都包含了一些奇怪的header,比如t、spv、n、st,这些字段大概率与api接口的加密与签名有关。接下来,需要结合代码进一步分析。

3.2 脱壳&反编译

直接通过Xposed + 反射大师App,即可做到轻松脱壳,App未针对Xposed做检测。脱壳后得到7个dex文件,使用python脚本合并,将7个dex文件利用jadx全部反编译成Java文件到同一目录,即可直接翻阅App反编译后的源码。

image-20240326120729769

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import os, sys
 
# 合并dex
# e.g:  python3 merge_dex.py ./source_dir/ output_dir
if __name__ == "__main__":
    if len(sys.argv) < 3:
        print("start error")
        sys.exit()
    source_dir = sys.argv[1]
    output_dir = sys.argv[2]
    print(source_dir, output_dir)
 
files = os.listdir(source_dir)
for file in files:
    if file.find(".dex") > 0:
        sh = '{your_path}/bin/jadx -Pdex-input.verify-checksum=no -j 1 -r -d ' + output_dir + " " + source_dir + file
        print(sh)
        os.system(sh)

这时直接在反编译的结果中搜索关键词"spv",却发现找不到。难道这些字段都隐藏到so中了,那就麻烦了。这时使用JEB再次反编译试试看,再次搜索"spv",找到了。

image-20240326151130082

这里,要提醒一下:针对反编译,同样的dex文件,用不同的反编译工具,结果也会不一样,可读性差异很多,因此当使用一种工具反编译失败的话,可以尝试用不同的工具,比如,通用一段代码的反编译结果,使用jadx时,提示反编译失败,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* JADX WARN: Code restructure failed: missing block: B:61:0x017a, code lost:
    r0 = r8.a("ssk");
    b.f.b.l.a(r0);
    r3 = r8.a("siv");
    b.f.b.l.a(r3);
    cn.xxxxclub.app.base.h.z.a(r0, r3);
 */
/* JADX WARN: Removed duplicated region for block: B:54:0x0168 A[Catch: Exception -> 0x018c, TryCatch #0 {Exception -> 0x018c, blocks: (B:42:0x0138, B:46:0x0154, B:48:0x015c, B:54:0x0168, B:56:0x0170, B:61:0x017a, B:45:0x014d), top: B:66:0x0138 }] */
/*
    Code decompiled incorrectly, please refer to instructions dump.
    To view partially-correct add '--show-bad-code' argument
*/
public okhttp3.ad intercept(okhttp3.w.a r19) {
    /*
        Method dump skipped, instructions count: 415
        To view this dump add '--comments-level debug' option
    */
    throw new UnsupportedOperationException("Method not decompiled: cn.xxxxclub.app.e.c.intercept(okhttp3.w$a):okhttp3.ad");
}

但是使用JEB时,结果则基本可用,如下:

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
public ad intercept(w.a arg19) {
      ....(略)
      String v8_1 = String.valueOf(z.b());
      v4_1.b("t", v8_1);
      l.b("dc1ad18e-3e2d-4d49-a303-f637c6a5a3fb", "randomUUID().toString()");
      String v9_1 = b.m.g.a("dc1ad18e-3e2d-4d49-a303-f637c6a5a3fb", "-", "", false, 4, null);
      v4_1.b("n", v9_1);
      v4_1.b("sy", "0");
      int v10_1 = v10 == 0 || !cn.xxxxclub.app.base.manager.d.a.i() ? 0 : 1;
      String v5_4 = this.a(((boolean)v10_1), v8_1 + v5_3 + v9_1 + g.a.b());
      if(((CharSequence)v5_4).length() > 0) {
          v4_1.b("st", v5_4);
      }
 
      v4_1.b("sny", (v10_1 == 0 ? "j" : "c"));
      v4_1.b("rcs", "1");
      v4_1.b("spv", "1.1");
      if(v11) {
          String v5_5 = URLEncoder.encode(String.valueOf(cn.xxxxclub.app.base.manager.f.a.b()), "utf-8");
          l.b(v5_5, "encode(LocationManager.g…de().toString(), \"utf-8\")");
          v4_1.b("Local-Longitude", v5_5);
          String v5_6 = URLEncoder.encode(String.valueOf(cn.xxxxclub.app.base.manager.f.a.a()), "utf-8");
          l.b(v5_6, "encode(LocationManager.g…de().toString(), \"utf-8\")");
          v4_1.b("Local-Latitude", v5_6);
      }
      ....
      return v5_7;
  }

3.3 动态调试分析

拿到反编译源码后,接下来就需要结合frida动态分析代码调用链,找到api调用的核心算法逻辑并加以验证。

image-20240326153601449


[注意]看雪招聘,专注安全领域的专业人才平台!

最后于 2024-6-13 09:38 被Dalin1编辑 ,原因: 添加原文链接,防无脑搬运
收藏
免费 3
支持
分享
最新回复 (26)
雪    币: 431
活跃值: (833)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
经典山姆会员店。。但是他的小程序好像没加密
2024-4-1 14:17
0
雪    币: 462
活跃值: (285)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
没有反编译过小程序,但是看抓包的报文,应该有用了微信的安全网关,报文请求和响应都是加密的。就没有深入研究山姆的小程序了
2024-4-1 14:22
0
雪    币: 4033
活跃值: (31446)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2024-4-1 14:48
1
雪    币: 1782
活跃值: (1935)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
Dalin1 没有反编译过小程序,但是看抓包的报文,应该有用了微信的安全网关,报文请求和响应都是加密的。就没有深入研究山姆的小程序了
这个是不是叫云函数?
2024-4-2 09:15
0
雪    币: 462
活跃值: (285)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
mb_fidppcok 这个是不是叫云函数?
不是,云函数类似于serverless,从客户端角度来看,和普通的http/https接口没区别。山姆这个报文都是加密了,大概率是用了腾讯的“Donut安全网关”,详细资料可以看看:6deK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6Q4x3X3g2%4k6h3W2^5K9h3&6Q4x3X3g2I4M7g2)9J5k6h3y4G2L8g2)9J5c8X3c8G2j5%4y4Q4x3V1k6Y4j5i4c8W2N6$3q4&6i4K6u0r3i4K6y4r3N6i4c8E0i4K6g2X3M7$3!0#2M7X3y4W2i4K6y4p5k6$3q4@1k6i4N6S2P5g2)9#2k6X3S2G2L8h3g2H3j5h3N6W2
2024-4-2 09:59
0
雪    币: 0
活跃值: (452)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
????????????????
2024-4-5 19:43
0
雪    币: 189
活跃值: (90)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8

最近在学习这个逆向,我只跟着做到RPC,剩下的去分析so看不明白,好像是动态加载的so,求指点

最后于 2024-4-15 20:08 被mb_ubjkchtw编辑 ,原因:
2024-4-15 19:47
0
雪    币: 462
活跃值: (285)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
我也没有深入分析so,只是发现低版本app的so跟最新版本app的不太一样,更简单一些。直接走rpc调用也就不用关心so细节了
2024-4-18 14:27
0
雪    币: 462
活跃值: (285)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
mb_ubjkchtw 最近在学习这个逆向,我只跟着做到RPC,剩下的去分析so看不明白,好像是动态加载的so,求指点
我也没有深入分析so,只是发现低版本app的so跟最新版本app的不太一样,更简单一些。直接走rpc调用也就不用关心so细节了
2024-4-18 14:29
0
雪    币: 1782
活跃值: (1935)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
Dalin1 不是,云函数类似于serverless,从客户端角度来看,和普通的http/https接口没区别。山姆这个报文都是加密了,大概率是用了腾讯的“Donut安全网关”,详细资料可以看看:https://d ...
那类似这样的方案,能拿到对应的代码或者Key?
2024-4-22 09:11
0
雪    币: 189
活跃值: (90)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
Dalin1 我也没有深入分析so,只是发现低版本app的so跟最新版本app的不太一样,更简单一些。直接走rpc调用也就不用关心so细节了
换思路通过曲线的方法搞出来了
2024-4-26 00:16
0
雪    币: 462
活跃值: (285)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
mb_fidppcok 那类似这样的方案,能拿到对应的代码或者Key?
理论上是可以的。小程序通过Dount组件,对接实际的请求和响应报文进行了加密。其具体加解密逻辑就需要逆向看看dount在客户端的各种处理了
2024-4-29 12:43
0
雪    币: 226
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
哥哥有v5.0.80版本的下载地址吗
2024-5-24 10:46
1
雪    币: 462
活跃值: (285)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
小日日 哥哥有v5.0.80版本的下载地址吗
dc4K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6S2M7r3E0H3N6i4u0W2i4K6u0W2L8X3g2@1i4K6u0r3M7$3S2S2L8W2)9J5k6r3#2#2i4K6u0V1K9s2g2A6i4K6u0V1P5i4g2S2L8W2)9J5k6s2y4Z5j5h3&6Y4i4K6u0V1k6r3W2S2L8W2)9J5c8X3y4F1i4K6u0W2M7$3q4E0M7$3y4D9N6h3u0Q4x3X3g2S2M7s2m8Q4x3V1k6V1L8%4N6F1L8r3!0S2k6q4)9J5c8U0g2Q4x3X3f1H3i4K6u0W2z5o6m8Q4x3U0k6F1j5Y4y4H3i4K6y4n7i4@1f1$3i4K6S2o6i4K6R3J5i4@1f1$3i4@1p5J5i4@1q4r3i4@1f1#2i4@1q4p5i4K6V1H3
2024-5-24 14:29
1
雪    币: 226
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
哥,我用objection尝试hook的时候提示找不到这个类,可以搜索到这个类,哥你是咋解决的呢,我用spawn也找不到,哥有联系方式吗,给红包
2024-5-25 11:31
0
雪    币: 226
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
我按照你的方式已经搞出来,objection尝试hook获取参数的时候不知道咋hook,希望大哥能教下
2024-5-25 11:59
0
雪    币: 859
活跃值: (945)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
酷安下载的最新版 5.0.104;抓包根证书就能直接抓到啊,而且直接用的hluda也没问题啊
2024-7-29 13:51
0
雪    币: 462
活跃值: (285)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
TrumpWY 酷安下载的最新版 5.0.104;抓包根证书就能直接抓到啊,而且直接用的hluda也没问题啊
是的,有些低版本的app是可以的,反调试做得相对弱一些
2024-7-30 16:52
0
雪    币: 227
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
21
怎么才能联系到你
2024-8-14 09:26
0
雪    币: 5138
活跃值: (4925)
能力值: ( LV10,RANK:171 )
在线值:
发帖
回帖
粉丝
22
感谢分享!!
2024-8-14 11:12
1
雪    币: 227
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
coneco 感谢分享!!
怎么才能联系你
2024-8-14 15:29
0
雪    币: 227
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
24
有人研究某会员商店有项目,加176074340
2024-8-14 17:37
0
雪    币: 251
活跃值: (1326)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
试试看看
2024-8-26 07:45
0
游客
登录 | 注册 方可回帖
返回