1、工具的技巧

Jadx-gui工具

搜索中文

首先需要在首选项那里将设置Unicode 字符转义关闭。

开发者助手

根据布局ID来定位程序

通过开发者助手的定位ID

image-20260223225502431

在mt管理器dex文件中搜索ID,搜索类型选择整数。

image-20260223230026054

算法助手

自定义hook

在jeb中,在方法悬浮,可以看到详细信息。

image-20260223231538184

1
2
3
4
5
6
7
8
9
10
11
org.json.JSONObject.has(java.lang.String) : boolean
Descriptor: Lorg/json/JSONObject;->has(Ljava/lang/String;)Z
[AST Objects Stack]
Class: class:Lapp/video/guoguo/SplashActivity;
Method: method:app.video.guoguo.SplashActivity.onEnd
Block:
Try:
Block:
If:
Predicate: (has(new org.json.JSONObject(s), \"libapp.so\"))
Call: has

在算法助手中填写,参考文章如下:

APP攻防–安卓逆向&JEB动态调试&LSPosed模块&算法提取&Hook技术 - 了了青山见 - 博客园

image-20260223231818129

ida

ida动态调试

前置信息

image-20260224221513638

函数的基本介绍:

函数名 描述
android_dlopen_ext()dlopen()do_dlopen() 这三个函数主要用于加载库文件。android_dlopen_ext 是系统的一个函数,用于在运行时动态加载共享库。与标准的 dlopen() 函数相比,android_dlopen_ext 提供了更多的参数选项和扩展功能,例如支持命名空间、符号版本等特性。
find_library() find_library() 函数用于查找库,基本的用途是给定一个库的名字,然后查找并返回这个库的路径。
call_constructors() call_constructors() 是用于调用动态加载库中的构造函数的函数。
init 库的构造函数,用于初始化库中的静态变量或执行其他需要在库被加载时完成的任务。如果没有定义init函数,系统将不会执行任何动作。需要注意的是,init函数不应该有任何参数,并且也没有返回值。
init_array init_array是ELF(Executable and Linkable Format,可执行和可链接格式)二进制格式中的一个特殊段(section),这个段包含了一些函数的指针,这些函数将在main()函数执行前被调用,用于初始化静态局部变量和全局变量。
jni_onload 这是Android JNI(Java Native Interface)中的一个函数。当一个native库被系统加载时,该函数会被自动调用。JNI_OnLoad可以做一些初始化工作,例如注册你的native方法或者初始化一些数据结构。如果你的native库没有定义这个函数,那么JNI会使用默认的行为。JNI_OnLoad的返回值应该是需要的JNI版本,一般返回JNI_VERSION_1_6

下断点时机:
应用级别的:java_com_XXX;
外壳级别的:JNI_Onload,.init,.init_array(反调试);
系统级别的:fopen,fget,dvmdexfileopen(脱壳);

ida调试流程

ida前置操作:

1.在IDA目录下的dbgsrv,选择跟手机架构一致的server
2.adb push as /data/local/tmp/

image-20250914124010953

移动后将android_server64重命名为as,修改as权限为可执行。

image-20260224221730917

3.进入手机端命令:adb shell
4.切换获取手机的root权限:su
5.跳到对应路径:cd /data/local/tmp/
6.提权:chmod 777 as
7.XappDebug hook(手机里打开这个app,把需要破解的软件开了)

image-20260224221848850

闪退的话,在mt管理器中运行命令终端,setenforce 0 就可以解决问题。

可以先通过下面命令确认问题:

调试确认SELinux问题
为了澄清是否因为SELinux导致的问题,可先执行:

1
2
3
setenforce 0 (临时禁用掉SELinux)

getenforce (得到结果为Permissive)

如果问题消失了,基本可以确认是SELinux造成的权限问题,需要通过正规的方式来解决权限问题。

遇到权限问题,在logcat或者kernel的log中一定会打印avc denied提示缺少什么权限,可以通过命令过滤出所有的avc denied,再根据这些log各个击破:

1
cat /proc/kmsg | grep avc 

1
dmesg | grep avc

参考文章

8.运行端口转发

第一个bat脚本:

1
2
3
4
@echo on   %关闭回显命令%
start "" cmd /k call IDAdebug2.bat %新打开一个cmd并运行IDAdebug1.bat%
adb shell "su -c './data/local/tmp/as'"
pause

第二个bat脚本:

1
2
3
4
@echo on %关闭回显命令%
adb forward tcp:23946 tcp:23946 %端口转发%
adb shell am start -n com.zj.demo/.ui.ChallengeEight %debug状态启动手机端APP%
pause

com.zj.demo/.ui.ChallengeEight(是类的启动类)

image-20260224222354860

8.1 运行二个bat脚本。

8.2将程序的so拉到ida中,下断点。

image-20260224222544417

8.3 选择调试器

image-20260224222620323

8.4 点击进程选项

image-20260224222712433

8.5 选择主机名以及端口。

image-20260224222752398

8.6 接着附加到进程

image-20260224222840605

  1. 7 输入搜索包名

image-20260224222910958

8.8 选择要附加的进程

image-20260224222939555

成功使用ida调试。

image-20260224223025271

其他问题

qtscrcpy无法触控手机问题解决方案

开启USB安装,USB调试(安全设置)既可。

ida脚本

放到plugins目录下,然后右在ida中键就会有的

image-20260224224029385

image-20260224224036823

frida

建议下载16.1.0版本,新版本的函数名做了更新,一些就的函数无法使用

workon查看环境

1
workon

进入环境,要CMD才行的

1
workon 环境名

查看手机是什么cpu

1
adb shell getprop ro.product.cpu.abi

image-20260224223509379

所以要将arm64位的下载下来

将frida服务端放到/data/local/tmp目录下

1
adb push .\frida-server-16.1.0-android-x86 /data/local/tmp/

修改文件权限,要可执行

adb进入手机shell

1
2
3
adb shell
cd /data/local/tmp/
./frida-server-16.1.0-android-x86

此时已经运行了frida了

1
C:\Users\用户名\Envs\fribatest\Scripts

下运行

1
frida-ps -U

image-20260224223824749

frida-ps -U为查看手机运行进程,下面的-U wuaipojie中的wuaipojie就是手机运行的进程来着。

如果运行成功,说明server端已经安装完成。

1
D:\reserve\Andriod\WORKON_HOME\fribatest\Scripts\frida.exe -U wuaipojie -l hook.js

Android studio

Android studio代理设置

代理设置如下图所示:

image-20260224214557613

image-20260224214708987

2、逆向功能实现

每个页面都是一个activity,页面的跳转可以通过修改类来实现。

可以通过修改xml文件来跳转。

也可以通过修改dex文件的代码逻辑来修改。

去除广告

通过lsposed加载算法助手,在模块中点击算法助手,接下来选择想要hook的app,勾选。接着打开算法助手,在应用栏中选择需要hook的app,点击应用总开关,接着选择弹窗定位,返回键可取消。‘

横幅广告

算法助手选择布局查看,然后复制图片的ID,在mt管理器或者np管理器(推荐MT文件管理器VIP会员版 2.14.5)中选择XML搜索。

image-20260223231250303

搜索类型选择资源ID。

image-20260223231200572

动态调试

搜索按钮:

image-20260224193637313

搜索出来后右键解析,既可转换成代码。

image-20260224193711920

下断点

image-20260224193754137

手机开启adb权限

.debug模式启动

1
adb shell am start -D -n com.zj.demo/.ui.MainActivity
  • adb shell am start -D -n
  • adb shell am start -D -n 包名/类名
  • am start -n 表示启动一个activity
  • am start -D 表示将应用设置为可调试模式

类名在在AndroidManifest.xml里查看,去掉前面的报名就是类名了。

image-20260224194829594

命令运行上面的adb代码。

1
adb shell am start -D -n com.zj.demo/.ui.MainActivity

点击附上,图如下:

image-20260224194955892

image-20260224195135622

成功后,看局部变量。截图如下:

image-20260224195245508

然后在手机上运行程序,触发一下断点。

注意事项

Xappdebug的系统框架需要勾选起来,需要重新开机。

image-20260224195524203

3、逆向的基础知识点

3.1、签名

目前签名分成v1-v4

Android 目前支持以下四种应用签名方案:

  • v1 方案:基于 JAR 签名。
  • v2 方案:APK 签名方案 v2(在 Android 7.0 中引入)
  • v3 方案:APK 签名方案 v3(在 Android 9 中引入)
  • v4 方案:APK 签名方案 v4(在 Android 11 中引入)

过签名

绕过针对dex中签名检验

首先就是重新签名原来的app,安装后,签名校验的定位,就是通过算法助手,开启log捕获,利用app的签名不对闪退的机制来获取日志,

image-20260224202511076

点击算法助手的右上开始,捕获log日志。

image-20260224202656037

在log中找到获取到校验签名的方法。

image-20260224202751702

然后在mt管理器中在dex文件搜索

签名校验的方法名,找到对应的逻辑,通过Jadx-gui编译成java代码方便查看后再看dex中修改相关逻辑,可以通过修改函数的最后返回值。

io重定向过签名检验

在apk读取安装包信息的时候,让其读取原来的APk安装包,这样就不会有任何问题了。

3.2、Xposed介绍

什么是Xposed?

Xposed是一款可以在不修改APK的情况下影响程序运行的框架,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。在这个框架下,我们可以编写并加载自己编写的插件APP,实现对目标apk的注入拦截等。

参考文章:正己

Xposed原理

用自己实现的app_process替换掉了系统原本提供的app_process,加载一个额外的jar包,入口从原来的: **com.android.internal.osZygoteInit.main()被替换成了: de.robv.android.xposed.XposedBridge.main()**,
创建的Zygote进程就变成Hook的Zygote进程了,从而完成对zygote进程及其创建的Dalvik/ART虚拟机的劫持(zytoge注入)

image-20260224205836081

Xposed的发展及免root框架

名称 地址 支持版本 是否免root
xposed https://github.com/rovo89/Xposed 2.3-8.1
EDXposed https://github.com/ElderDrivers/EdXposed 8.0-10
LSPosed https://github.com/LSPosed/LSPosed 8.1-13
VirtualXposed https://github.com/android-hacker/VirtualXposed 5.0-10.0
太极 https://www.coolapk.com/apk/me.weishu.exp 5.0-13
两仪 https://www.coolapk.com/apk/io.twoyi 8.1-13
天鉴 https://github.com/Katana-Official/SPatch-Update 6-10

Xposed可以做什么?

1.修改app布局:上帝模式
2.劫持数据,修改参数值、返回值、主动调用等。例:微信防撤回、步数修改、一键新机
应用变量

image-20260224205941080

Xposed环境配置

前置

ubuntu虚拟机镜像,感谢沐阳哥提供的镜像!!!
内置:

  • Frida开发环境
  • 动态分析及开发工具:android-studio
  • 动态分析工具:ddms
  • 静态分析工具:jadx1.4.4
  • 动静态分析工具:jeb
  • 动态分析工具:集成HyperPwn
  • 静态分析工具:010 editor
  • 抓包工具:Charles
  • 抓包工具:WireShark
  • 动态分析工具:unidbg

vm虚拟机:https://www.vmware.com/cn/products/workstation-pro/workstation-pro-evaluation.html
(或下载我打包好的)
激活码自行百度哦

第一步,安装虚拟机调整路径,输入激活码

第二步,导入镜像,文件->打开->选择解压好的镜像

第三步,点击运行,待初始化,输入密码:toor

  1. Android Studio创建新项目
  2. 将下载的xposedBridgeApi.jar包拖进libs文件夹
  3. 右击jar包,选择add as library
  4. 修改xml文件配置
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 是否是xposed模块,xposed根据这个来判断是否是模块 -->
<meta-data
android:name="xposedmodule"
android:value="true" />
<!-- 模块描述,显示在xposed模块列表那里第二行 -->
<meta-data
android:name="xposeddescription"
android:value="这是一个Xposed模块" />
<!-- 最低xposed版本号(lib文件名可知) -->
<meta-data
android:name="xposedminversion"
android:value="89" />

5.修改build.gradle,将此处修改为compileOnly 默认的是implementation

1
2
implementation 使用该方式依赖的库将会参与编译和打包
compileOnly 只在编译时有效,不会参与打包

6.新建–>Folder–>Assets Folder,创建xposed_init(不要后缀名):只有一行代码,就是说明入口类
7.新建Hook类,实现IXposedHookLoadPackage接口,然后在handleLoadPackage函数内编写Hook逻辑

1
2
3
4
5
6
7
8
9
import de.robv.android.xposed.IXposedHookLoadPackage; 
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class Hook implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {

}
}

继承了IXposedHookLoadPackag便拥有了hook的能力

Xpoosed常用API

An efficient Hook API and Xposed Module solution built in Kotlin

1.Hook普通方法

修改返回值

1
2
3
4
5
6
7
XposedHelpers.findAndHookMethod("com.zj.wuaipojie.Demo", loadPackageParam.classLoader, "a", String.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
param.setResult(999);
}
});

修改参数

1
2
3
4
5
6
7
XposedHelpers.findAndHookMethod("com.zj.wuaipojie.Demo", loadPackageParam.classLoader, "a", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
String a = "pt";
param.args[0] = a; }
});

2.Hook复杂&自定义参数

1
Class a = loadPackageParam.classLoader.loadClass("类名"); XposedBridge.hookAllMethods(a, "方法名", new XC_MethodHook() {   @Override   protected void beforeHookedMethod(MethodHookParam param) throws Throwable {      super.beforeHookedMethod(param);      } });

3.Hook替换函数

1
2
3
4
5
6
7
Class a = classLoader.loadClass("类名")
XposedBridge.hookAllMethods(a,"方法名",new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
return "";
}
});

4.Hook加固通杀

1
2
3
4
5
6
7
8
XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {  
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Context context = (Context) param.args[0];
ClassLoader classLoader = context.getClassLoader();
//hook逻辑在这里面写
}
});

3.3、ELF文件

ELF(Executable and Linkable Format)是一种可执行和可链接的文件格式,是linux底下二进制文件,可以理解为windows下的PE文件,在Android中可以比作SO,方便函数的移植,在常用于保护Android软件,增加逆向难度。

ELF文件的主要组成部分包括:

  • ELF Header:文件头,描述文件的基本信息
  • Program Header Table:程序头表,描述进程映像的布局
  • Section Header Table:节区头表,描述文件的各个节区
节区名 描述
.text 代码段,存放程序的指令
.data 数据段,存放已初始化的全局变量和静态变量
.rodata 只读数据段,存放只读数据
.bss 未初始化数据段,存放未初始化的全局变量和静态变量
.symtab 符号表,存放符号信息
.strtab 字符串表,存放字符串数据
.dynsym 动态符号表,存放动态链接需要的符号信息
.dynamic 动态链接信息,存放动态链接器需要的信息

3.4、NDK开发

NDK(Native Development Kit)是一套用于开发Android应用程序的工具集,它允许您在C/C++中编写性能关键的部分代码,并将这些代码与Java代码进行连接。

步骤:
1.下载NDK和CMake
img
img
2.新建一个项目,往下拉,找到”c++”这个选项
3.查看CMakeLists.txt和编写native-lib.cpp
下面是cmakelist.txt和native-lib.cpp文件的作用以及简要说明:

文件名 作用 说明
CMakeLists.txt 构建配置文件 CMakeLists.txt是用于配置NDK项目的构建系统的文件。它指定了构建所需的源文件、依赖项、编译选项等。在构建过程中,CMake会根据该文件的指示生成对应的构建脚本,用于编译本地代码并生成本地库。
native-lib.cpp 本地代码实现文件 native-lib.cpp是包含本地代码实现的文件。它定义了通过Java和本地代码之间进行通信的本地方法。该文件中的函数实现将被编译为本地库,供Java代码调用。
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
public class MainActivity extends AppCompatActivity {

// Used to load the 'ndkdemo' library on application startup.
static {
System.loadLibrary("ndkdemo"); // 加载名为"ndkdemo"的库
}

private ActivityMainBinding binding; // 声明一个ActivityMainBinding变量

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

binding = ActivityMainBinding.inflate(getLayoutInflater()); // 使用ViewBinding将布局文件解析为一个ActivityMainBinding对象
setContentView(binding.getRoot()); // 将Activity的布局设置为根布局

// Example of a call to a native method
TextView tv = binding.sampleText; // 获取布局文件中的TextView控件
tv.setText(stringFromJNI()); // 调用本地方法stringFromJNI()并将其返回的字符串设置为TextView的文本内容
}

/**
* A native method that is implemented by the 'ndkdemo' native library,
* which is packaged with this application.
*/
public native String stringFromJNI(); // 声明一个native方法stringFromJNI()
}
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
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# 设置构建本地库所需的CMake的最小版本要求
cmake_minimum_required(VERSION 3.22.1)

# 声明和命名项目
project("ndkdemo")

# 创建并命名一个库,设置其类型为STATIC或SHARED,并指定源代码的相对路径
# 可以定义多个库,CMake会为您构建它们
# Gradle会自动将共享库打包到APK中
add_library(
# 设置库的名称
ndkdemo

# 设置库类型为共享库
SHARED

# 提供源文件的相对路径
native-lib.cpp)

# 搜索指定的预构建库并将路径存储为变量。
# 由于CMake默认在搜索路径中包含系统库,因此您只需指定要添加的公共NDK库的名称。
# CMake会在完成构建之前验证该库是否存在。
find_library(
# 设置路径变量的名称
log-lib

# 指定要让CMake定位的NDK库的名称
log)

# 指定CMake应链接到目标库的库。
# 您可以链接多个库,例如在此构建脚本中定义的库、预构建的第三方库或系统库。
target_link_libraries(
# 指定目标库
ndkdemo

# 将目标库链接到NDK中包含的log
${log-lib})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <jni.h> // JNI头文件,提供了JNI函数和数据类型的定义
#include <string> // C++标准库的string类

// 声明一个jni函数,该函数将会被Java代码调用
// JNIEXPORT表示这个函数是可导出的,并且可以被其他代码使用
// jstring表示这个函数返回的是一个Java字符串对象
// JNICALL是JNI函数的调用约定
// Java_com_example_ndkdemo_MainActivity_stringFromJNI是JNI函数的命名规则,与Java中对应的方法名对应
// Java打头,1包名,2类名,3方法名字;"_"号隔开
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ndkdemo_MainActivity_stringFromJNI(
JNIEnv* env, // JNIEnv是指向JNI环境的指针,可以用来访问JNI提供的功能
jobject /* this */) { // jobject是指向Java对象的指针,在本例中并没有使用

std::string hello = "Hello from C++"; // 创建一个C++字符串对象
return env->NewStringUTF(hello.c_str()); // 将C++字符串对象转换为Java字符串对象并返回
}

JNI的前世今生

NDK是开发套件,JNI才是调用的框架。所以与其说是NDK开发,不如说是JNI的开发。不过NDK是Android提供的开发套件。JNI可不是,JNI全称Java Native Interface,即Java本地接口,JNI是Java调用Native 语言的一种特性。通过JNI可以使得Java与C/C++机型交互。即可以在Java代码中调用C/C++等语言的代码或者在C/C++代码中调用Java代码。

JNI的两种注册方式

jni静态注册方式

  • 优点: 理解和使用方式简单, 属于傻瓜式操作, 使用相关工具按流程操作就行, 出错率低

  • 缺点: 当需要更改类名,包名或者方法时, 需要按照之前方法重新生成头文件, 灵活性不高

    jni动态注册方式
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
#include <jni.h>
#include <string>

extern "C" {

JNIEXPORT jstring JNICALL Java_com_example_ndkdemo_MainActivity_nativeGetStringFromJNI(JNIEnv* env, jobject obj) {
std::string hello = "Hello wuaipojie";
return env->NewStringUTF(hello.c_str());
}

// 定义本地方法注册函数
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}

// 定义要注册的本地方法
JNINativeMethod methods[] = {
{"nativeGetStringFromJNI", "()Ljava/lang/String;", reinterpret_cast<void*>(Java_com_example_ndkdemo_MainActivity_nativeGetStringFromJNI)}
};

// 获取类引用
jclass clazz = env->FindClass("com/example/ndkdemo/MainActivity");
if (clazz == nullptr) {
return -1;
}

// 注册本地方法
if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
return -1;
}

return JNI_VERSION_1_6;
}

} // extern "C"

数据类型

下面是一些常见的C++数据类型和它们在Java中的对应关系,以及它们在JNI动态注册中的数据类型签名(signature):

C++ 数据类型 Java 数据类型 JNI 数据类型签名
jint int “I”
jboolean boolean “Z”
jbyte byte “B”
jchar char “C”
jshort short “S”
jlong long “J”
jfloat float “F”
jdouble double “D”
jobject Object “Ljava/lang/Object;”
jstring String “Ljava/lang/String;”
jarray Array “[elementType”
jobjectArray Object[] “[Ljava/lang/Object;”
jbooleanArray boolean[] “[Z”
jbyteArray byte[] “[B”
jcharArray char[] “[C”
jshortArray short[] “[S”
jintArray int[] “[I”
jlongArray long[] “[J”
jfloatArray float[] “[F”
jdoubleArray double[] “[D”

在JNI动态注册中,需要使用正确的数据类型签名来声明本地方法。例如,如果你要注册一个返回int类型的本地方法,其数据类型签名应为I

4、逆向实战

去广告

关键字:initsdk、loadad、initad等

广告关键词 厂商 文档
com.qq.e.ads 腾讯优量汇广告 https://developers.adnet.qq.com/doc/android/union/union_splash
CSJAD、TTAdSdk、bytedance、pangolin 穿山甲广告 https://www.csjplatform.com/supportcenter/5395
ADMob、google.ads 谷歌广告 https://developers.google.com/admob/android/app-open?hl=zh-cn#extend
TorchAd 360广告 https://easydoc.soft.360.cn/doc?project=186589faed863b0a24f15f9bcbafd5c7&doc=2cbbbe19c5cb90f5e7a41c7037b0029a&config=title_menu_toc
kwad 快手广告 https://u.kuaishou.com/home/help/detail/1334/1370/1310
baidu.mobads 百度广告 http://bce.ssp.baidu.com/mssp/sdk/BaiduMobAds_MSSP_bd_SDK_android_v5.1.pdf
MimoSdk 米盟广告 https://t5.a.market.xiaomi.com/download/AdCenter/0d3a369516ee146e8a9d5c290985939da4624fe0a/AdCenter0d3a369516ee146e8a9d5c290985939da4624fe0a.html
sigmob.sdk sigmob广告 https://doc.sigmob.com/#/Sigmob%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/SDK%E9%9B%86%E6%88%90%E8%AF%B4%E6%98%8E/Android/SDK%E6%8E%A5%E5%85%A5%E9%85%8D%E7%BD%AE/
TradPlus TradPlus聚合广告 https://service.cocos.com/document/zh/tradplusad.html

通过免广告关键字来实现部分广告的去除。

首先通过mt的activity的监听器监听启动类,在jadx-ui中分析相关的广告类启动器,在mt中直接注释掉就行了。

签名校验

先对app重新签名,app会闪退,在算法助手里打开app的闪退拦截,在日志里分析拦截的包是哪个类触发的,跟踪这些代码,使其方法放回空。

去掉更新弹窗

首先使用算法助手打开弹窗定位

image-20260224223327550

布局优化

使用开发助手

image-20260224223403702

获取日志后查看其方法名,在电脑上jadx中分析就行了。

5、其他问题

无法解决adb调试问题,APP闪退

  1. 调试确认SELinux问题
    为了澄清是否因为SELinux导致的问题,可先执行:
1
2
3
setenforce 0 (临时禁用掉SELinux)

getenforce (得到结果为Permissive)

如果问题消失了,基本可以确认是SELinux造成的权限问题,需要通过正规的方式来解决权限问题。

frida17版本和17以下的版本特性不同,函数名称已改变

端口占用

发生下面问题

phoenix:/data/local/tmp # ./frida-server-14.2.18-android-arm64
Unable to start: Error binding to address 127.0.0.1:27042: Address already in use

解决方法:

image-20260224224237697

1
2
ps -ef | grep frida
kill -9 25546