【iOS安全】JS 调用Objective-C中WKWebview Handler的三种方式

有三种实现途径

1. WKScriptMessageHandler

OC部分:注册并实现Handler

将OC中的方法"nativeMethod"注册为JavaScript Message Handler,从而WebView中的JavaScript代码可以调用该方法

c 复制代码
// Register in Objective-C code
- (void)setupWKWebView
{
    // [WKWebViewConfiguration alloc]返回一个被分配和初始化的WKWebViewConfiguration对象的指针
    // init方法是WKWebViewConfiguration类的实例方法
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    
    configuration.userContentController = [[WKUserContentController alloc] init];
    
    // 将OC中的方法"nativeMethod"注册为JavaScript Message Handler,从而可以在WebView中执行JavaScript代码时调用该方法
    [configuration.userContentController 
        addScriptMessageHandler:self // addScriptMessageHandler是方法名,self是参数1
        name:@"nativeMethod"]; // name是参数2
    
    // 初始化WKWebView
    WKWebView *webView = 
        [[WKWebView alloc]
            initWithFrame:self.view.frame
            configuration:configuration];
}

// Handler method defined in WKScriptMessageHandler
- (void)userContentController:
    (WKUserContentController *)userContentController //userContentController是参数1
    didReceiveScriptMessage:(WKScriptMessage *)message //message是参数2
{
    if ([message.name isEqualToString:@"nativeMethod"]) // 当JS端调用的是nativeMethod时
    {
        ... //OC端的handler逻辑实现
    }
}

JS部分:调用Handler

调用"nativeMethod"

javascript 复制代码
// Invoke in JavaScript code
window.webkit.messageHandlers.nativeMethod.postMessage();

2. WebViewJavascriptBridge

OC部分:注册并实现Handler

注册名为"nativeMethod"的Handler

c 复制代码
// OC中 调用bridgeForWebView:方法,来初始化WebViewJavascriptBridge
// self.bridge将被设置为WKWebView的navigationDelegate属性
self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];

[self.bridge registerHandler:@"nativeMethod" //参数1,JS端以这个函数名调用该注册的native方法
    handler: //参数2的参数名,冒号后面跟着参数2的参数值,是一个block;当JS端调用nativeMethod方法时,OC端执行该block
    ^(id data, WVJBResponseCallback responseCallback) 
    // ^代表后面是一个block 
    // data是JS端传递过来的数据
    // responseCallback是 OC端的 block 执行完毕之后,往 JS 端传递的数据
    {
        ... // block中的代码,这些代码在JS端调用nativeMethod时被执行
    }
];

JS部分:调用Handler

js 复制代码
WebViewJavascriptBridge.callHandler('nativeMethod', data, function(responseData) {
    // 处理来自Objective-C的响应数据
    console.log(response); 
});

例如我们使用Frida分析出来,某app的wkwebview中有如下handler:

c 复制代码
{
    callNavigationSelectView = "<__NSMallocBlock__: 0x281d4a440>";
    checkNotificationPermission = "<__NSMallocBlock__: 0x281d4b240>";
    clickControlToShare = "<__NSMallocBlock__: 0x281d4bf00>";
    couponPaySuccess = "<__NSMallocBlock__: 0x281d4a780>";
    doQRScan = "<__NSMallocBlock__: 0x281d4bf80>";
    faceDetect = "<__NSMallocBlock__: 0x281d4bcc0>";
    getDeviceAlipay = "<__NSMallocBlock__: 0x281d4a4c0>";
    getDeviceId = "<__NSMallocBlock__: 0x281d4a800>";
    getDeviceInfo = "<__NSMallocBlock__: 0x281d4a680>";
    getLocation = "<__NSMallocBlock__: 0x281d4a600>";
    getNetworkStatus = "<__NSMallocBlock__: 0x281d4b0c0>";
    getOtherDeviceInfo = "<__NSMallocBlock__: 0x281d4b540>";
    getSMDeviceId = "<__NSMallocBlock__: 0x281d4a2c0>";
    getTripEmail = "<__NSMallocBlock__: 0x281db04c0>";
    getUserInfo = "<__NSMallocBlock__: 0x281d4a540>";
    goToKF = "<__NSMallocBlock__: 0x281d4a340>";
    goToVideoPlayer = "<__NSMallocBlock__: 0x281d4a700>";
    hideLoadingDialog = "<__NSMallocBlock__: 0x281d4b3c0>";
    jdPayHandle = "<__NSMallocBlock__: 0x281d4b900>";
    jumpToMiniPro = "<__NSMallocBlock__: 0x281d4a380>";
    requestNotificationPermission = "<__NSMallocBlock__: 0x281d4af00>";
    saveImage = "<__NSMallocBlock__: 0x281d4a500>";
    sendMsg = "<__NSMallocBlock__: 0x281d4a5c0>";
    shareOnTheWebviewPage = "<__NSMallocBlock__: 0x281d4a640>";
    shareWxImages = "<__NSMallocBlock__: 0x281d4b4c0>";
    shareWxMinipg = "<__NSMallocBlock__: 0x281d4a580>";
    startAuthoritySetting = "<__NSMallocBlock__: 0x281d4a300>";
    startNetworkSetting = "<__NSMallocBlock__: 0x281d4a7c0>";
    statusBarShare = "<__NSMallocBlock__: 0x281d4ad40>";
    uploadTripEmail = "<__NSMallocBlock__: 0x281d49b40>";
    webviewClose = "<__NSMallocBlock__: 0x281d4a740>";
    webviewGoBack = "<__NSMallocBlock__: 0x281d4a480>";
}

这时候在JS端就可以这么调用:

c 复制代码
WebViewJavascriptBridge.callHandler('getLocation', function(response) {
  console.log(response); 
});

确实能调用起来

3. DSBridge

这个不是很常见

OC部分:

c 复制代码
@implementation JsObject
- (NSString *) nativeMethod:(NSString *) msg
{
    ...
}
@end

DWKWebView* dwebview = [[DWKWebView alloc] initWithFrame:bounds];
[dwebview addJavascriptObject:[[JsObject alloc] init] namespace:nil];

JS部分:

js 复制代码
var dsBridge=require("dsbridge");
var str=dsBridge.call("nativeMethod","arg");

参考:

Medusa Attack: Exploring Security Hazards of {In-App}{QR} Code Scanning[C]//32nd USENIX Security Symposium (USENIX Security 23). 2023: 4607-4624.

相关推荐
谢道韫66642 分钟前
今日总结 2024-12-24
javascript·vue.js·elementui
一朵好运莲43 分钟前
React引入Echart水球图
开发语言·javascript·ecmascript
梦境之冢2 小时前
axios 常见的content-type、responseType有哪些?
前端·javascript·http
racerun2 小时前
vue VueResource & axios
前端·javascript·vue.js
app开发工程师V帅2 小时前
iOS 苹果开发者账号: 查看和添加设备UUID 及设备数量
ios
CodeCreator18182 小时前
iOS AccentColor 和 Color Set
ios
J总裁的小芒果2 小时前
THREE.js 入门(六) 纹理、uv坐标
开发语言·javascript·uv
m0_548514772 小时前
前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
java·前端·javascript
浮游本尊2 小时前
Nginx配置:如何在一个域名下运行两个网站
前端·javascript
新中地GIS开发老师2 小时前
《Vue进阶教程》(12)ref的实现详细教程
前端·javascript·vue.js·arcgis·前端框架·地理信息科学·地信