安卓逆向经典案例-XX谷

H5app逆向——XX谷

在这里插入图片描述

这里显示为真,说明app没有禁用WebView调试。

所以调试考虑

  • 反编译出错
  • 利用字符串加密或者反射的方式去禁用调试
通过什么方式可以查找自己想frida hook的类?

在使用 Frida 进行逆向工程时,查找你想要 hook 的类和方法是一个关键步骤。以下是一些常见的方法和工具,可以帮助你找到目标类和方法:

1. 使用 Frida 自带的脚本

Frida 提供了一些内置的脚本,可以帮助你枚举和查找类和方法。

枚举所有加载的类

你可以使用以下脚本来枚举所有加载的类:

Java.perform(function() {
    Java.enumerateLoadedClasses({
        onMatch: function(className) {
            console.log(className);
        },
        onComplete: function() {
            console.log("Enumeration complete");
        }
    });
});
枚举类中的所有方法

找到目标类后,你可以使用以下脚本来枚举该类中的所有方法:

Java.perform(function() {
    var targetClass = Java.use('com.example.TargetClass');
    var methods = targetClass.class.getDeclaredMethods();
    methods.forEach(function(method) {
        console.log(method.toString());
    });
});

2. 使用 jadx 反编译 APK

你可以使用 jadx 反编译 APK 文件,以查看应用程序的源代码。这可以帮助你找到感兴趣的类和方法。

安装和使用 jadx
  1. 安装 jadx:你可以从 jadx GitHub 页面 下载并安装 jadx。

  2. 反编译 APK:使用以下命令反编译 APK 文件:

    jadx -d output_dir your_app.apk
    
  3. 浏览源代码:在输出目录中浏览反编译后的源代码,查找你感兴趣的类和方法。

3. 使用 Android Studio 进行动态调试

你可以使用 Android Studio 的调试工具来动态调试应用程序,设置断点并检查运行时的类和方法。

4. 使用 Frida 的 findClass 方法

你可以使用 Frida 的 findClass 方法来查找特定的类:

Java.perform(function() {
    var className = 'com.example.TargetClass';
    if (Java.available) {
        try {
            var targetClass = Java.use(className);
            console.log('Class found: ' + className);
        } catch (e) {
            console.log('Class not found: ' + className);
        }
    }
});

5. 使用 Frida 的 enumerateClassLoaders 方法

有时候类可能还没有加载,你可以使用 enumerateClassLoaders 方法来查找类加载器并手动加载类:

Java.perform(function() {
    Java.enumerateClassLoaders({
        onMatch: function(loader) {
            try {
                if (loader.findClass('com.example.TargetClass')) {
                    console.log('Class loader found: ' + loader);
                }
            } catch (e) {
                // Ignore
            }
        },
        onComplete: function() {
            console.log('Enumeration complete');
        }
    });
});

6. 使用 Frida 的 InterceptorStalker

你可以使用 Frida 的 InterceptorStalker 来动态跟踪和 hook 方法调用。

示例:拦截方法调用
Java.perform(function() {
    var targetClass = Java.use('com.example.TargetClass');
    targetClass.targetMethod.implementation = function(arg1, arg2) {
        console.log('targetMethod called with arguments: ' + arg1 + ', ' + arg2);
        var result = this.targetMethod(arg1, arg2);
        console.log('targetMethod returned: ' + result);
        return result;
    };
});

总结

通过上述方法,你可以有效地查找和 hook 你感兴趣的类和方法。根据具体情况选择合适的方法和工具,可以大大提高你的逆向工程效率。如果你有任何进一步的问题或需要更多的帮助,请随时告诉我!

解决方法:

直接hook类

andriod.webkit.WebView

hook实战

Java.perform(function (){

    var WebView = Java.use("android.webkit.WebView");//hook 类android.webkit.WebView

    WebView.setWebContentsDebuggingEnabled.overload("boolean").implementation = function (s) {

        // send(s.toString());

        console.log("webview hook")//当出现webview hook时,说明有布尔值被hook了

        // this.loadUrl.overload("java.lang.String").call(this, s);

        // console.log(this.)

        this.setWebContentsDebuggingEnabled(true)//设置webview可调

    };

} 作者:叫我龙哥就好re https://www.bilibili.com/read/cv7946527/ 出处:bilibili

hook WebView脚本

Java.perform(function () {

    var WebView = Java.use("android.webkit.WebView");
    WebView.$init.overload('android.content.Context').implementation = function (a) {
        console.log("WebView.$init is called");
        var retval = this.$init(a);
        this.setWebContentsDebuggingEnabled(true);
        return retval;
    }
    WebView.$init.overload('android.content.Context','android.util.AttributeSet').implementation = function (a,b) {
        console.log("WebView.$init is called");
        var retval = this.$init(a,b);
        this.setWebContentsDebuggingEnabled(true);
        return retval;
    }
    WebView.$init.overload('android.content.Context','android.util.AttributeSet','int').implementation = function (a,b,c) {
        console.log("WebView.$init is called");
        var retval = this.$init(a,b,c);
        this.setWebContentsDebuggingEnabled(true);
        return retval;
    }
    WebView.$init.overload('android.content.Context','android.util.AttributeSet','int','boolean').implementation = function (a,b,c,d) {
        console.log("WebView.$init is called");
        var retval = this.$init(a,b,c);
        this.setWebContentsDebuggingEnabled(true);
        return retval;
    }
    WebView.$init.overload('android.content.Context','android.util.AttributeSet','int','int').implementation = function (a,b,c,d) {
        console.log("WebView.$init is called");
        var retval = this.$init(a,b,c,d);
        this.setWebContentsDebuggingEnabled(true);
        return retval;
    }
    // WebView.$init.overload('android.content.Context','android.util.AttributeSet','int','int','java.util.Map','boolean').implementation = function (a,b,c,d) {
    //     console.log("WebView.$init is called");
    //     var retval = this.$init(a,b,c,d,e,f);
    //     this.setWebContentsDebuggingEnables(true);
    //     return retval;
    // }
    // WebView.setWebContentDebuggingEnabled.implementation = function () {
    //     this.setWebContentsDebuggingEnabled(true);
    //     console.log("setWebContentDebuggingEnabled is called")
    // }
    // 检查 WebView 类是否存在
    if (WebView) {
        // 重写 setWebContentsDebuggingEnabled 方法
        WebView.setWebContentsDebuggingEnabled.implementation = function (enabled) {
            this.setWebContentsDebuggingEnabled(true);
            console.log("setWebContentsDebuggingEnabled is called with argument: " + enabled);
        };//setWebContentsDebuggingEnabled
    } else {
        console.log("WebView class not found");
结果

在这里插入图片描述

现在可以调试了

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这里的到的http是发送的端口。httpcanary可以抓包,charles要设置非标准端口抓包。

       login: function() {
                    var A = this
                      , t = A.$refs.phone.value;
                    /^1[3456789]\d{9}$/.test(t) ? A.$http.post(A.$store.state.marUrl + "/login/login", {
                        phone: A.$refs.phone.value,
                        password: A.$refs.password.value
                    }, {
                        emulateJSON: !0
                    }).then((function(t) {
                        if ("用户名或密码错误" == t.body.msg)
                            this.presentAlert("手机号或密码错误");
                        else {
                            var e = t.body.user;
                            A.$cookies.set("user", e, "15d"),
                            A.$store.commit("changeToken", t.body.token),
                            A.$store.commit("changeTokenState", t.body.token),
                            this.$router.push({
                                path: "/shop"
                            })
                        }
                    }

这里我获得了A.$store.state.marUrl"http://121.36.75.162:7878",算是逆向吗?可以通过这个url获取什么有价值的信息吗?

加密通常在JS文件中,

解决方法:远程调试、修改JS代码注入

H5app的发包方法:

  1. 纯JS发包,可以在远程调试工具抓包(chrom:inspect)
  2. 部分JS发包,部分java,这时调试工具抓不了,要分析
    • JS和java如何互相调用,找java层接口
  3. 纯java发包

webView远程调试的要求:

  1. 手机端的webview比电脑端的Chrome版本低
  2. 手机端的webview需要开启可调式
  3. 需要科学上网(VPN)才能在chrome浏览器调试

批处理脚本(.bat)

这里是博主写的用来一键启动frida server的批处理文件。

确保你的批处理脚本在启动 Frida Server 之前检查并释放端口:

@echo off
adb kill-server
adb start-server

REM 检查并杀掉占用端口的进程
adb shell "su -c 'lsof -i :27042 | grep LISTEN | awk '{print $2}' | xargs kill -9'"

adb shell "su -c 'cd /data/local/tmp && chmod 777 frida-server-14.2.2-android-arm64 && ./frida-server-14.2.2-android-arm64 &'"
adb forward tcp:27042 tcp:27042

REM 检查 Frida Server 是否成功启动
adb shell "ps | grep frida-server"
if %errorlevel% neq 0 (
    echo Frida Server failed to start.
    pause
    exit /b 1
) else (
    echo Frida Server started successfully!
)

REM 检查端口转发是否成功
adb forward --list | findstr "tcp:27042"
if %errorlevel% neq 0 (
    echo Port forwarding failed.
    pause
    exit /b 1
) else (
    echo Port forwarding set up successfully!
)

REM 测试连接到 Frida Server
frida-ps -H 127.0.0.1:27042
if %errorlevel% neq 0 (
    echo Failed to connect to Frida Server.
    pause
    exit /b 1
) else (
    echo Successfully connected to Frida Server!
)

pause
netstat -tunlp
  • 用于查看frida server的端口占用情况
kill -9 [PID]
  • 可以杀死fridaserver进程,重启frida server

总结

引用webview类的方法
找webview类时遇到的问题

在 Android Studio 中没有看到 WebView.setWebContentsDebuggingEnabled 方法,可能是因为你引用的 WebView 类是一个模拟(mock)版本,而不是实际的 Android 系统中的 WebView 类。模拟版本通常用于测试和开发环境中,并不包含所有实际类的方法。

解决方法

  1. 确保引用正确的库:确保你的项目引用了正确的 Android SDK 库,而不是模拟库。

  2. 检查依赖项:在 build.gradle 文件中,确保你引用了正确的 Android 库。

示例 build.gradle 文件

确保你的 build.gradle 文件中包含以下依赖项:

dependencies {
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support:design:28.0.0'
    implementation 'com.android.support:support-v4:28.0.0'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    implementation 'com.android.support:cardview-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:support-annotations:28.0.0'
    implementation 'com.android.support:support-core-utils:28.0.0'
    implementation 'com.android.support:support-core-ui:28.0.0'
    implementation 'com.android.support:support-fragment:28.0.0'
}

检查类路径

确保你引用的是实际的 android.webkit.WebView 类,而不是模拟类。你可以通过以下方式检查:

  1. 在代码中直接引用 android.webkit.WebView

    import android.webkit.WebView;
    
    public class MyActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            WebView webView = findViewById(R.id.webview);
            webView.setWebContentsDebuggingEnabled(true);
        }
    }
    
  2. 确保没有引用模拟类:检查你的项目中是否有类似 com.android.layoutlib.bridge.MockView 的引用,如果有,移除或替换为实际的 Android 类。

使用正确的方法

确保你使用的是正确的方法名 setWebContentsDebuggingEnabled,而不是其他类似的方法名。

示例代码

以下是一个完整的示例代码,确保正确引用 WebView 类并调用 setWebContentsDebuggingEnabled 方法:

import android.os.Bundle;
import android.webkit.WebView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        WebView webView = findViewById(R.id.webview);
        WebView.setWebContentsDebuggingEnabled(true);
    }
}

进一步排查

  1. 检查 Android SDK 版本:确保你使用的 Android SDK 版本支持 setWebContentsDebuggingEnabled 方法。该方法在 API 级别 19(Android 4.4 KitKat)及以上版本中可用。

  2. 查看官方文档:查阅 Android 官方文档,确保方法名和用法正确。

如果你有任何进一步的问题或需要更多的帮助,请随时告诉我!

资料

安卓逆向第七篇-hook android WebView js注入 - 简书 (jianshu.com)

WebViewDebugHook: 深度调试Webview的利器-CSDN博客

我找到了几个关于使用 Frida hook WebView 重载方法的资源和示例。以下是一些有用的链接和信息:

  1. Stack Overflow - Frida Intercept all webview traffic

    • 讨论了如何使用 Frida 拦截所有 WebView 流量,包括异步 JavaScript 请求。
    • 链接
  2. Node Security - Android Hooking in Frida

    • 详细解释了如何使用 Frida hook Android 的 WebView 类,包括获取 loadUrl 方法的重载版本。
    • 链接
  3. OWASP - Testing for URL Loading in WebViews

    • 介绍了如何使用 Frida 或 frida-trace 动态测试 WebView 中的深度链接,包括 hook shouldOverrideUrlLoadingshouldInterceptRequest 方法。
    • 链接
  4. GitHub - iddoeldor/frida-snippets

    • 提供了多个 Frida 示例,包括如何 hook 所有方法重载。
    • 链接
  5. GitHub - How to hook WebSettings.getSettings() method

    • 讨论了如何 hook WebView 类中的 getSettings 方法,并获取与 WebView 关联的 WebSettings 对象。
    • 链接

这些资源应该能帮助你找到更多关于如何使用 Frida hook WebView 重载方法的示例和详细信息。如果你有任何进一步的问题或需要更多的帮助,请随时告诉我!

  • 36
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吕昀hui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值