Android逆向实战——以某APP跳过广告为例
字数 1042 2025-08-22 18:37:14

Android逆向实战:跳过某APP广告的完整教学

1. 准备工作

1.1 所需工具

  • MT管理器:用于查看APK信息和Activity记录
  • Objection:动态分析工具,用于方法hook
  • Jadx:反编译工具,用于查看Java源码
  • Frida:动态插桩工具,用于运行时修改应用行为
  • Apktool:用于反编译和回编译APK
  • 签名工具:如apksigner,用于回编译后的APK签名

1.2 目标APP分析

目标APP的广告流程:

  1. 启动时首先加载com.qiyi.video.WelcomeActivity
  2. 然后跳转到org.qiyi.android.video.MainActivity
  3. 在MainActivity中处理广告逻辑

2. 动态分析

2.1 使用Objection进行初步hook

# hook MainActivity的所有方法
objection -g com.qiyi.video explore -s "android hooking watch class_method org.qiyi.android.video.MainActivity.*"

发现WelcomeActivity hook失败,转而分析MainActivity。

2.2 关键方法hook

# 监控触摸事件和广告日志
objection -g com.qiyi.video explore \
-s "android hooking watch class_method org.qiyi.android.video.MainActivity.dispatchTouchEvent --dump-args" \
-s "android hooking watch class_method com.qiyi.video.startup.Startup.log --dump-args"

通过对比跳过广告和未跳过广告的日志,发现广告时间减少和触摸事件变化。

3. 跳过广告的两种方法

3.1 方法一:模拟点击跳过广告

分析dispatchTouchEvent方法:

@Override
public final boolean dispatchTouchEvent(MotionEvent motionEvent) {
    tv1.a aVar = this.S;
    if (aVar != null) {
        aVar.a(motionEvent);
    }
    return super.dispatchTouchEvent(motionEvent);
}

使用Frida生成并发送模拟点击事件:

Java.perform(function() {
    console.log('Begin...');
    const MainActivityClass = Java.use('org.qiyi.android.video.MainActivity');
    
    // 获取MotionEvent相关类
    var MotionEvent = Java.use('android.view.MotionEvent');
    var PointerProperties = Java.use('android.view.MotionEvent$PointerProperties');
    var PointerCoords = Java.use('android.view.MotionEvent$PointerCoords');
    var SystemClock = Java.use('android.os.SystemClock');
    
    // 设置指针属性
    var properties = [PointerProperties.$new()];
    properties[0].id.value = 0;
    properties[0].toolType.value = MotionEvent.TOOL_TYPE_FINGER.value;
    
    // 设置坐标(跳过按钮位置)
    var coords = [PointerCoords.$new()];
    coords[0].x.value = 469.13126;
    coords[0].y.value = 48.949013;
    
    // 定时查找MainActivity实例并发送点击事件
    setTimeout(function() {
        Java.choose('org.qiyi.android.video.MainActivity', {
            onMatch: function(instance) {
                console.log('Found instance:', instance);
                setTimeout(function() {
                    var downTime = SystemClock.uptimeMillis();
                    var eventTime = SystemClock.uptimeMillis();
                    
                    // 发送ACTION_DOWN事件
                    var me_move = MotionEvent.obtain.call(
                        MotionEvent, downTime, eventTime, 
                        MotionEvent.ACTION_DOWN.value, 1, 
                        properties, coords, 0, 0, 0, 0, 2, 0, 0x1002, 0x2
                    );
                    instance.dispatchTouchEvent(me_move);
                    
                    // 发送ACTION_UP事件
                    eventTime = SystemClock.uptimeMillis();
                    var me_up = MotionEvent.obtain.call(
                        MotionEvent, downTime, eventTime, 
                        MotionEvent.ACTION_UP.value, 1, 
                        properties, coords, 0, 0, 0, 0, 2, 0, 0x1002, 0x2
                    );
                    instance.dispatchTouchEvent(me_up);
                }, 1000);
            },
            onComplete: function() {
                console.log('Completed');
            }
        });
    }, 1000);
});

3.2 方法二:修改广告请求逻辑

通过分析日志发现>>> Splash Ad相关逻辑,追踪到关键方法:

public final void r() {
    boolean z14;
    if ((MixUIUtils.isTabletDevice() && GPadSpecialLogic.hideSplashAd()) || q()) {
        return;
    }
    
    // 关键判断条件
    if (StringUtils.equals("0", SpToMmkv.get(QyContext.getAppContext(), 
            "isIgnoreAdReqWhenAppLaunchForPlayer", "0", 
            SharedPreferencesConstants.LAUNCH_SHAREPREFERENCE_NAME)) 
            && f42.a.b() && !f42.a.d()) {
        z14 = true;
    } else {
        z14 = false;
    }
    
    if (z14) {
        return; // 跳过广告请求
    }
    
    sy1.n.d(null, "requestSplashAd"); // 请求广告
    // 其他广告相关逻辑...
}

使用Frida hook关键方法:

Java.perform(function() {
    // Hook SpToMmkv.get方法
    var SpToMmkvClass = Java.use('org.qiyi.basecore.utils.SpToMmkv');
    SpToMmkvClass.get.overload('android.content.Context', 'java.lang.String', 
        'java.lang.String', 'java.lang.String').implementation = function(context, str, str2, str3) {
        if (str === "isIgnoreAdReqWhenAppLaunchForPlayer") {
            console.log('SpToMmkv.get() called for isIgnoreAdReqWhenAppLaunchForPlayer');
            return "1"; // 修改返回值
        }
        return this.get(context, str, str2, str3);
    };
    
    // Hook f42.a.b方法
    var f42_a_Class = Java.use('f42.a');
    f42_a_Class.b.implementation = function() {
        console.log('f42.a.b() called');
        return true; // 强制返回true
    };
    
    // Hook f42.a.d方法
    f42_a_Class.d.implementation = function() {
        console.log('f42.a.d() called');
        return false; // 强制返回false
    };
});

4. 静态修改方法

4.1 反编译APK

apktool.bat d .\iqiyi.apk

4.2 修改smali代码

找到f42.a.b方法的smali代码,修改使其直接返回true:

.method public b()Z
    .registers 2
    
    const/4 v0, 0x1  # 修改为直接返回true
    
    return v0
.end method

或者直接删除条件判断部分,只保留其他两个条件的判断。

4.3 回编译和签名

apktool.bat b .\iqiyi\
# 然后使用签名工具对回编译后的APK进行签名

5. 关键点总结

  1. Activity流程分析:通过MT管理器或logcat确定广告相关的Activity
  2. 日志监控:使用Objection监控关键日志输出,定位广告相关方法
  3. 两种绕过方法
    • 动态模拟点击跳过按钮
    • 静态修改广告请求逻辑
  4. Frida使用技巧
    • 监控方法调用及参数
    • 修改方法返回值
    • 生成并发送模拟事件
  5. 静态修改要点
    • 定位关键判断条件
    • 修改smali代码逻辑
    • 回编译和签名注意事项

6. 注意事项

  1. 本教程仅用于学习Android逆向技术,请勿用于非法用途
  2. 修改他人APP可能违反用户协议和相关法律
  3. 不同版本APP的实现可能不同,需要根据实际情况调整分析方法
  4. 回编译后的APK需要正确签名才能安装运行
  5. 动态分析方法(Frida)需要设备root或模拟器环境
Android逆向实战:跳过某APP广告的完整教学 1. 准备工作 1.1 所需工具 MT管理器 :用于查看APK信息和Activity记录 Objection :动态分析工具,用于方法hook Jadx :反编译工具,用于查看Java源码 Frida :动态插桩工具,用于运行时修改应用行为 Apktool :用于反编译和回编译APK 签名工具 :如apksigner,用于回编译后的APK签名 1.2 目标APP分析 目标APP的广告流程: 启动时首先加载 com.qiyi.video.WelcomeActivity 然后跳转到 org.qiyi.android.video.MainActivity 在MainActivity中处理广告逻辑 2. 动态分析 2.1 使用Objection进行初步hook 发现WelcomeActivity hook失败,转而分析MainActivity。 2.2 关键方法hook 通过对比跳过广告和未跳过广告的日志,发现广告时间减少和触摸事件变化。 3. 跳过广告的两种方法 3.1 方法一:模拟点击跳过广告 分析 dispatchTouchEvent 方法: 使用Frida生成并发送模拟点击事件: 3.2 方法二:修改广告请求逻辑 通过分析日志发现 >>> Splash Ad 相关逻辑,追踪到关键方法: 使用Frida hook关键方法: 4. 静态修改方法 4.1 反编译APK 4.2 修改smali代码 找到 f42.a.b 方法的smali代码,修改使其直接返回true: 或者直接删除条件判断部分,只保留其他两个条件的判断。 4.3 回编译和签名 5. 关键点总结 Activity流程分析 :通过MT管理器或logcat确定广告相关的Activity 日志监控 :使用Objection监控关键日志输出,定位广告相关方法 两种绕过方法 : 动态模拟点击跳过按钮 静态修改广告请求逻辑 Frida使用技巧 : 监控方法调用及参数 修改方法返回值 生成并发送模拟事件 静态修改要点 : 定位关键判断条件 修改smali代码逻辑 回编译和签名注意事项 6. 注意事项 本教程仅用于学习Android逆向技术,请勿用于非法用途 修改他人APP可能违反用户协议和相关法律 不同版本APP的实现可能不同,需要根据实际情况调整分析方法 回编译后的APK需要正确签名才能安装运行 动态分析方法(Frida)需要设备root或模拟器环境