写点什么

【iOS 逆向与安全】原生程序与 WebView 交互

作者:小陈
  • 2023-10-25
    四川
  • 本文字数:2993 字

    阅读完需:约 10 分钟

前言

WKWebView 是 iOS 应用中强大的组件,但如何在逆向工程中最好地利用它呢?本文将带您了解在逆向过程中遇到 webview 后的相关操作。这些技术将让您能够修改 WKWebView 行为,读写关键元素,接口拦截,并揭示更多有趣的可能性。



一、目标

了解如何在 iOS 逆向工程中处理 WKWebView,包括 元素读写和接口拦截的基本概念。

二、开发环境和工具清单

  • mac 系统

  • Xcode13.2.1

  • iOS15 设备

三、流程

1、示例程序

手动创建一个示例程序,里面只包含了一个基本的 webview 容器,呈现的内容为某 app 的滑块 url,基础代码如下:


@interface ViewController ()
@property (nonatomic, strong) WKWebView *webview;
@end
@implementation ViewController
- (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.webview]; NSURL *url = [NSURL URLWithString:@"https://xxx/xxx"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [self.webview loadRequest:request];}
- (WKWebView *)webview { if (_webview == nil) { _webview = [[WKWebView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; } return _webview;}
@end
复制代码


界面效果图:


<img src="https://nas.witchan.com:5802/index.php/s/MaGjtiSoE3BzM3S/preview" alt="image-20231024184810472"/>


url 的部分 html 代码如下:


<img src="https://nas.witchan.com:5802/index.php/s/d4xY6zf7ECN8ss3/preview" alt="image-20231024170506779"/>

2、拦截并修改 html

由于 h5 里内容被包含在一个自定义标签里(shadow-root),而这自定义标签的模式为 closed。我们需要拦截并把该标签的模式改为 open,这样才能通过 css 选择器去获取对应的子元素。通过全局搜索发现自定义标签于 xxx.js 返回。直接上代码:


a、修改 webview 的初始化代码如下:


// 修复'https' is a URL scheme that WKWebView handles natively错误Method m1 = class_getClassMethod([WKWebView class], @selector(handlesURLScheme:));Method m2 = class_getClassMethod([ViewController class], @selector(hook_handlesURLScheme:));method_exchangeImplementations(m1, m2);        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];        // 设置当前对象来处理webview的https请求[config setURLSchemeHandler:self forURLScheme:@"https"];        _webview = [[WKWebView alloc] initWithFrame:[[UIScreen mainScreen] bounds] configuration:config];
复制代码


b、实现处理 https 请求的协议:


- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask {    NSURLRequest *request = urlSchemeTask.request;    NSString *urlStr = request.URL.absoluteString;        NSLog(@"req url =%@=", urlStr);    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {        if (error) {            [urlSchemeTask didFailWithError:error];        } else {            if ([urlStr containsString:@"xxx.js"]) {                // 获取xxx.js的内容                NSString *modifyData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];                                // 查询attachShadow({mode:\"closed\"})并替换为attachShadow({mode:\"open\"})                modifyData = [modifyData stringByReplacingOccurrencesOfString:@"attachShadow({mode:\"closed\"})" withString:@"attachShadow({mode:\"open\"})"];                                // 覆盖xxx.js内容                data = [modifyData dataUsingEncoding:NSUTF8StringEncoding];            }                        // 设置当前请求的返回信息            [urlSchemeTask didReceiveResponse:response];            [urlSchemeTask didReceiveData:data];            [urlSchemeTask didFinish];        }    }] resume];}
复制代码


<img src="https://nas.witchan.com:5802/index.php/s/qbn5SdMFSNHp8wE/preview" alt="image-20231024175142364" />


<img src="https://nas.witchan.com:5802/index.php/s/CyKdb3xa3zzSGDC/preview" alt="image-20231024174910942" />

2、修改 html 元素

修改按钮文案"拖动滑块完成上方拼图"为"移动端小陈",修改 html 元素和修改 js 基本上一样,关键代码如下:


NSString *modifyData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];if ([modifyData containsString:@"拖动滑块完成上方拼图"]) {    modifyData = [modifyData stringByReplacingOccurrencesOfString:@"拖动滑块完成上方拼图" withString:@"移动端小陈"];    // 替换html内容    data = [modifyData dataUsingEncoding:NSUTF8StringEncoding];}
复制代码

3、获取 img 标签的值

简单的内容可通过查找替换处理。而复制的内容,还得用 css 选择器。咱们通过在 webview 中执行一段 js 来获取特定元素(注:获取到的结果只能是 string 类型),获取 img 标签的关键代码如下:


NSString *jsFunc = @"\function getImgSrc(clsName) {\var sliderImg = document.querySelector('#captcha-dialog').children[1].shadowRoot.querySelector('#slider').getElementsByClassName(clsName);\if (sliderImg.length > 0) {\  var imgSrc = sliderImg[0].src;\  return imgSrc;\} else {\  return "";\}\};getImgSrc('#cls-name#')";
[webView evaluateJavaScript:[jsFunc stringByReplacingOccurrencesOfString:@"#cls-name#" withString:@"slider-img-bg"] completionHandler:^(NSString *backgroundData , NSError *error) { NSLog(@"background =%@=", backgroundData);}];
复制代码

4、接口拦截

修改某接口的请求参数,代码如下:


   // 修改接口的请求    if ([urlStr containsString:@"xxx"]) {        NSMutableDictionary *body = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil];        body = [body mutableCopy];        body[@"e"] = @(0);        NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:request.URL.absoluteURL                                                                      cachePolicy:NSURLRequestUseProtocolCachePolicy                                                                  timeoutInterval:10.0];        mutableRequest.HTTPMethod = @"POST";        mutableRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;        mutableRequest.HTTPBody = [NSJSONSerialization dataWithJSONObject:body options:0 error:nil];        request = mutableRequest;    }
复制代码


修改某接口的响应和上边的修改 js 类型,大家自行尝试



总结

以上就是在逆向中遇到 webview 后的相关处理办法,希望能对你有所帮助。


源码请关住工众好后回复:webview 源码


提示:阅读此文档的过程中遇到任何问题,请关住工众好【移动端Android和iOS开发技术分享】或+99 君羊【812546729




发布于: 刚刚阅读数: 3
用户头像

小陈

关注

和昨天不一样 2019-03-12 加入

公众号:移动端Android和iOS开发技术分享

评论

发布
暂无评论
【iOS逆向与安全】原生程序与WebView交互_逆向_小陈_InfoQ写作社区