飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2590|回复: 4

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

[复制链接]
  • TA的每日心情
    无聊
    2021-11-11 13:50
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2023-10-25 09:10:29 | 显示全部楼层 |阅读模式
    前言
    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
    界面效果图:
    url的部分html代码如下:



    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];
    }


    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#')";
    &#8203;
    [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后的相关处理办法,希望能对你有所帮助。

    PYG19周年生日快乐!
  • TA的每日心情
    奋斗
    前天 10:19
  • 签到天数: 1385 天

    [LV.10]以坛为家III

    发表于 2023-10-25 15:43:01 | 显示全部楼层
    支持支持一波。优秀。
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    1 小时前
  • 签到天数: 319 天

    [LV.8]以坛为家I

    发表于 2023-10-25 20:51:41 | 显示全部楼层
    十分感谢,又学习一波~
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    1 小时前
  • 签到天数: 1080 天

    [LV.10]以坛为家III

    发表于 2023-10-26 08:33:41 | 显示全部楼层
    PYG有你更精彩!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表