数据包修改、自动化脚本实现及app剖析

本文非教学,为技术探讨。不提供软件和环境,仅作技术分享。

鸣谢:XuanRan,参考了XuanRan的脚本。

测试软件:职校家园

目标:将app的定位改为自己想要的。

最初思路

思路一:使用虚拟定位,欺骗app,从而能够实现任意位置。

思路二:通过修改数据包的方法,使能够随意发送一个的位置。

虚拟定位

这方面并没有深入研究过,但我认为理论上来说是没有问题的,苦于没有找到合适的软件。

尝试了使用VMos ,在手机里面装了一个虚拟机,这样就有了root和XP框架,可以定位软件进行虚拟定位。但没有找到一个合适的虚拟定位软件。附VMos下载链接

VMos下载链接

修改数据包

 

手机抓包

首先,拦截手机数据包,对软件的数据包进行分析。这里有一个小技术点,如何用burp抓包手机app流量。可参考文章Burp抓取安卓模拟器包教程

有几个关键点

1.手机必须安装证书,否则只能抓浏览器http流量,应用的抓不了。

2.同一局域网电脑抓手机数据包,电脑可能需要关闭防火墙。

分析数据包

抓取到数据包后,就要对数据包进行分析

进行登录后,看到3个很明显的登录验证身份的数据包

4f4e194fa79741e0a2cfacc64c310163.png

 首先第一个请求

4415f5f14c2742c5b3088164b3612312.png

 与平常的数据包多了os,phone,Sign,cl_ip选项

第二个请求

622513ade3ee48c0a0ce97c8e9cd1432.png

请求头里面的 Sign值变了,POST请求里面写了登录的账号信息,同时有一个dToken,观察相应包,dToken作为deviceId返回了回来,同时返回了uid。

36b2f8d0e6604f5682986d1598328301.png

百度得deviceId是设备ID

47e17a1fb4724fa4845c1480598da97a.png

 第三个请求

87609795770f483b9ba6206a6466d7b5.png

 似乎是登录上去主页的信息,返回了许多图片信息。同时Sign值仍然发生了改变。

8b9ebca26e194a64be215ca40498c919.png

 拦截发送位置的数据包c0a6fb5870604456af5078b87590b43d.png

 一个POST请求将位置信息发送过去,address即为地点信息,longitude,latitude为经纬度。

尝试直接修改

afc1d8fa77cc432b8afd1a6363cb24eb.png

发现返回提示Sign验证错误,并没有成功。说明Sign值有单独算法生成并验证,参考文章服务器端数据合法性验证:签名sign和口令token原理

 如果想知道Sign算法,必然需要逆向分析

但是已经有位大佬XuanRan解了出来,他的图片给了我思路

5124ba2a37fd47dbbaba9a460476ab64.png

def login(user, token):
    password = getMd5(user["password"])
    deviceId = user["deviceId"]

    data = {
        "phone": user["phone"],
        "password": password,
        "dtype": 6,
        "dToken": deviceId
    }
    headers["Sign"] = getMd5((json.dumps(data) + token))
    url = 'http://sxbaapp.zcj.jyt.henan.gov.cn/interface/relog.ashx'
    res = requests.post(url, headers=headers, data=json.dumps(data))
    return res.json()

Sign的生成算法即为POST请求的表单+token值,然后进行md5运算得到。

更改数据包

知道了这些信息之后,重新拦截发送位置的数据包,修改地址信息后,重新计算Sign值再发送。成功更换数据包中的位置信息!

2a1959edc6d6493d8aab51b2e74711bf.png

 至此,已经完全实现需求。但是问题还没有结束,如何写自动化脚本运行及Sign值的算法如何逆向出来,成为值得深入探讨的问题。

脚本自动化

这里脚本直接使用了XuanRan的脚本,节约了很多时间,再次感谢。

整体脚本编写思路和上文数据包分析步骤一样,分为三步走

获取token-->登录--->发送修改后数据包

具体实现不再赘述。

部署到服务器

这里采用了华为云的“函数工作流 FunctionGraph”,腾讯云的云函数和其作用相同,但是腾讯云函数从大约6月份开始收费,所以不采用。

(第一次注册华为云,还有人给我打电话,听说我只是用函数工作流不买服务器,好像很失望)

部署过程中遇到的值得注意的点。

代码的导入与执行

需要注意,程序的入口函数在设置里面指定,同时还需要调高执行超时时间,防止还没响应就已经超时。

f497ef71bf254437ab3f1e936bcce8a8.png

 文件名需要在最外层,也就说导入完文件后,须在在外层创建一个python文件写一个函数调用主函数。

建议打开监控功能,同样小流量是免费的

ac7e236f4b6b41cbb8f28d8daad24bcb.png

 

发送通知也很有意思,可以组群发送,这里不再展开说。微信推送

定时任务

需求是周一到周五的早上运行脚本发送数据包,这里创建了一个触发器来实现功能。

Cron表达式可以在线生成在线Cron表达式生成器

d171cef82c0148d59f0565d620388559.png

 app逆向

这为整个技术的核心内容,同时也是完成后花费大量时间研究的内容。

其中走了很多弯路,浪费相当多的时间,这里进行总结。

步骤一:脱壳

直接放入jadx-gui里面看

3c53491e0de44c5c9a3a5f015d0db29c.png

明显的看不到任何有用的代码

d5b78d3dc85543fbbb62a88bbcf67c87.png

 使用查壳工具,发现是360加固。

这里参考了一篇文章Android逆向 某州 解密sign字段 so层 算法分析 Unidbg模拟执行

 883b88283db643a08ddcba7f65ac68a0.png

 实际上这个软件用dump_dex.js无法成功脱掉,而且步骤复杂。

最终参考CTF逆向-[网鼎杯 2020 青龙组]bang-安卓脱壳逆向:frida-dexdump导出得到源码

c4b84db8a594477ab668ee3977ad3c57.png

使用frida-dexdump成功脱掉

f4cc18dc835e4b8f967566442e8de965.png

frida安装

Frida详细安装教程

参考的上面教程,简单来说windows端安装只需要

pip install frida
pip install frida-tools

 然后就可以命令行使用frida了。

通过adb将frida服务端安装到手机里

这里使用模拟器较方便,我用的是雷电模拟器

05b3b6624c0c4fd8a4cb64a70d93915f.png

有时候连不上,需要-s指定是哪个虚拟机

 72a57f569871407784216c2a92eb9536.png

使用adb push命令将frida-server传入虚拟机

使用dump_dex.js脱壳可以参考此文章 APP脱壳过程2(新手入门)

 dump_dex.js可以在Github上下载到。

这里提一个点,新版frida已经没有--no-pause选项,会报错

frida: error: unrecognized arguments: --no-pause

b0edb11191534beb9d6853f4a779a3bc.png

b644d4ebc4c349aaa4f6f02c50cc1699.png

 步骤二:审代码,找算法。

代码量非常之大,虽然脱壳可以像CTF一样,但是找最终代码不像CTF可以直接搜索flag。任务的复杂在于如何从海量代码中定位到需要的代码片段。

上面那篇文章前面脱壳的步骤让我走了弯路,但是后面的内容让我很有启发

8cff0262fbca4b36b298126d33b4b6ef.png

 一开始搜索 sign 结果太多,上千条(耗费相当多时间)。但是搜 "sign"让我快速定位

17a723c1872847ec8f6e47042ee6ceb8.png

                try {
                    C1300f fVar2 = new C1300f();
                    d0Var.mo8318e(fVar2);
                    String obj3 = C1408p.m5680U(fVar2.readString(forName)).toString();
                    String c = App.m8798a().mo7477c("token");
                    f.d(c);
                    String a = Md5Util.m6928a(f.m(obj3, c));
                    Request.C2269a aVar2 = new Request.C2269a(zVar);
                    aVar2.f9606c.mo9156a("Sign", a);
                    String m = j1.m(App.m8799b());
                    if (m == null) {
                        m = "";
                    }
                    aVar2.f9606c.mo9156a("cl_ip", m);
                    zVar = aVar2.mo9191a();
                } catch (Exception e) {
                    Log.e("EncryptInterceptor", f.m("加密异常====》", e));
                    return fVar.mo9731b(zVar, fVar.f10813b, fVar.f10814c);
                }
            }

由代码可以看出来Sign是变量obj3和变量c拼接后MD5而成,而c正是token,obj3是某一个对象转成了字符串(这个地方还有待深入研究)不难猜出是和POST请求的表单内容+token拼接后MD5运算而得。

前面在发送请求时候,尝试过不同的POST请求表单内容,发现只要表单内容不变,Sign值就不变,也可以印证这一点。

这一个环节仍然有许多东西值得深入研究,但是时间原因,就先到这里。

 

总结:

整个过程涉及数据包修改,到自动部署,到安卓逆向及其他一些细枝末节。

再次鸣谢XuanRan

 

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值