├── .idea ├── .gitignore ├── misc.xml ├── vcs.xml ├── inspectionProfiles │ ├── profiles_settings.xml │ └── Project_Default.xml ├── modules.xml └── 安卓逆向案例.iml ├── Frida常用以及框架脚本 ├── 查看当前运行.py ├── frida-rpc框架.py └── frida-hook框架.py ├── adb使用笔记.md ├── 得物 ├── 测试主页推荐.py ├── hook.js └── newSign.py ├── 豆瓣 ├── hook_sig.py └── 发送请求.py ├── README.md └── frida使用笔记.md /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # 基于编辑器的 HTTP 客户端请求 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Frida常用以及框架脚本/查看当前运行.py: -------------------------------------------------------------------------------- 1 | import frida 2 | 3 | rdev = frida.get_remote_device() 4 | print(rdev) 5 | 6 | processes = rdev.enumerate_processes() 7 | for process in processes: 8 | print(process) 9 | 10 | front_app = rdev.get_frontmost_application() 11 | print(front_app) -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/安卓逆向案例.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Frida常用以及框架脚本/frida-rpc框架.py: -------------------------------------------------------------------------------- 1 | import frida 2 | 3 | rdev = frida.get_remote_device() 4 | session = rdev.attach("名称") 5 | 6 | 7 | # 整体思路和hook差不多,但是需要在rpc里面进行导出 8 | src = """ 9 | rpc.exports = { 10 | CustomizationFunctionName: function(参数列表) { 11 | var res; 12 | Java.perform(function(){ 13 | var CustomizationObjectName = Java.use("包名.类名"); 14 | res = CustomizationObjectName.函数名(参数列表); 15 | }); 16 | return res; 17 | } 18 | } 19 | 20 | """ 21 | 22 | script = session.create_script(src) 23 | script.load() 24 | 25 | wanna_args = script.exports_sync.CustomizationFunctionName("参数列表") 26 | print(wanna_args) 27 | 28 | -------------------------------------------------------------------------------- /adb使用笔记.md: -------------------------------------------------------------------------------- 1 | # 此文件记录adb的使用 2 | ## 安装 3 | 此过程略,可以在网上轻易获取到 4 | ## 使用 5 | 首先我们介绍一下adb命令的基本构成 6 | ```bash 7 | adb -s 设备 命令 8 | ``` 9 | 十分简洁,我们只需要知道我们需要执行什么命令即可。 10 | 11 | 同时,如果你的设备只有一个,那么命令可以简化为 12 | ```bash 13 | adb 命令 14 | ``` 15 | 16 | ### 常用命令 17 | 18 | 我们首先需要知道启动以及结束和连接设备 19 | 20 | ``` bash 21 | adb start-server # 启动服务 22 | adb kill-server # 中止服务 23 | adb -s 设备 connect ip:host # 连接设备 24 | ``` 25 | 26 | 我们使用下述命令进行查看设备 27 | 28 | ```bash 29 | adb devices 30 | ``` 31 | 32 | 这个命令可以把连接到的设备展示出来 33 | 34 | 另外例如推送文件,下载apk相关我们可以直接输入adb获取它的使用文档 35 | 36 | 下面介绍查看手机或虚拟机的cup型号的命令,会在我们使用frida时有用 37 | 38 | ```bash 39 | adb shell getprop ro.product.cpu.abi # 查看型号 40 | ``` 41 | 42 | 同时,我们可以通过下述命令进入手机的Linux终端(记得开启root哦) 43 | 44 | ```bash 45 | adb shell 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /Frida常用以及框架脚本/frida-hook框架.py: -------------------------------------------------------------------------------- 1 | import frida 2 | import sys 3 | 4 | rdev = frida.get_remote_device() 5 | # app名称或者app包名称 6 | session = rdev.attach("com.shizhuang.duapp") 7 | 8 | # 目标:指定替换是那个包中的方法名 9 | # - 包名称:com.shizhuang.duapp.common.utils 10 | # - 类名称:RequestUtils 11 | # - 方法名:c m30623c-jadx工具给你创造的。 12 | # - 类名称.方法名.implementation = function(方法的参数列表){var res = this.方法(参数);return res} 13 | # - 如果是由重载的函数,那么需要携带参数类型,详情可以看frida的报错信息 14 | # - 这里给一个具体的例子RequestUtils.a.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation 15 | scr = """ 16 | Java.perform(function () { 17 | // 导入类 18 | var RequestUtils = Java.use("包名.类名"); 19 | 20 | // 找到类中的方法进行hook 21 | RequestUtils.c.implementation = function(map,j){ 22 | console.log("666"); 23 | var res = this.c(map,j); 24 | console.log("999"); 25 | return res; 26 | } 27 | 28 | }); 29 | """ 30 | script = session.create_script(scr) 31 | 32 | 33 | def on_message(message, data): 34 | print(message, data) 35 | 36 | 37 | script.on("message", on_message) 38 | 39 | script.load() 40 | sys.stdin.read() 41 | -------------------------------------------------------------------------------- /得物/测试主页推荐.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from newSign import get_newSign 3 | 4 | 5 | headers = { 6 | "User-Agent": "duapp/5.28.0(android;9)", 7 | "Connection": "Keep-Alive", 8 | "Accept-Encoding": "gzip", 9 | "cookieToken": "", 10 | "webua": "Mozilla/5.0 (Linux; Android 9; SM-G977N Build/LMY48Z; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile Safari/537.36/duapp/5.28.0(android;9)", 11 | "duplatform": "android", 12 | "duv": "5.28.0", 13 | "duloginToken": "", 14 | "shumeiid": "", 15 | "X-Auth-Token": "", 16 | } 17 | cookies = { 18 | "HWWAFSESTIME": "" 19 | } 20 | url = "https://app.dewu.com/sns-rec/v1/recommend/all/feed" 21 | params = { 22 | "lastId": "", 23 | "limit": "20", 24 | "deliveryProjectId": "0", 25 | "negativeFeedbackUids": "", 26 | "negativeFeedbackCids": "", 27 | "pushChannel": "", 28 | "pushContentId": "", 29 | "lastExposureCids": "", 30 | "abV518Autoplay": "0", 31 | "ab528feedsCardNewCommodity": "1", 32 | "deviceNetwork": "WIFI", 33 | "abVIcon": "2", 34 | "abCoverReverse": "0", 35 | } 36 | sign_time = get_newSign(params) 37 | params['newSign'] = sign_time[0] 38 | headers['timestamp'] = sign_time[1] 39 | response = requests.get(url, headers=headers, cookies=cookies, params=params) 40 | 41 | print(response.json()) 42 | 43 | -------------------------------------------------------------------------------- /豆瓣/hook_sig.py: -------------------------------------------------------------------------------- 1 | import frida 2 | import sys 3 | 4 | rdev = frida.get_remote_device() 5 | session = rdev.attach("豆瓣") 6 | 7 | 8 | scr = """ 9 | Java.perform(function () { 10 | // 导入类 11 | var RequestUtils = Java.use("com.douban.frodo.network.ApiSignatureHelper"); 12 | var encrypted = Java.use("com.douban.frodo.utils.crypto.HMACHash1"); 13 | var apiKey = Java.use("com.douban.ad.utils.ApiUtils") 14 | 15 | // 找到类中的方法进行hook 16 | RequestUtils.a.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = 17 | function(str, str1, str2){ 18 | console.log(str, str1, str2); 19 | var res = this.a(str, str1, str2); 20 | console.log(res); 21 | return res; 22 | } 23 | encrypted.a.implementation = function(str, str1){ 24 | console.log(str, str1) 25 | var res = this.a(str, str1) 26 | console.log(res); 27 | return res; 28 | } 29 | apiKey.getApiKey.implementation = function(context){ 30 | console.log(context) 31 | var res = this.getApiKey(context) 32 | console.log(res); 33 | return res; 34 | } 35 | 36 | }); 37 | """ 38 | script = session.create_script(scr) 39 | 40 | 41 | def on_message(message, data): 42 | print(message, data) 43 | 44 | 45 | script.on("message", on_message) 46 | 47 | script.load() 48 | sys.stdin.read() 49 | -------------------------------------------------------------------------------- /得物/hook.js: -------------------------------------------------------------------------------- 1 | // hook 添加params试图定位添加newsign的地方 2 | Java.perform(function () { 3 | // 导入类 4 | var RequestUtils = Java.use("com.shizhuang.duapp.common.helper.net.ParamsBuilder"); 5 | 6 | // 找到类中的方法进行hook 7 | RequestUtils.addParams.overload('java.lang.String', 'java.lang.Object').implementation = function(str, str1){ 8 | console.log(str, str1); 9 | showStacks() 10 | var res = this.addParams(str, str1); 11 | return res; 12 | } 13 | }) 14 | // 定位加密点 15 | Java.perform(function () { 16 | // 导入类 17 | var RequestUtils = Java.use("com.duapp.aesjni.AESEncrypt"); 18 | 19 | // 找到类中的方法进行hook 20 | RequestUtils.encode.implementation = function (obj, str) { 21 | console.log('=================================================') 22 | console.log('obj', obj); 23 | console.log('str', str); 24 | console.log('=================================================') 25 | var res = this.encode(obj, str); 26 | console.log(res) 27 | console.log('=================================================') 28 | showStacks() 29 | console.log('=================================================') 30 | return res; 31 | } 32 | }) 33 | // 显示调用栈 34 | function showStacks() { 35 | Java.perform(function () { 36 | console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new())); 37 | }); 38 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 安卓逆向合集 2 | > 此项目为安卓逆向实战合集以及部分笔记 3 | > 4 | > 仅作学习分析以及学习记录,__禁止商用__,如遇__侵权__请联系删除 5 | > 6 | > 本项目将持续更新 7 | ### 我的个人博客 8 | [回锅炒辣椒的个人博客](https://www.xsblog.site/) 9 | ## 环境篇 10 | 众所周知,安卓逆向首先需要一个安卓环境,有两种方案,第一是模拟器,第二是真机 11 | 12 | ### 模拟器 13 | 市面上有很多模拟器可以用,up选择的是夜神模拟器,在官网下载好模拟器后,我们需要改一些配置 14 | 15 | 第一,抓包配置 --> 配置WIFI的IP以及按照你的抓包工具进行配置。 16 | 17 | 第二,开root,很简单 18 | 19 | > 但是会出现抓包抓不到的情况,这种是由于在java层配置了不走系统代理,所以我们需要别的工具: 20 | > 21 | > 1. drony(不推荐),有时会导致无法上网,不稳定 22 | > 2. SocksDroid(推荐),开启工具时记得删除系统代理 23 | 24 | > 注: 夜神模拟器默认的端口是62025, 所以我们需要连接这个端口(不一定,我的电脑是这个端口) 25 | 26 | ### 反编译工具 27 | 28 | 1. jadx(java层) 29 | 2. jeb(java层) 30 | 3. ida(so层,c语言层) 31 | 32 | ### 查壳脱壳工具 33 | 34 | 按照自己的喜好即可,网上有很多 35 | 36 | ### 获取apk途径 37 | 38 | 百度搜索即可 39 | 40 | ## 实战篇 41 | 42 | > 更多的笔记见其他文件。 43 | 44 | | 项目 | 难度 | 45 | | ---- | ---- | 46 | | 豆瓣 | 简单 | 47 | | 某物 | 中等 | 48 | 49 | ### 豆瓣 50 | 51 | 想必大家爬虫梦的开始就是豆瓣250吧,那么我们安卓逆向的开始也从豆瓣开始吧~ 52 | 53 | 分析过程: 54 | 55 | 1. 首先抓包分析,确认接口,确认加密参数名: _sig 56 | 2. 全局搜索,确认加密位置 57 | 3. hook加密函数,分析加密流程 58 | 4. 用python改写,实现发包 59 | 60 | 总结算法: 豆瓣的_sig是由请求方式以及url的path和时间戳以&相连,进行一次hmacsha1,然后将结果转化为base64的格式 61 | 62 | ### 某物 63 | 64 | 第二个案例首先更新第一部分,newSign的获取。得物前几个版本比较简单,但是新版本有些内容不太一样 65 | 66 | 第一,newSign放到so层添加,并且是VMP的so文件,在这里我们不分析这个so文件,在全局搜索其他部分,找到加密位置 67 | 68 | 分析过程: 69 | 1. 首先抓包分析,需要分析参数: newSign 70 | 2. 全局搜索其他关键字 71 | 3. hook函数,然后去so层分析 72 | 4. 用python改写 73 | 74 | 总结: 这个算法是将params添加四个额外的内容,排序,然后用aes加密之后在加密md5得到newSign 75 | 76 | 之后更新搜索接口的加密以及解密... 77 | -------------------------------------------------------------------------------- /得物/newSign.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import time 3 | 4 | from Crypto.Cipher import AES 5 | from Crypto.Util.Padding import pad 6 | import hashlib 7 | 8 | 9 | def get_newSign(search_dict: dict) -> tuple[str, str]: 10 | new_dict = { 11 | 'uuid': '', 12 | 'timestamp': str(int(time.time() * 1000)), 13 | 'loginToken': '', 14 | 'platform': 'android' 15 | } 16 | new_dict.update(search_dict) 17 | str_to_encode = ''.join( 18 | [f'{k}{v}' for k, v in sorted(new_dict.items(), key=lambda item: item[0])] 19 | ) 20 | newSign = encrypt(str_to_encode) 21 | md5_hash = hashlib.md5() 22 | md5_hash.update(newSign.encode()) 23 | return md5_hash.hexdigest(), new_dict['timestamp'] 24 | 25 | 26 | def encrypt(plaintext): 27 | cipher = AES.new("d245a0ba8d678a61".encode('utf-8'), AES.MODE_ECB) 28 | padded_plaintext = pad(plaintext.encode('utf-8'), AES.block_size) 29 | ciphertext = cipher.encrypt(padded_plaintext) 30 | ciphertext = str(base64.encodebytes(ciphertext), 'utf-8').replace('\n', '') 31 | return ciphertext 32 | 33 | 34 | if __name__ == '__main__': 35 | params = { 36 | "lastId": "", 37 | "limit": "20", 38 | "deliveryProjectId": "0", 39 | "negativeFeedbackUids": "", 40 | "negativeFeedbackCids": "", 41 | "pushChannel": "", 42 | "pushContentId": "", 43 | "lastExposureCids": "", 44 | "abV518Autoplay": "0", 45 | "ab528feedsCardNewCommodity": "1", 46 | "deviceNetwork": "WIFI", 47 | "abVIcon": "2", 48 | "abCoverReverse": "0", 49 | } 50 | print(get_newSign(params)) 51 | 52 | 53 | -------------------------------------------------------------------------------- /豆瓣/发送请求.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import hashlib 3 | import hmac 4 | import time 5 | from urllib.parse import urlparse, quote 6 | 7 | import requests 8 | 9 | 10 | def sha1_base64(url, method): 11 | path = urlparse(url).path 12 | encoded_path = quote(path, safe='') 13 | timestamp = str(int(time.time())) 14 | key = b'bf7dddc7c9cfe6f7' 15 | message = '&'.join([method, encoded_path, timestamp]) 16 | hmac_sha1 = hmac.new(key, message.encode('utf-8'), hashlib.sha1) 17 | hashed_data = hmac_sha1.digest() 18 | return base64.b64encode(hashed_data).decode('utf-8'), timestamp 19 | 20 | 21 | headers = { 22 | "User-Agent": "Rexxar-Core/0.1.3 api-client/1 com.douban.frodo/7.18.0(230) Android/28 product/beyond1qlteue vendor/samsung model/SM-G977N brand/samsung rom/android network/wifi udid/81c09b13e49151d13ed4d8d3817b99c45cf0d399 platform/mobile nd/1 com.douban.frodo/7.18.0(230) Rexxar/1.2.151 platform/mobile 1.2.151", 23 | "Connection": "Keep-Alive", 24 | "Accept-Encoding": "gzip" 25 | } 26 | 27 | url = "https://frodo.douban.com/api/v2/movie/hot_gaia" 28 | sig_ts = sha1_base64(url, 'GET') 29 | params = { 30 | "area": "全部", 31 | "sort": "time", 32 | "playable": "0", 33 | "loc_id": "0", 34 | "start": "0", 35 | "count": "20", 36 | "udid": "81c09b13e49151d13ed4d8d3817b99c45cf0d399", # 和请求头的一致 37 | "rom": "android", 38 | "apikey": "", # 需填写你的key,暂时没分析出生成逻辑 39 | "s": "rexxar_new", 40 | "channel": "Yingyongbao_Market", 41 | "timezone": "Asia/Shanghai", # 时区 42 | "device_id": "", # 设备id 43 | "os_rom": "android", 44 | "apple": "", # 暂未分析,多次固定不变 45 | "sugar": "46007", 46 | "_sig": sig_ts[0], 47 | "_ts": sig_ts[1] 48 | } 49 | response = requests.get(url, headers=headers, params=params) 50 | 51 | print(response.text) 52 | print(response) 53 | 54 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 98 | -------------------------------------------------------------------------------- /frida使用笔记.md: -------------------------------------------------------------------------------- 1 | # 此文件记录frida的使用 2 | 3 | ## 电脑安装frida 4 | ```bash 5 | pip install frida 6 | pip install frida-tools 7 | ``` 8 | 十分简单 9 | ## 手机安装frida 10 | 首先我们需要确定手机的cpu类型 11 | 12 | 模拟器通常是: x86_64 13 | 14 | 真机通常是: arm 15 | 16 | 我们根据不同的型号去frida的github下载对应的frida-sever 17 | 18 | 下面附录frida的github链接: https://github.com/frida/frida 19 | 20 | 我们下载好之后需要解压然后推送到手机中 21 | ```bash 22 | adb -s 设备 push xx/xxx/xxx/frida-server /sdcard # 首先推送到一个用户目录然后在安卓的Linux推送到系统中 23 | adb shell # 进入手机 24 | su - # 获得root权限 25 | mv /sdcard/frida-server /data/local/tmp # 移动到系统文件 26 | cd /data/local/tmp # 进入目录 27 | chmod 777 frida-server # 赋予最高权限 28 | ./frida-server # 开启服务 29 | ``` 30 | 在安卓开启frida服务之前,我们记得在电脑上开启tcp转发 31 | ```bash 32 | adb forward tcp:27042 tcp:27042 33 | adb forward tcp:27043 tcp:27043 34 | ``` 35 | 36 | ## 下面介绍一些固定的格式 37 | ### 获取连接设别的信息,确认包名 38 | ```python 39 | import frida 40 | 41 | rdev = frida.get_remote_device() 42 | print(rdev) 43 | 44 | processes = rdev.enumerate_processes() 45 | for process in processes: 46 | print(process) 47 | 48 | front_app = rdev.get_frontmost_application() 49 | print(front_app) 50 | 51 | ``` 52 | ### hook类中的方法 53 | 这个是hook的类的方法没有重载的情况 54 | ```python 55 | import frida 56 | import sys 57 | 58 | rdev = frida.get_remote_device() 59 | # app名称或者app包名称 60 | session = rdev.attach("com.shizhuang.duapp") 61 | 62 | # 目标:指定替换是那个包中的方法名 63 | # - 包名称:com.shizhuang.duapp.common.utils 64 | # - 类名称:RequestUtils 65 | # - 方法名:c m30623c-jadx工具给你创造的。 66 | # - 参数1:map 67 | # - 参数2:long 68 | scr = """ 69 | Java.perform(function () { 70 | // 导入类, 看文件最顶部的package 71 | var RequestUtils = Java.use("com.shizhuang.duapp.common.utils.RequestUtils"); 72 | 73 | // 找到类中的方法进行hook 74 | RequestUtils.c.implementation = function(map,j){ 75 | console.log("666"); 76 | var res = this.c(map,j); 77 | console.log("999"); 78 | return res; 79 | } 80 | 81 | }); 82 | """ 83 | script = session.create_script(scr) 84 | 85 | 86 | def on_message(message, data): 87 | print(message, data) 88 | 89 | 90 | script.on("message", on_message) 91 | 92 | script.load() 93 | sys.stdin.read() 94 | ``` 95 | 下面是类中的函数具有重载的情况 96 | ```python 97 | 98 | scr = """ 99 | Java.perform(function () { 100 | // 导入类 101 | var RequestUtils = Java.use("com.douban.frodo.network.ApiSignatureHelper"); 102 | 103 | // 找到类中的方法进行hook,然后加上overload参数类型即可 104 | RequestUtils.a.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = 105 | function(str, str1, str2){ 106 | console.log(str, str1, str2); 107 | var res = this.a(str, str1, str2); 108 | console.log(res); 109 | return res; 110 | } 111 | 112 | }); 113 | """ 114 | script = session.create_script(scr) 115 | ``` 116 | ### 下面是hook so层代码的情况 117 | > so层代码的hook需要在真机下才可以,因为默认只有arm芯片,不支持x86_64 118 | > 119 | ```python 120 | scr = """ 121 | Java.perform(function () { 122 | var addr_func = Module.findExportByName("libJNIEncrypt.so", "AES_128_ECB_PKCS5Padding_Encrypt"); 123 | Interceptor.attach(addr_func, { 124 | onEnter: function(args){ 125 | // 进入并执行函数:AES_128_ECB_PKCS5Padding_Encrypt,args就是参数 126 | console.log("-------------参数 1-------------"); 127 | console.log(args[0].readUtf8String()) 128 | 129 | console.log("-------------参数 2-------------"); 130 | console.log(args[1].readUtf8String()); 131 | }, 132 | onLeave: function(retValue){ 133 | console.log("-------------返回-------------"); 134 | console.log(retValue.readUtf8String()); 135 | } 136 | }) 137 | }); 138 | """ 139 | script = session.create_script(scr) 140 | ``` 141 | > 小总结: 142 | > 143 | > frida hook参数函数的时候,前面的基本都不变,只是hook脚本会发送改变 144 | 145 | ### frida rpc调用so层函数 146 | 147 | ```python 148 | import frida 149 | 150 | rdev = frida.get_remote_device() 151 | session = rdev.attach("名称") 152 | 153 | 154 | # 整体思路和hook差不多,但是需要在rpc里面进行导出 155 | src = """ 156 | rpc.exports = { 157 | CustomizationFunctionName: function(参数列表) { 158 | var res; 159 | Java.perform(function(){ 160 | var CustomizationObjectName = Java.use("包名.类名"); 161 | res = CustomizationObjectName.函数名(参数列表); 162 | }); 163 | return res; 164 | } 165 | } 166 | 167 | """ 168 | 169 | script = session.create_script(src) 170 | script.load() 171 | 172 | wanna_args = script.exports.CustomizationFunctionName("参数列表") 173 | print(wanna_args) 174 | ``` 175 | 其实rpc也很简单,就是稍微导出一下方法就可以了. 176 | 177 | ## frida过检测 178 | ### 常见的frida检测 179 | 1、检测文件名 180 | 181 | 2、检测端口 182 | 183 | 3、双进程保护 184 | 185 | 4、检测D-Bus 186 | 187 | 5、检测/proc/pid/maps映射文件 188 | 189 | 6、检测/proc/pid/task/tip/status 190 | 191 | 7、检测/data/local/tmp目录 192 | ### 利用第三方库以及转化端口达到效果 193 | 我们在注入frida的时候,经常会遇到一注入app就闪退的情况,这种情况说明被检测到了frida 194 | 195 | 这里我们采用绕过的方案 196 | 使用Frida的魔改版本 Hluda来隐藏Frida特征,其介绍:跟随 FRIDA 上游自动修补程序,并为 Android 构建反检测版本的 frida-server。使用方式跟官方Frida没有区别。 197 | 198 | github地址:https://github.com/hzzheyang/strongR-frida-android/ 199 | 200 | 官方Frida默认端口是27042,现在我们来修改启动端口 201 | ```bash 202 | ./hlu-server_x8664 -l 0.0.0.0:8080 203 | ``` 204 | ```bash 205 | adb forward tcp:8080 tcp:8080 206 | frida -H 127.0.0.1:8080 -f com.shizhuang.duapp -l Hook.js 207 | ``` 208 | 使用python脚本连接时 209 | ```python 210 | host = '127.0.0.1:8080' 211 | manager = frida.get_device_manager() 212 | device= manager.add_remote_device(host) 213 | ``` --------------------------------------------------------------------------------