Frida java层自吐加密算法
Frida java层自吐加密算法
本文转自愧怍 并作补充
代码
针对 java 层加密算法,能 hook 到 java 自带的加密函数库
1 | const config = { |
本文转自愧怍 并作补充
针对 java 层加密算法,能 hook 到 java 自带的加密函数库
1 | const config = { |
本文转自nosafer 并作补充
Nginx 1.18.0及之前版本中存在安全漏洞。攻击者可利用该漏洞进行缓存投毒,劫持凭证或绕过安全保护。
Nginx <= 1.8.0
1 | GET /test.html |
1 | 200 OK |
1 | GET / |
1 | 200 OK |
1 | GET / |
1 | 200 OK |
本文转自thinkoaa 并作补充
之前写了一个burp插件,直接使用目标站点的加密js来解决用intruder模块爆破时的payload加密问题
地址:https://www.freebuf.com/sectool/242363.html
除了上面的情况外,有时还会遇到把burp当作代理,调用网站的js代码处理来自浏览器、sqlmap等工具的内容情况。
比如目标网站的参数调用了js加密算法,不管是手动访问也好,还是sqlmap注入也好,需要调用指定算法处理参数,用python或java重写算法的话呢,时间成本太高,有些算法还挺复杂……但,如果能够直接复用目标网站的js代码的话就太方便了。
因此,简单写了一个burp suite插件,专门解决上述问题:下载地址:JSFlash
使用步骤是 可以参考我之前另一个插件的文章 参考地址:
- 1.把目标站点的相关js代码放到本地js文件中,调试可用;
- 2.把JSFlash插件导入到Burp Suite中,在插件中加载指定的js文件并填写对应的参数;
- 3.抓包发repeater做测试,如果效果符合预期,则该插件会根据指定的规则,调用js代码,处理指定的内容。
效果图:
因为插件是通过java调用js,因此window、document等对象及方法,还有一些很新的js特性可能在浏览器中执行正确,但插件调用时会报错,因此插件会把可能产生的错误信息弹出显示,方便根据实际逻辑修改,根据我的经历来看,不管多复杂,只要耐心点,没有改不了的情况,如图:
再举一个例:
2.1 设置url,一定要用burp的Copy URL菜单复制,不要手动填写,以免出错:
2.2 设置处理指定内容的规则
GET方式:
php代码如图:
处理结果:
POST方式:
php代码如图:
结果如图:
一次调用多个方法,处理多个指定内容:
数据包:
规则:
php代码:
结果:
这个插件用到的时候,需要具体情况具体分析,不过思路是这么个思路,目的就是复用js代码,提高工作效率。
本文转自ichi9o 并作补充
通常情况下,数据包中的签名字段会包含sign字符串,如sign、appsign等等,然后根据字段在JS代码中寻找签名的过程,并进行分析。
以下内容为一个真实案例,撒,哈气灭路!
通过数据包可知该网站的签名字段是 sign
在浏览器中的源代码搜索字段sign,找到签名代码
首当其冲的就是app.*.js样式的文件,在app.72b81572.js文件中发现了可疑点分析 function k(e) 可知,是要对 r 参数进行签名的,r 又跟e、t、a、n 这几个参数相关,因此要搞清楚这几个参数的值是怎么来的,所有就在函数开始的第一行就下断点来跟进。
1
2
3
4
5
6
7
8
9
10
11
12 function k(e) {
const t = g()
, n = m();
let a;
a = e ? b(e) : {};
const r = e ? `${c.a.stringify(a.hasParams)}&${t}&time=${n}` : `&${t}&time=${n}`;
return e = Object.assign({}, a.params, {
sign: h()(decodeURIComponent(r)),
time: n
}),
e
}首先是 t,跟进 g 函数,执行到 return 就可以发现 t = 年 + “5616” + 月 + 日
然后就是 n,这个 e 的值呢,根据跟进可知是 cookie 里面的,不过这个 e 在本案例的作用不大,最后通过 return 就可以知道返回的值就是:当前时间戳- e
接下来就是 a,根据返回的结果可知 a 的值和 e 相同,通过分析数据包可知,e的内容即请求参数(GET)或请求体(POST)
然后 r 的值就出来了,也就是签名的明文
综上所述
r = 请求内容 + & + t + & + n(这里的请求内容需要注意的是,POST Data是Json格式的要转换为:key1=value1&key1=value1…)
其中
t = 年 + “5616” + 月 + 日
n = 当前时间戳(本案例可不减e也可成功)
将断点打在签名代码行,跟进代码的执行,发现加密的类名是 Md5,所有可以计算 r 的 md5 值,与代码执行的 sign 结果进行比较。
可以看到,该网站使用的是 md5 计算的 sign
mitmproxy 脚本是实时加载的,因此 mitmproxy 只要带着脚本运行,就可以边调试了。
mitmproxy 使用命令
1 mitmdump -p 777 -s .\mitmscript.py --flow-detail 0关于脚本的编写这里给出以下 mitmproxy 的一些常用的属性和方法ctx:
- ctx.log.info(): 用于在 mitmproxy 的日志中输出信息。
- ctx.options: 用于访问 mitmproxy 的配置选项,您可以在配置文件中定义这些选项。
- ctx.master: mitmproxy 的 Master 对象,提供了一些控制代理行为的方法。
- ctx.proxy: mitmproxy 的 ProxyConfig 对象,提供了有关代理配置的信息。
- ctx.client: mitmproxy 的 ClientConnection 对象,表示客户端连接的相关信息。
- ctx.server: mitmproxy 的 ServerConnection 对象,表示服务器连接的相关信息。
- ctx.protocol: mitmproxy 的 ProtocolHandler 对象,表示处理请求和响应的协议处理器。
在 mitmproxy 脚本中,可以使用以下一些回调函数来处理不同阶段的 flow 对象:
- def request(flow: mitmproxy.http.HTTPFlow) -> None: 当 mitmproxy 拦截到请求时调用此回调函数,可以获取和处理请求的各种信息。
- def response(flow: mitmproxy.http.HTTPFlow) -> None: 当 mitmproxy 拦截到响应时调用此回调函数,可以获取和处理响应的各种信息。
- def error(flow: mitmproxy.http.HTTPFlow) -> None: 当请求或响应出现错误时调用此回调函数,可以获取和处理错误信息。
- def clientconnect(flow: mitmproxy.tcp.TCPFlow) -> None: 当客户端连接到 mitmproxy 时调用此回调函数,可以获取和处理客户端连接的相关信息。
- def serverconnect(flow: mitmproxy.tcp.TCPFlow) -> None: 当 mitmproxy 连接到服务器时调用此回调函数,可以获取和处理服务器连接的相关信息。
- flow.request.method: 获取请求的方法(GET、POST等)。
- flow.request.scheme: 获取请求的协议(http 或 https)。
- flow.request.host: 获取请求的主机名。
- flow.request.port: 获取请求的端口号。
- flow.request.path: 获取请求的路径部分。
- flow.request.url: 获取完整的请求URL。
- flow.request.headers: 获取请求的头部信息,是一个字典对象,可以通过键来访问特定的头部字段。
- flow.request.cookies: 获取请求中的Cookie信息,是一个字典对象,可以通过键来访问特定的Cookie。
- flow.request.query: 获取请求的查询参数,是一个字典对象,可以通过键来访问特定的查询参数。
- flow.request.content: 获取请求的内容,如果请求是POST请求且带有内容,则可以通过该属性来访问请求的内容。
- flow.request.text: 获取请求的内容,并以文本形式返回。
- flow.request.urlencoded_form: 获取请求的URL编码表单数据,是一个字典对象,可以通过键来访问特定的表单字段。
- flow.request.multipart_form: 获取请求的多部分表单数据,是一个列表对象,列表中的每个元素都是一个字典,表示一个表单字段。
- flow.request.content: 获取请求的原始内容,以字节形式返回。
附上本案例的代码供参考
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 from datetime import datetime
from mitmproxy import ctx
import hashlib
import random
import json
import time
class Modify:
def __init__(self):
self.plaintext = ''
self.new_sign = ''
current_datetime = datetime.now()
self.today = f"{current_datetime.year}5616{current_datetime.month:02d}{current_datetime.day:02d}"
def md5(self):
md5_hash = hashlib.md5()
md5_hash.update(self.plaintext.encode('utf-8'))
self.new_sign = md5_hash.hexdigest()
def request(self, flow):
if flow.request.method == "POST":
ctx.log.info(f'\n原POST请求体:{flow.request.text}')
data = json.loads(flow.request.get_text())
if data != '{}' and 'sign' in data:
del data['sign']
del data['time']
for k in data:
self.plaintext += f"{k}={str(data[k])}&"
timestamp = int(time.time() * 1000)
self.plaintext += f"{self.today}&time={timestamp}"
self.md5()
data["sign"] = self.new_sign
data["time"] = timestamp
flow.request.set_text(json.dumps(data).replace(' ', ''))
ctx.log.info(f'\n新POST请求体:{flow.request.text}')
self.plaintext = ''
else:
ctx.log.info('无参数,无需改签')
elif flow.request.method == "GET":
ctx.log.info(f'\n原GET请求体:{flow.request.query}')
query = flow.request.query
if query != '{}' and 'sign' in query:
del query['sign']
del query['time']
if query:
for k in query:
self.plaintext += f"{k}={str(query[k])}&"
else:
self.plaintext = "&"
timestamp = int(time.time()) * 1000
self.plaintext += f"{self.today}&time={timestamp}"
self.md5()
query["sign"] = self.new_sign
query["time"] = timestamp
ctx.log.info(f'\n新GET请求体:{flow.request.query}')
self.plaintext = ''
else:
ctx.log.info('无参数,无需改签')
def response(flow):
if '签名校验失败!' in flow.response.text:
ctx.log.error(f'\n签名异常:\nurl => {flow.request.path}\n异常信息 => {flow.response.text}')
addons = [
Modify()
]
本文转自强人电子 并作补充
nRF Connect支持缓存事件记录以及录播和重演,接下来我们看看这到底是个怎样的功能。
在连接上设备后,向左滑动可以切换到事件记录页面,同时支持多种LOG格式,如下图中连接上后执行了一次读取电量的操作:
LOG记录支持复制、保存为文件、分享和清除:
nRF Connect支持事件的录播和重演,实质上就是在上一节记录的基础上,从某个时间点开始截取然后保存,录播是根据刚刚保存的记录对蓝牙设备进行一模一样的指令及数据操作。
在已连接界面中,点击右下角的红色部分:
会弹出三个图标,分别表示:
- 新建文件夹(用于存放后续的录播文件)
- 导入录播文件(导入其他地方的录播文件,本机录播的会默认显示在文件列表里,不需要导入)
- 开始录播
- 创建一个“da bai”文件夹
- 点击第三个图标开始录播
- 开始录播后,可以发起通信事件
顺序为:开始录播 => 读取电量 => 读取厂商信息 => 读取硬件版本号 => 读取软件版本号 => 结束录播可以看到LOG记录是这样的:
命名录播文件为”read info”以及将其移动到”da bai”文件夹下:
录播文件保存下来后,可以对其进行重演,相当于执行一遍刚刚录播的操作:
重演录播后,我们再去看看事件记录,确实再一次操作了录播的内容,时间间隔竟然也是一样的:
录播文件支持这些操作:
- Export to XML
- Rename
- Move
- Mirror
这里重点聊聊 Export to XML 和 Mirror。
支持将录播文件导出为XML文件可以分享给他人使用,导出之后是这样的:
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 <macro name="read info" icon="PLAY">
<assert-service description="Ensure Battery Service" uuid="0000180f-0000-1000-8000-00805f9b34fb">
<assert-characteristic description="Ensure Battery Level" uuid="00002a19-0000-1000-8000-00805f9b34fb">
<property name="READ" requirement="MANDATORY"/>
</assert-characteristic>
</assert-service>
<assert-service description="Ensure Device Information" uuid="0000180a-0000-1000-8000-00805f9b34fb">
<assert-characteristic description="Ensure Manufacturer Name String" uuid="00002a29-0000-1000-8000-00805f9b34fb">
<property name="READ" requirement="MANDATORY"/>
</assert-characteristic>
<assert-characteristic description="Ensure Hardware Revision String" uuid="00002a27-0000-1000-8000-00805f9b34fb">
<property name="READ" requirement="MANDATORY"/>
</assert-characteristic>
<assert-characteristic description="Ensure Software Revision String" uuid="00002a28-0000-1000-8000-00805f9b34fb">
<property name="READ" requirement="MANDATORY"/>
</assert-characteristic>
</assert-service>
<read description="Read value of Battery Level" characteristic-uuid="00002a19-0000-1000-8000-00805f9b34fb" service-uuid="0000180f-0000-1000-8000-00805f9b34fb">
<assert-value description="Assert value equals 'd'" value-string="d"/>
</read>
<read description="Read value of Manufacturer Name String" characteristic-uuid="00002a29-0000-1000-8000-00805f9b34fb" service-uuid="0000180a-0000-1000-8000-00805f9b34fb">
<assert-value description="Assert value equals 'YFTech'" value-string="YFTech"/>
</read>
<read description="Read value of Hardware Revision String" characteristic-uuid="00002a27-0000-1000-8000-00805f9b34fb" service-uuid="0000180a-0000-1000-8000-00805f9b34fb">
<assert-value description="Assert value equals 'UVWbejJZpqrsPtwuvxy'" value-string="UVWbejJZpqrsPtwuvxy"/>
</read>
<read description="Read value of Software Revision String" characteristic-uuid="00002a28-0000-1000-8000-00805f9b34fb" service-uuid="0000180a-0000-1000-8000-00805f9b34fb">
<assert-value description="Assert value equals 'V 2.66.0329'" value-string="V 2.66.0329"/>
</read>
</macro>
导入之后自动重命名为read info 2。
这里的镜像指的是角色镜像,比如录播文件里面你是中央设备,镜像之后你就变成了外围设备。这里必须注意当你是外围设备的时候,需要将GATT SERVICE配置成录播文件的一样的配置,具体配置方法可以参考GATT SERVICE配置,建议使用克隆方式。
在BLE开发中,同样的测试内容通常不止操作一次,此时我们可以用上本章的内容,事半功倍!
看完本文觉得有帮助点赞鼓励鼓励吧~如果有问题可以在评论区留言,大白会用光的速度回复您。想了解关于nRF Connect的更多用法及使用技巧,可以关注nRF Connect 专栏。
本文转自seclst 并作补充
在这篇文章中,我们将讨论如何使用BtleJuice通过执行中间人(MiTM)攻击来利用一个蓝牙低能耗(BLE)智能灯泡。本文中探讨的技术,也同样适用于其他基于BLE的智能设备。
本文的主要内容包括:
1
2
3
4
5
6
7 安装BtleJuice;
分析在目标设备上运行的所有截获的GATT操作;
使用GATT操作执行Man-in-the-middle(中间人)攻击;
将数据导出到文件。以下是一些必须满足的基本硬软件要求:
1
2
3 基于BLE的物联网智能灯泡
两个蓝牙适配器
1
2
3
4
5 Node.js > 4.3.2
虚拟机(VMware/Virtual Box)
BtleJuice
BtleJuice是执行蓝牙智能设备的中间人攻击(也被称为蓝牙低能量)的完整框架。BtleJuice由两个组件组成 - 拦截代理和核心。这两个组件需要在两个系统上单独运行,每个系统都连接了蓝牙4.0+适配器。我们将使用一台物理机器和另一台运行在同一主机上的虚拟机(VM)。
注意:不是使用两台独立的物理机器。其中一个适配器将连接到主机,另一个适配器连接到VM。下面,我们按照以下步骤在主机和VM上来安装BtleJuice。
Step 1:Btlejuice需要一个相当新版本的node(>=4.3.2) 和npm。你可以按照本指南使用nvm(Node 版本管理器)来进行安装。
Step 2:使用包管理器安装BtleJuice的依赖项:
1 sudo apt-get install bluetooth bluez pbbluetooth-dev pbudev-devStep 3:安装 Btlejuice:
1 npm install -g btlejuice
Step 1:将蓝牙适配器连接到VM并启动蓝牙:
1 service bluetooth startStep 2:通过hciconfig命令查看适配器是否已按预期工作:
Step 3:在虚拟机中启动btlejuice-proxy:
Step 4:找到VM的IP地址,以便我们可以从主机连接到它。或在终端中运行ifconfig来获取IP:
Step 1:在主机上打开终端并运行hciconfig:
Step 2:运行sudo service bluetooth stop停止蓝牙服务:
Step 3:在主机上插入蓝牙适配器:
Step 4:通过hciconfig命令查看连接到主机的蓝牙适配器是否已按预期工作:
Step 5:通过运行sudo hciconfig hciX up打开蓝牙适配器,其中的X是上一步中获得的蓝牙适配器号:
Step 6:现在我们需要运行BtleJuice核心并连接虚拟机:
1 sudo btlejuice -u <VM IP address> -w其中u是运行btlejuice-proxy的VM的IP地址,w表示启动Web界面:
与此同时,在VM中运行的btlejuice-proxy将会显示客户端连接的消息:
Step 7:一旦主机上运行的BtleJuice核心成功连接到bltjejuice-proxy,我们打开浏览器并导航至http://localhost:8080/:
Step 8:单击蓝牙图标的 “Select Target”按钮。此时将会出现一个对话框,并显示核心检测到的所有可用蓝牙设备:
Step 9:双击目标设备并等待接口准备就绪(蓝牙按钮方面将改变):
Step 10:将关联的移动应用程序与刚创建的dummy设备连接:
Step 11:如果连接成功,则主界面上将显示已连接的事件:
BtleJuice充当移动应用程序和BLE智能灯泡之间的代理,发送到灯泡的任何命令都将被BtleJuice捕获并被转发给灯泡。
让我们使用移动应用程序与灯泡进行交互,并尝试破译命令的结构方式。
Step 1:使用Android应用程序将灯泡颜色更改为蓝色,蓝色的RGB值为:2, 0, 255:
BtleJuice捕获相应的数据包:
现在将灯泡颜色更改为红色,RGB值为: 255, 8, 0:
BtleJuice捕获与命令相对应的数据包,以将颜色更改为红色:
检查数据包,我们可以注意到一个模式。应用程序中显示的颜色的RGB值与捕获中的第二个,第三个和第四个字节匹配。
因此,如果我们更改这些字节然后重放数据包,应该能够获得不同的颜色。
Step 2:从捕获的数据包列表中,右键单击颜色更改命令,然后单击replay:
Step 3:将数据值中的颜色字节从8c 86 ff更改为任何其他值,例如8c 45 ff,这是一种带有紫色调的颜色:
Step 4:单击“ Write”按钮。 我们会注意到灯泡颜色变为了紫色:
BtleJuice可以将捕获的数据导出到文件中,以便以后使用或在其他工具中进行分析。
单击export按钮并下载捕获数据的JSON(或文本)版本:
至此,我们已经演示了BtleJuice作为独立工具的使用。
此外,BtleJuice还提供了NodeJS和Python bindings,我们可以在我们自己的BLE攻击工具中使用它。有关更多信息,请参阅此处。
我得说一句,这可能是明日方舟第一次限定把陪跑风头几乎完全压住的一次
虽然我并不认为黍太超出预期,一是看莱茵看多了习惯这样的配色,而是梯田与闽南语这样的象征我从小就在接触(有生之年能听到客家话嘛?)……
但是确实还是超出预期了(这都什么发言啊,已经混乱了),然而我还要两三个小时才下班QAQ
最后感谢鹰角送的新年贺词,诶,是什么来着?
感觉是可以拿来镇宅子的存在了(“▔□▔)……
前段时间没有事做的时候,组织上仿佛看穿了我很咸,突然让我去研究下灰产包,让我分析用了什么技术&做出了什么改动。
虽然入职就听说了公司应用之前有被灰产“薅羊毛”的问题,但真让我弄我也没专门弄过啊,而且这部分之前是交给风控组去做的,这么久了整不来靠我嘛?而且我也想吐槽这灰产包你们又是怎么弄来的,还有两份不同技术实现的……
如果想对apk内部内容进行修改,从而达到实现某些功能或规避某些审查的目的,就一定要对签名进行重签,这一点上只需要和正版签名比对一下便能发现。如何检测使用了这些篡改应用的用户等不在这次的任务范围内,篡改功能点内容也不展开讨论,此处仅讨论绕过审查重签的技术。
对灰产包简单的逆向后,我在第一个包很快地就发现了一个
KillApplication.java
:很显然,做篡改的兄弟还不够细,或者根本没懂相应的原理性知识,留下了如此明显的痕迹,并且在URL参数直接暴露了篡改方式:
算是让我直接回忆起之前用过的MT管理器,好像酷安就能下到,不过我已经很久没用过了,不知道MT现在是自带这种签名方式还是作为外部插件使用的。
而MT APP签名检查及绕过在Android逆向-获取APP签名 一文中有详细表述,在此不做赘述(懒)
那我们再来看下一个,啊,还不用我找,MobSF都给我翻出来了:
你是?
顺着
FuckSign.java
和2863678687@qq.com
这两个信息(痕迹也是太明显了),我找到了另一种篡改方式:直接获取下来也很容易就复现了篡改与绕过:
首先啊,风控安全真是和什么都斗争不断,除开apk包篡改,也还有模拟GPS定位、虚拟用户接码手机号等等,还好不是我直接负责:
然后,之前文章提到过外网可能是MobSF官方开的一个在线检测的平台,直接暴露了非常多的检测应用报告,无独有偶,我在做这次灰产分析的时候,在搜索引擎寻找
FuckSign.java
,发现了国内一个仿MobSF的在线检测平台,从搜索引擎记录来看,市场上很多其他应用也不堪灰产侵扰:我在发现这个检测平台的时候,它给检测项部分“需要开通VIP”解锁,该说是刻意而为导致规避了部分问题还是啥呢……总之,我在几周后重新访问的时候,他已经是崩溃状态,嘛,不好评价:
最后,要做灰产黑产,就要从原理性把痕迹去除或转化,不能留太明显的技术痕迹,虽然可以说这些最后找到的都是开源项目,是卖刀者不是作恶人,但淹死的多是会水的,这里分享一篇文章:灰产,赚点快钱?。
新公司让我对应用移动端产品也渗透一下,自然地想到移动端APK相关的自动化检测工具,于是Docker起了一个MobSF跑了下检测,算是做个铺垫。
当然还不如自己手动测来的漏洞直接,自动化扫描得出的结果不一定都具有直接性和威胁性,但MobSF还支持动态检测,实测下来确实能自动化访问activity事件,但每次调用Frida去执行注入测试的时候就会出大大小小的问题:
- 目前Mac M1/M2芯片由于ARM架构的问题,还无法完全解决Genymotion跑不了ARM包的问题(Genymotion给的MAC客户端实现用的是X86架构,完全不是官方说的因为是ARM芯片就可以直接支持ARM包了,实践出真知),M1/M2可使用的系统目前只有Android11,无法打translation包
- 很多移动应用做了SSL-Pinning等方式防抓包,需要用各种Posed去解,这些操作可能会与MobSF动态检测的模块冲突与覆盖(如MobSF动态检测会自动植入证书)
虽然对个人的工作不会带来太大的影响(又不是没有扫描器就不会渗透了),但我还是想流畅地使用一回动态检测啊,看看能达到什么层度,有这个执念在,我萌生了一个想法:
互联网上有没有别人搭建好的完整检测平台呢?
还真被我找到一个,而且像是官方搭建的站点,此处相关域名隐去,不予展开。
作为一个安全人员,自然会考虑提交检测的包会上传存储在哪及检测内容是否会暴露的问题,于是我先下意识地访问了recent scans:
这是啥?!为什么我能看到今天所有提交检测的应用,并且可以看到完整的检测报告?!而且更哈人的是,举例应用竟然是未对外发布的内部研发版本(官网版本2.0.011 < 研发版本2.0.015),且没有做加固之类的!
这不禁让我想到了两个问题:
- MobSF这个线上检测平台肯定是没做好权限划分的,或者从设计来说MobSF可能就没实现这点,因为一般都是在本地部署的检测平台;纵使在后台做了定期清理数据的策略,在短期内这些检测内容还是会留存下来
- 所有被检测的应用可以被任意的人员查看,如果有安全问题很有可能线上版本也存在类似问题,而且数据泄漏就是泄漏了,在一段时间内一个访问凭证都将是有效的,即使你知道它已经泄露,会因为你不知道多少功能调用用到了这个凭证而不敢直接替换
那么这个应用里有什么呢?
直接上图,这些码应该够了吧:
除了显而易见的
google_maps_key
外,apk内还硬编码了firebase_database_url
、google_api_key
、google_app_id
、google_storage_bucket
等敏感参数(有些是我直接获取源包找的),firebase_database_url
直接访问果然无权限,但是剩下的几个参数是怎么调用的?能获得什么信息呢?首先猜测和存储空间有关,但不对,Google Cloud并不是用这样的参数类型请求访问的;那既然存在
firebase_database_url
,会不会和Firebase有关?一番文档翻找下,我大致了解了Firebase是啥,还有一部分的API调用,并知道了相关的API Key是在什么位置被生成又用于何处的:之后要做的事情就简单了,构造一个请求,就可以获取到与Firebase服务器交互许可的凭证了:
之后的操作就不做了,扩大影响面应该很容易,所以为什么要演奏春日……啊不对,为什么要把应用程序的报告暴露在公开检测平台!
Deploy an application - Desktop User Guide
How to install Xposed/EdXposed/LSPosed + Magisk with Genymotion Desktop?