第一章 · 起源

某日,想做个爬虫工具,爬某个网站上的数据已做实验之用。大家都知道爬pc网页上的数据有几个常见的问题:首先是数据不规范需要自己解析html,第二现在很多网站是前端动态渲染的,直接爬取的html可能就是个静态页面什么也没有,还需要执行js才能生成最终的页面。因此就考虑,能否用它App的接口去爬数据,因为一般App调用的接口返回的都是json格式,解析起来比较方便。

第二章 · 尝试

既然要抓取App的接口,肯定需要抓包,现在接口一般都用的https通信,直接抓二进制的tcp包是无法解密的。想到用Fiddler,它的原理很简单,就是启动一个https代理服务器,手机上设置Fidder启动的代理服务ip和端口。这是第一步,第二步就是证书,Fiddler会自己生成一个证书,把这个证书作为根证书导入的手机中,这时手机对Fiddler返回的证书就是可信任的。通信的时候,Fiddler作为客户端它会和服务端建立https连接,得到解密后的数据,然后自己启动一个https的服务,把数据返回给手机端。手机端这个时候实际访问的是Fillder启动的https服务,验证的证书也是Fillder自己颁发的。至于https如何验证签名如何加密通讯的这里就不做展开了,有兴趣的可以自己查阅。

但是,必须要说的是这样配置代理用Fiddler抓包的确可以抓到用手机浏览器访问的内容,现在App为了防止代理模式抓https的包,一般都会把证书放到自己的App中,验证https server返回的证书和App中的证书是否一致,这个时候server返回的证书是Fiddler自己颁发的,肯定和App本地的不一样所以App这时是无法访问接口的。

为什么Fiddler要自己颁发一个证书呢?这是由于Fiddler需要把和服务端通信的内容解密,所以它作为一个正常的client端先和服务端建立连接,验证服务端的证书,用服务端的证书上的公钥加密自己生成的对称秘钥,服务端拿到对称秘钥后用私钥解密,双方都知道对称秘钥,之后的通信用对称秘钥加解密。同理Fiddler作为App的代理服务器,也是要和app建立https连接的,这时如果直接返回服务端上的证书,App用服务端上证书的公钥加密App生成的对称秘钥。但是Fiddler没有证书的私钥,所以Fiddler需要自己颁发一个证书,有公私钥,才能和App正常的用https通信。

尝试用Fiddler代理抓App的包失败了

第三章 · 脱狱

遇到了问题,肯定要解决问题。现在问题的关键就是App验证本地证书和Fiddler返回的证书不一致,要做的就是绕开这验证,或者让App验证这个证书永远通过。不得不说,道高一尺魔高一丈,还真有这样的东西,根据维基百科的解释Xposed框架(Xposed framework)是一套开放源代码的、在Android高权限模式下运行的框架服务,可以在不修改APK文件的情况下修改程序的运行(修改系统),基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。

安装Xposed是有风险的,弄不好手机会变成砖,这里我就用模拟器替代手机安装了,下载MuMu模拟器,安装Xposed框架



同时还需要安装一个Xposed的一个插件Just Trust Me



安装好之后,我们再打开这个App,同时配置模拟器网络的代理,再用Fiddler抓包可以看到内容

第四章 · 柳暗花明

看到上面的截图,的确是找打了请求的地址,但是发现发出的请求内容是

{
"pagesize": 10,
"page": 1,
"platid": "0",
"langid": "0",
"typeid": "0",
"saletime": "全部",
"time": 1595672934792,
"sign": "c2522179dd87522f0d2997e28d48289e"
}

没错,有一个签名,这个签名一看就知道是md5做的,但是我不知道规则,而且生成的签名肯定是这些请求的参数加上一个字符串,最后md5一下,服务端还要验证签名,才能正常返回结果。这时仿佛又回到了原点,不解决这个签名,我们是无法正常请求服务的。要解决这个签名唯一的办法就是反编译包,从代码中发现蛛丝马迹。

apktool是一个开源的用于反编译apk包的工具,用它试试看能不能找到对应的md5加密的源码。用它反编译apk后,代码非常庞大,在里面搜索接口的名称djscreen竟然找到代码了

    invoke-static {}, Ljava/lang/System;->currentTimeMillis()J
move-result-wide v8
.line 493
.local v8, "time":J
new-instance v10, Ljava/lang/StringBuilder;
invoke-direct {v10}, Ljava/lang/StringBuilder;-><init>()V
const-string v11, "10"
invoke-virtual {v10, v11}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v10
iget v11, p0, Lcom/ws3dm/app/activity/GameCategoryActivity;->mPage:I
invoke-virtual {v10, v11}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
move-result-object v10
iget-object v11, p0, Lcom/ws3dm/app/activity/GameCategoryActivity;->platid:Ljava/lang/String;
invoke-virtual {v10, v11}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v10
iget-object v11, p0, Lcom/ws3dm/app/activity/GameCategoryActivity;->langid:Ljava/lang/String;
invoke-virtual {v10, v11}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v10
iget-object v11, p0, Lcom/ws3dm/app/activity/GameCategoryActivity;->typeid:Ljava/lang/String;
invoke-virtual {v10, v11}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v10
iget-object v11, p0, Lcom/ws3dm/app/activity/GameCategoryActivity;->saletime:Ljava/lang/String;
invoke-virtual {v10, v11}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v10
invoke-virtual {v10, v8, v9}, Ljava/lang/StringBuilder;->append(J)Ljava/lang/StringBuilder;
move-result-object v10
invoke-virtual {v10}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v7
.line 494
.local v7, "validate":Ljava/lang/String;
invoke-static {v7}, Lcom/ws3dm/app/util/StringUtil;->MD5(Ljava/lang/String;)Ljava/lang/String;

根据代码可以看到MD5的规则就是10+mPage+platid+langid+typeid+saletime+time然后送达工具com.ws3dm.app.util.StringUtil执行MD5方法,进入这个类看看怎么MD5的

    .method public static MD5(Ljava/lang/String;)Ljava/lang/String;
.locals 9
.param p0, "string" # Ljava/lang/String;
.prologue
.line 77
const-string v4, "e8S8Ho0N25z78u6qn4kHyN"
.line 78
.local v4, "key":Ljava/lang/String;
new-instance v5, Ljava/lang/StringBuilder;
invoke-direct {v5}, Ljava/lang/StringBuilder;-><init>()V
invoke-virtual {v5, p0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v5
invoke-virtual {v5, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v5
invoke-virtual {v5}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object p0

惊喜的发现传入的字符串+e8S8Ho0N25z78u6qn4kHyN然后再MD5就是结果

试试101000全部1595672934792e8S8Ho0N25z78u6qn4kHyN正好是c2522179dd87522f0d2997e28d48289e和抓包中的参数一致,搞定,到此基本上是破解结束了。后续还发现基本上所有的接口都是采取这种模式进行md5然后请求的。

第五章 · 终结

至此整个的抓包加破解的流程就结束了,整个过程其实是做二件事情,解决https验证证书,找到md5签名的规则。整个App相对而且是比较好破解的,整个MD5的过程都是Java写的,比较好反编译。这也是和后端通信,常见的一种处理方式。但是这种方式,的确不是很安全,没有很好的保护Api不被外部破解,比较安全的做法是把签名方法放到so中,或者对数据进行加密解密,同时也不要忘记混淆代码。

记一次抓包和破解App接口的更多相关文章

  1. 小迪安全 Web安全 基础入门 - 第三天 - 抓包&封包&协议&APP&小程序&PC应用&WEB应用

    一.抓包工具 1.Fiddler.Fiddler是一个用于HTTP调试的代理服务器应用程序,能捕获HTTP和HTTPS流量,并将其记录下来供用户查看.它通过使用自签名证书实现中间人攻击来进行日志记录. ...

  2. charles 抓包工具破解方法

    在线破解地址: https://www.zzzmode.com/mytools/charles/ 之后将下载的jar包替换  charles.app ->右键显示包内容 ->content ...

  3. 猫眼电影App抓包获取评论数据接口

     之前在CSDN程序人生公众号上看到了这篇文章<邪不压正>评分持续走低,上万条网友评论揭秘,是救救姜文还是救救观众?,文中提到了通过抓包猫眼App发现了评论的数据接口:http://m.m ...

  4. fiddler抓包,搞定接口

    上篇介绍的世纪佳缘登录是由已有cookie保持登录状态的.世纪佳缘登陆不需要填入验证码,可以很方便直接请求登录接口来达到登录状态的目的. 这篇介绍直接从登录接口进行登录,那么这就要求要找到登录接口ur ...

  5. mac 下使用Charles抓包华为手机app

    安装Charles:https://www.cnblogs.com/sea-stream/p/11577418.html 需要保证手机与电脑连接同一个Wi-Fi设置mac charles,打开代理 2 ...

  6. [转载]Fiddler 解析!抓包抓得好真的可以为所欲为 [一]

    说起抓包,很多人以为就是用个工具,简简单单地抓一下就可以了.昨天在面试一个安卓逆向,直接告诉我[抓包没有技术含量].在这里,我必须发一个教程,解析一下抓包神器——Fiddler.Fiddler仅仅是一 ...

  7. Fiddler和app抓包

    1:请在“运行”,即下面这个地方输入certmgr.msc并回车,打开证书管理. 打开后,请点击操作--查找证书,如下所示: 然后输入“fiddler”查找所有相关证书,如下所示: 可以看到,我们找到 ...

  8. 转:APP开发浅谈-Fiddler抓包详解

    原文地址:http://www.luoxudong.com/?p=306 Fiddler抓包工具在APP开发过程中使用非常频繁,对开发者理解HTTP网络传输原理以及分析定位网络方面的问题非常有帮助.今 ...

  9. Airmon-ng抓包&破解wifi

    安装  aircrack获取(aircrack源) sudo apt-get install aircrack-ng 配置 安装组件 sudo apt-get install build-essent ...

随机推荐

  1. ORACLE数据库数据被修改或者删除恢复数据(闪回)

    1. SELECT * FROM CT_FIN_RiskItem  --先查询表,确定数据的确不对  (cfstatus 第一行缺少) 2. select * from CT_FIN_RiskItem ...

  2. 堆/题解 P3378 【【模板】堆】

    概念: 堆就是一颗二叉树,满足父亲节点总是比儿子节点大(小).因此,堆也分为大根堆和小根堆,大根堆就是父亲节点比儿子节点大,小根堆正好相反.注意加粗的地方,是每一个节点哦!!!!! 还是直接看例题吧, ...

  3. python运行时报错can't find '__main__' module in 'xxx' 的解决办法

    刚开始学习python,想要使用pycharm来编辑和运行程序,所以就安装了下pycharm ,写了个简单的代码决定运行下,结果出现如下错误: 度娘找了一番,解决了问题,发现错误主要因为在这里 没有运 ...

  4. 强大的 actuator 服务监控与管理

    SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖 ...

  5. Cache写策略(Cache一致性问题与骚操作)

    写命中 写直达(Write Through) 信息会被同时写到cache的块和主存中.这样做虽然比较慢,但缺少代价小,不需要把整个块都写回主存.也不会发生一致性问题. 对于写直达,多出来%10向主存写 ...

  6. YAML & JSON &XML如何选择

    前言 本文翻译https://www.csestack.org/yaml-vs-json-vs-xml-difference/,下文会针对当前现有的数据序列化语言做下梳理.重点突出YAML是什么,优缺 ...

  7. 树的子结构(剑指offer-17)

    题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 解析 解答 /** public class TreeNode { int val = 0; Tr ...

  8. js数组算法题01

    题目:随机生成一个长度为 10 的整数类型的数组,例如 [2, 10, 3, 4, 5, 11, 10, 11, 20],将其排列成一个新数组,要求新数组形式如下,例如 [[2, 3, 4, 5], ...

  9. Scala 基础(十三):Scala 模式匹配(一)

    1 match 应用案例 Scala的模式匹配 案例代码完整: package com.atguigu.base object MatchDemo { def main(args: Array[Str ...

  10. 数据可视化之powerBI技巧(五)在Power BI中写出优雅的度量值是什么体验?

    之前的文章(采悟:连接表的几个DAX函数,一次全掌握)介绍了产品A的客户与产品B的客户的各种交叉关系,其中最常用的应该是找出A和B的共同客户,以便进行产品关联分析. 之前的思路是计算出两个产品的共同客 ...