首页
社区
课程
招聘
[原创]关于Nokelock蓝牙锁破解分析
发表于: 2023-4-6 21:54 21960

[原创]关于Nokelock蓝牙锁破解分析

2023-4-6 21:54
21960

img
今年西葫芦剑的时候是一个蓝牙题都没做出来,之前复现xuanxuan师傅出的THUCTF硬件题的蓝牙部分也没完全弄懂,于是下定决心通过几个设备来研究研究
刚学pwn的时候,对宿舍楼下的小蓝车就有所“垂涎”,一直在思考如何打(太可刑了)
经过给小蓝车app投资数次1.5米巨资过后,作为名义上的股东,我大概弄清楚了小蓝车的锁应该也是蓝牙的(因为每次连它都让我开蓝牙233)
为了避免下半辈子只能在几平米的空间活动,我在某鱼上淘到了一款蓝牙锁作为小蓝车的平替
这里简单记录一下研究的过程

首先需要解决的问题是获取蓝牙锁的MAC地址,因为最后我们需要使用gatttool(后面会提到这个工具)直接通过MAC地址与蓝牙锁交互
比较好用的是nRF这个软件(苹果手机可以用lightblue),能够直接扫描查看周围的蓝牙设备
但如果直接在生活区进行抓包干扰因素非常多:
img
于是我们跑到一个没有其它设备的地方轻触指纹区域,当亮起红光的时候:
img
在nRF上就能看到设备名和MAC地址了:
img
可以看出设备名为BlueFPL,MAC地址为F0:45:DA:AA:F4:36

通过树莓派+蓝牙适配器的组合(环境搭建详见:[原创]基于树莓派的蓝牙调试环境搭建-智能设备-看雪论坛-安全社区|安全招聘|bbs.pediy.com (kanxue.com)
使用bluetoothctl的scan on功能,就能扫描出设备:
img
表示我们的蓝牙调试环境没有问题
使用gatttool尝试连接并使用primary看查所有service:
img
然后通过characteristics命令看查所有的特性:
img
其中handle是特性的句柄,char properties是特性的属性值,char value handle是特性值的句柄,uuid是特性的标识
虽然扫描出了service和characteristics,但我们还不能直观的知道这些服务是用来干什么的,而且也没法将特性和服务配对
下面我们使用bettercap这一个强大的工具中的"ble.recon"模块,进行深入的扫描和理解

githu仓库:https://github.com/bettercap/bettercap
个人认为仓库给出的安装教程非常的模糊,很多东西都没有说清楚,所以这里简单讲讲我是怎么安装的
环境:ubuntu或树莓派4b 安装:
(1)首先需要安装go环境:

(2)go“换源”:

(3)安装依赖:

(4)安装软件包:

然后输入如下命令就能够使用低功耗蓝牙功能了:

img
具体的用法可以参考官方手册:https://www.bettercap.org/modules/ble/
对于我们刚才提到的需要,使用ble.enum就好啦:
img
可以发现,通过ble.enum,能够形象地看出service所属的characteristics以及它们的属性
接下来我们就可以通过蓝牙嗅探,看看在开锁的过程中涉及的服务和特征

通过ubertooth one,我们嗅探到了如下的蓝牙数据:
img
可以看出大致分为"Write Request"和"Handle Value Notification"两类,我们各点开一个看看
"Write Request":
img
"Handle Value Notification":
img
可以发现它们的handle分别是0x3和0x6,分别对应的是前面bettercap里获取的UUID为36f5和36f6的特征,十分合理
于是以后的抓包我们可以给出如下过滤(上面那张图片这么规整已经是过滤过后了的):

多次尝试抓包,发现value的值差别很大,猜测有所加密 那么下一步就要从安卓逆向的角度分析app里的加密模式和密钥了

实际上可能会出现很难抓到包的情况,所以这里提供第二种思路供大家尝试:
嗅探是中间信道,很可能会受到干扰,于是我们尝试从手机的蓝牙日志里直接获取和锁的通信
首先需要打开开发人员选项,一般的手机都是在"关于本机"的位置点击多次版本号就可打开
进入开发人员选项后,开启"蓝牙HCI信息收集日志"
img
然后我们需要使用"adb"这个调试工具,连上手机,然后dump下BUG日志
img
解压这个zip文件,在解压目录下会生成同名的一个txt文件:
img
把它拖到Ubuntu里面(不知道为啥,在我的windows上会有问题),然后下载一个叫btsnooz.py的脚本并把它放在和这个文本文件同目录下,执行如下命令:

(ps:为什么命令会和官方的教程有点不太一样,因为产生了如下的报错和解决办法)
img
然后就得到了能够用wireshark查看的蓝牙日志"hci.log"了:
img
可以看到效果非常好,但是在笔者的手机上的数据会有一个问题,就是value显示不全:
img
不知道是不是脚本对数据包有所切割,反正就感觉很离谱
而且这种方法对我平时用的手机也不生效,甚至不能产生hci.log文件

将apk拖进JEB中,然后在Bytecode层级的com.nokelock.blelibrary.b.b里面能找到加密和解密的地方:
img
差别就是Ciper.init()的第一个参数,询问一下chatgpt:
img
img
观察类中的这两个方法,都涉及两个byte数组参数arg2,arg3:
img
arg2对应的是密文/明文,arg3对应的是密钥
具体的用Ciper类加密可以参考这一篇文章:Java使用Cipher类实现加密,包括DES,DES3,AES和RSA加密 - 蔡昭凯 - 博客园 (cnblogs.com)
经过上面的分析,我们知道了加密算法是AES而且是ECB模式无padding,但是还不知道密钥和密钥长度
接下来我们尝试在apk里进行插桩,目的是打印密文/明文,密钥来分析实际上开锁的时候在apk中的数据

实际上插桩这步是劳烦oacia爷帮我做的,教程同步到了他的文章:[原创]对某apk的一次插桩记录-Android安全-看雪论坛-安全社区|安全招聘|bbs.pediy.com (kanxue.com)
写的非常好,这里就不再班门弄斧了
可能唯一没太讲清楚会遇到问题的是,使用他给的smali进行插桩会和github上的项目会有一点点差别:
img

在最后插桩的时候,这里从object变成B类(字节数组)了,如果还是使用object类会有问题
因为我们重写的java源码是对字节数组进行的操作,可以参考原来的apk里类似对字节数组的操作的smali代码:
img
img
然后还有一个神奇的问题,就是在笔者的电脑上使用回编译过后的apk,会缺少签名、主SDK等等东西:
img
这种APK在我的手机上安装不了,但雷电模拟器能装(但先要使用这个工具对回编译的APK进行签名)
于是我把雷电模拟器里的apk导出来,它的这些东西又变正常了:
img
非常神奇,然后顺利成章的我的手机也能装了
原来手机也这么矫情2333

通过adb工具,我们能够连接安卓设备并且执行一些命令
这里我们通过adb logcat命令来搜索SewellDinG查看插桩打印的信息:

在插桩打印的信息中有两个点值得我们注意:
(1)"241F632E5907042061014C1A3A45193B"这个字符串一直在重复,且一直处于一组数据的中部
(2)出现了以"050D"、"0502"、"0501"开头的后面不大一样的疑似有规律的数据
根据我们的插桩,一直处于中部的数据只可能是密钥,那么"241F632E5907042061014C1A3A45193B"就是密钥的某种形式。通过密钥创建的方法"SecretKeySpec"的参数类型可以看出,这是密钥的16进制字符串表示:
img
对chatgpt输入如下指令即可自动生成解密脚本:

解密脚本:

运行结果:
img
对我们之前的wireshark里的数据都进行解密,然后把结果用XLS表示出来:
img
在app里的com.nokelock.blelibrary.mode.order可以发现和"Write Request"解密出来的头4个字符有关的enum:
img
添加到表格中:
img
发现有一个特别令我们欣喜的东西——"OPEN_LOCK"
是否意味着我们把这个value的值通过蓝牙工具发到锁中锁就开了?
答案是否定的,这个value以及它解出来的text是会变的,这一点比照前面adb打印插桩的同样的"0501"开头的数据就知道。所以我们还需要知道怎么获得这个"变"的东西
值得注意的是,同样在这个地方有个"GET_TOKEN"字样:
img
猜测变化的值和这里有关
至于有没有和"Handle Value Notification"有关的类似的enum,在com.nokelock.blelibrary.mode.a里找到了这个:
img
不难看出,这里的代码应该是app接收到蓝牙锁返回的"Handle Value Notification"的value,将它解密过后根据前4个字符去执行对应的功能。而且根据"0202"这个分支里的具体内容已经能大致猜测这里响应的内容是什么了——电池电量,因为有个(v1<=100)的判断,然后对v3这个bool变量赋值判断是否合法。
再结合之前的"0201"为"GET_BATTERY",一切的说法都看上去合理了起来,我们甚至已经能根据前面的数据,推测响应的时候电池电量为54
但这个说法还有待验证,以及我们还不知道"v0.a()"执行了什么操作,于是需要更深入的逆向

首先为了验证前面"发送过后获取响应"的说法,逆向到了com.nokelock.blelibrary.BLEService:
img
看到了熟悉的两个UUID,以及它们对应的Characteristic变量
在下面能找到分别对这两个Characteristic的操作:
img
从这里就已经能看出在蓝牙通信的时候,app往UUID36f5写入请求信息,然后蓝牙锁通过UUID36f6进行响应

v0一开始是在这里定义的:
img
这个com.nokelock.blelibrary.a.a是一个抽象接口:
img
以v0.a()为例,如果我们想看它具体是怎么实现的,在JEB里点击"a"就能直接查看了:
img
进入红框的部分就能看到具体的实现了:
img
可以看到这里有个电池电量低于20就会打印"电量不足"的字样,和使用app时候的情况一致
猜测对于"GET_TOKEN"的响应也在这里面,但是不好直接找出TOKEN的值
于是我们去找"OPEN_LOCK"的地方,因为那里大概率会有响应的"TOKEN"

在jadx里查找"OPEN_LOCK"这个字符串,定位到了这个地方:
img
红框部分通过对"SET_B_ARRAY"的逆向,可以得到是:
(0x6,0x30,0x30,0x30,0x30,0x30,0x30)
对应了OPEN_LOCK解密的部分数据:06303030303030
其余数据能够在父类TX_Order里看出来:
img
蓝色部分是0501,绿色部分是刚才的那块数据,红色部分应该是Token,剩下的黄色部分使用随机数进行填充

分析com.nokelock.blelibrary.b.d.a().b():
img
最后返回的其实是这里的字符数组:
img
"c2 == 0"对应的是它上面的一个地方:
img
结合之前的分析,就能知道GET_TOKEN的响应头应该是"0602"了 那么接下来唯一需要解决的是发送的GET_TOKEN请求长什么样子了

同样通过查找字符串的手段,我们可以定位到这里:
img
和"OPEN_LOCK"不一样的地方就是它重写了a()这个方法,可以很容易分析出响应头为"06010101"
剩下的数据都是为了方便最后的加密进行的随机数的填充
那么发送未加密前是"06010101000000000000000000000000"的数据就能成功获取TOKEN的值

通过上面有点长的分析,我们弄清楚了开锁的重要流程(关于获取电量这些无关紧要的在此不考虑):
(1)APP发送GET_TOKEN请求,锁返回TOKEN
(2)APP根据锁返回的TOKEN,执行开锁命令
接下来我们通过Bluepy这个python的蓝牙模块尝试发包开锁

github网址:IanHarvey/bluepy: Python interface to Bluetooth LE on Linux (github.com)
安装依赖(使用python3环境):

安装模块:

如果上面两步失败,可以尝试从源码进行安装:

官方手册:bluepy - a Bluetooth LE interface for Python — bluepy 0.9.11 documentation (ianharvey.github.io)
Bluepy这个模块采用了面向对象编程的思想,在具体操作的时候对设备、服务等等都抽象成了对象以便于操作

通过Scanner生成一个对象进行扫描:

通过Peripheral函数建立连接

经过分析,我们知道36f6这个characteristic的属性是notify
对于notify属性的characteristic,没办法直接读和直接写,需要先向UUID为"0x2902"的descriptor写入"1"进行订阅才能获取所有notify属性的characteristic的响应
另外,我们写一个类来获取响应的handle和value:

通过等待响应即可获取token:

对36f5写入发包数据即可开锁:

img

物联网安全拔“牙”实战——低功耗蓝牙(BLE)初探 https://www.ctfiot.com/10661.html
Ubertooth One 使用系列 (一) — 破解蓝牙锁 - 知乎 (zhihu.com)
低功耗蓝牙ATT/GATT/Profile/Service/Characteristic规格解读 - iini - 博客园 (cnblogs.com)
Java使用Cipher类实现加密,包括DES,DES3,AES和RSA加密 - 蔡昭凯 - 博客园 (cnblogs.com)
[python] bluepy 一款python封装的BLE利器 - beautifulzzzz - 博客园 (cnblogs.com)
Python3环境,树莓派使用bluepy与BLE设备通信 - 天命小猪 - 博客园 (cnblogs.com)

sudo apt install golang-go
sudo apt install golang-go
echo "export GOPROXY=https://goproxy.io,direct" >> ~/.profile && source ~/.profile
echo "export GOPROXY=https://goproxy.io,direct" >> ~/.profile && source ~/.profile
sudo apt install build-essential libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev libssl-dev libnl-3-dev libnl-genl-3-dev pkg-config
sudo apt install build-essential libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev libssl-dev libnl-3-dev libnl-genl-3-dev pkg-config
git clone https://github.com/bettercap/bettercap.git
cd bettercap
make build
sudo make install
git clone https://github.com/bettercap/bettercap.git
cd bettercap
make build
sudo make install
sudo bettercap
ble.recon on
sudo bettercap
ble.recon on
(btatt.opcode == "Handle Value Notification" && btatt.handle == 0x6 ) || (btatt.opcode == "Write Request" && btatt.handle == 0x3)
(btatt.opcode == "Handle Value Notification" && btatt.handle == 0x6 ) || (btatt.opcode == "Write Request" && btatt.handle == 0x3)
LC_CTYPE=C sed -n "/BEGIN:BTSNOOP_LOG_SUMMARY/,/END:BTSNOOP_LOG_SUMMARY/p " bugreport-ASK-AL00x-HONORASK-AL00x-2023-04-03-08-31-01.txt | egrep -av "BTSNOOP_LOG_SUMMARY" | python btsnooz.py > hci.log
LC_CTYPE=C sed -n "/BEGIN:BTSNOOP_LOG_SUMMARY/,/END:BTSNOOP_LOG_SUMMARY/p " bugreport-ASK-AL00x-HONORASK-AL00x-2023-04-03-08-31-01.txt | egrep -av "BTSNOOP_LOG_SUMMARY" | python btsnooz.py > hci.log
invoke-static {p0}, LSewellDinGLog;->Log([B)V
invoke-static {p0}, LSewellDinGLog;->Log([B)V
F:\platform-tools>adb logcat -s SewellDinG
--------- beginning of main
03-27 17:18:08.895 31117 31117 D SewellDinG: 05010630303030303082E3C89616017D
03-27 17:18:08.895 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:08.895 31117 31117 D SewellDinG: 6629B62C88A7E50525E92C328AF258E6
03-27 17:18:10.114 31117 31117 D SewellDinG: 732F5CB22C06B0C2D0D17AD31D165805
03-27 17:18:10.114 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:10.114 31117 31117 D SewellDinG: 05020100E3C896010202000000000000
03-27 17:18:11.770 31117 31117 D SewellDinG: 530B1FCA1467A408A321E71F3D152127
03-27 17:18:11.771 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:11.772 31117 31117 D SewellDinG: 050D0100E3C896010202000000000000
03-27 17:18:37.864 31117 31117 D SewellDinG: 05010630303030303082E3C89601635C
03-27 17:18:37.864 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:37.864 31117 31117 D SewellDinG: 3FFA9BE0BA05D2ECC8CF74D2CDB7867C
03-27 17:18:39.263 31117 31117 D SewellDinG: 732F5CB22C06B0C2D0D17AD31D165805
03-27 17:18:39.263 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:39.263 31117 31117 D SewellDinG: 05020100E3C896010202000000000000
03-27 17:18:40.923 31117 31117 D SewellDinG: 530B1FCA1467A408A321E71F3D152127
03-27 17:18:40.923 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:40.924 31117 31117 D SewellDinG: 050D0100E3C896010202000000000000
F:\platform-tools>adb logcat -s SewellDinG
--------- beginning of main
03-27 17:18:08.895 31117 31117 D SewellDinG: 05010630303030303082E3C89616017D
03-27 17:18:08.895 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:08.895 31117 31117 D SewellDinG: 6629B62C88A7E50525E92C328AF258E6
03-27 17:18:10.114 31117 31117 D SewellDinG: 732F5CB22C06B0C2D0D17AD31D165805
03-27 17:18:10.114 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:10.114 31117 31117 D SewellDinG: 05020100E3C896010202000000000000
03-27 17:18:11.770 31117 31117 D SewellDinG: 530B1FCA1467A408A321E71F3D152127
03-27 17:18:11.771 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:11.772 31117 31117 D SewellDinG: 050D0100E3C896010202000000000000
03-27 17:18:37.864 31117 31117 D SewellDinG: 05010630303030303082E3C89601635C
03-27 17:18:37.864 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:37.864 31117 31117 D SewellDinG: 3FFA9BE0BA05D2ECC8CF74D2CDB7867C
03-27 17:18:39.263 31117 31117 D SewellDinG: 732F5CB22C06B0C2D0D17AD31D165805
03-27 17:18:39.263 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:39.263 31117 31117 D SewellDinG: 05020100E3C896010202000000000000
03-27 17:18:40.923 31117 31117 D SewellDinG: 530B1FCA1467A408A321E71F3D152127
03-27 17:18:40.923 31117 31117 D SewellDinG: 241F632E5907042061014C1A3A45193B
03-27 17:18:40.924 31117 31117 D SewellDinG: 050D0100E3C896010202000000000000
请用python实现一个密钥的16进制字符表示形式是241F632E5907042061014C1A3A45193B的ECB模式无padding的AES-128解密程序,并以16进制字符串的形式输出打印明文
请用python实现一个密钥的16进制字符表示形式是241F632E5907042061014C1A3A45193B的ECB模式无padding的AES-128解密程序,并以16进制字符串的形式输出打印明文
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.primitives.ciphers.modes import ECB
from cryptography.hazmat.backends import default_backend
import binascii
 
# 转换输入的16进制字符串为字节串
key_hex = "241F632E5907042061014C1A3A45193B"
 
key = binascii.unhexlify(key_hex)
#key = b"[B@7ef20235"
# 创建 AES 密钥
if len(key) == 16# 128 bit
    algorithm = algorithms.AES(key)
else:
    raise ValueError("Invalid key size")
# 创建解密器
backend = default_backend()
cipher = Cipher(algorithm, modes.ECB(), backend=backend)
decryptor = cipher.decryptor()
# 解密密文
#iv = "a20e10ec8ebfd6069c1f84a9cff39e33"
iv = "51653e25e098f5e74e0f152062ee6d5d"
encrypted_data = binascii.unhexlify(iv)
decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()
# 打印解密结果
print(binascii.hexlify(decrypted_data))
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.primitives.ciphers.modes import ECB
from cryptography.hazmat.backends import default_backend
import binascii
 
# 转换输入的16进制字符串为字节串
key_hex = "241F632E5907042061014C1A3A45193B"
 
key = binascii.unhexlify(key_hex)
#key = b"[B@7ef20235"
# 创建 AES 密钥
if len(key) == 16# 128 bit
    algorithm = algorithms.AES(key)
else:
    raise ValueError("Invalid key size")
# 创建解密器
backend = default_backend()
cipher = Cipher(algorithm, modes.ECB(), backend=backend)
decryptor = cipher.decryptor()
# 解密密文
#iv = "a20e10ec8ebfd6069c1f84a9cff39e33"
iv = "51653e25e098f5e74e0f152062ee6d5d"
encrypted_data = binascii.unhexlify(iv)
decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()
# 打印解密结果
print(binascii.hexlify(decrypted_data))
sudo apt-get install python3-pip libglib2.0-dev
sudo apt-get install python3-pip libglib2.0-dev
sudo pip3 install bluepy
sudo pip3 install bluepy
sudo apt-get install git build-essential libglib2.0-dev
git clone https://github.com/IanHarvey/bluepy.git
cd bluepy
python setup.py build
sudo python setup.py install
sudo apt-get install git build-essential libglib2.0-dev
git clone https://github.com/IanHarvey/bluepy.git
cd bluepy
python setup.py build
sudo python setup.py install
scanner = Scanner()
devices = scanner.scan(timeout=3)
print("%-30s %-10s" % ("Name", "Address"))
for dev in devices:
        print("%-30s %-20s" % (dev.getValueText(9), dev.addr))
scanner = Scanner()
devices = scanner.scan(timeout=3)
print("%-30s %-10s" % ("Name", "Address"))
for dev in devices:
        print("%-30s %-20s" % (dev.getValueText(9), dev.addr))
addr = ""
conn = Peripheral(addr)   
addr = ""
conn = Peripheral(addr)   
services = conn.getServices()
for svc in services:
    print(svc.uuid)   
services = conn.getServices()
for svc in services:
    print(svc.uuid)   
# 1. 获取所有 Characteristic
characteristics = conn.getCharacteristics()
for charac in characteristics:  
    print(charac.uuid)
     
# 2. 获取特定 Service 下的 Characteristic
characteristics = svc.getCharacteristics()
# 1. 获取所有 Characteristic
characteristics = conn.getCharacteristics()
for charac in characteristics:  
    print(charac.uuid)
     
# 2. 获取特定 Service 下的 Characteristic
characteristics = svc.getCharacteristics()
charac.read()            
charac.write()         
charac.read()            
charac.write()         
class NotifyDelegate(DefaultDelegate):
    def __init__(self,params):
        DefaultDelegate.__init__(self)
         
    def handleNotification(self,cHandle,data):
        global TOKEN
        print("Notification from Handle: 0x" + format(cHandle,"02X"))
        TOKEN = decrypt(binascii.hexlify(data))
        print(TOKEN)
class NotifyDelegate(DefaultDelegate):
    def __init__(self,params):
        DefaultDelegate.__init__(self)
         
    def handleNotification(self,cHandle,data):
        global TOKEN
        print("Notification from Handle: 0x" + format(cHandle,"02X"))
        TOKEN = decrypt(binascii.hexlify(data))
        print(TOKEN)

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2023-8-30 17:49 被Nameless_a编辑 ,原因:
收藏
免费 15
支持
分享
最新回复 (7)
雪    币: 4131
活跃值: (5837)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
2
2023-4-7 10:40
0
雪    币: 2337
活跃值: (6708)
能力值: ( LV7,RANK:102 )
在线值:
发帖
回帖
粉丝
3
什么年代了,还插桩,frida走一个
2023-4-7 11:22
0
雪    币: 7005
活跃值: (11209)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
4
fjqisba 什么年代了,还插桩,frida走一个
hhhh还是安卓新手,正准备学呢
2023-4-7 11:29
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
大佬牛逼!
2023-4-7 15:34
0
雪    币: 3303
活跃值: (30941)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
感谢分享
2023-4-8 13:55
1
雪    币: 1671
活跃值: (215847)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
7
tql
2023-4-8 17:18
0
雪    币: 8447
活跃值: (5041)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
8
2023-4-9 18:24
0
游客
登录 | 注册 方可回帖
返回
//