【iOS安全】Block开发与逆向

1. OC中的Block

1.1 Block的基本概念

  • 在iOS开发中,Block是一种特殊的数据类型,类似于其他编程语言中的匿名函数。它可以封装一段代码,并且能够像普通变量一样传递、存储和执行。Block可以捕获并访问定义它时所在作用域的变量,这种变量捕获机制使得Block在异步编程、回调处理和事件响应等场景中非常有用。

1.2. Block的语法结构

  • Block的语法结构如下:
    ^ 返回值类型 (参数列表) {
        // 代码块内容
    };
    
  • 例如,一个简单的Block,它接收两个整数参数并返回它们的和:
    int (^sumBlock)(int, int) = ^int(int a, int b) {
        return a + b;
    };
    
  • 在这个例子中,sumBlock是一个Block变量,^int(int a, int b)定义了这个Block的返回值类型为int,参数为两个int类型的变量ab{ return a + b; }是Block内部的代码,用于计算并返回ab的和。

1.3. Block在异步编程中的应用(以网络请求为例)

  • 在iOS开发中,进行网络请求时,通常会使用异步操作,因为网络请求可能需要花费一些时间才能完成。Block可以作为回调函数来处理网络请求的结果。
  • 例如,使用NSURLSession进行网络请求:
    NSURLSession *session = [NSURLSession sharedSession];
    NSURL *url = [NSURL URLWithString:@"https://example.com/api/data"];
    NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (!error) {
            // 解析数据并更新UI等操作
            NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"请求成功,结果: %@", result);
        } else {
            NSLog(@"请求失败,错误: %@", error);
        }
    }];
    [task resume];
    
  • 在这个例子中,completionHandler是一个Block,它作为参数传递给dataTaskWithURL:completionHandler:方法。当网络请求完成时,这个Block会被调用。Block内部可以访问data(请求返回的数据)、response(响应信息)和error(错误信息),并根据这些信息进行相应的处理,如解析数据、更新用户界面(UI)等操作。

1.4. Block在事件处理中的应用(以按钮点击为例)

  • 当处理用户界面(UI)中的按钮点击事件时,Block也非常有用。例如,使用UIButtonaddTarget:action:forControlEvents:方法来添加按钮点击事件的处理。
  • 假设在一个视图控制器中有一个按钮,当点击按钮时,要执行一段特定的代码,可以使用Block来实现简洁的事件处理:
    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [button setTitle:@"点击我" forState:UIControlStateNormal];
    [button addTarget:self action:^(UIButton *sender) {
        NSLog(@"按钮被点击了");
    } forControlEvents:UIControlEventTouchUpInside];
    
  • 在这个例子中,addTarget:action:forControlEvents:方法的action参数是一个Block。当按钮被点击(UIControlEventTouchUpInside事件发生)时,这个Block会被执行,在Block内部可以编写需要执行的代码,如在这里只是简单地打印一条消息表示按钮被点击。这种方式相比于传统的@selector(选择器)方法更加直观和灵活,特别是在处理简单的事件响应时,可以减少代码的复杂性。

1.5. Block在排序和遍历中的应用(以数组排序为例)

  • 在对数组进行排序时,NSArrayNSMutableArray提供了可以接受Block的排序方法。
  • 例如,有一个包含整数的数组,要按照数字大小进行排序:
    NSArray *numbers = @[@3, @1, @4, @1, @5, @9, @2, @6, @5, @3, @5];
    NSArray *sortedNumbers = [numbers sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        NSInteger num1 = [obj1 integerValue];
        NSInteger num2 = [obj2 integerValue];
        if (num1 < num2) {
            return NSComparisonResultLessThan;
        } else if (num1 > num2) {
            return NSComparisonResultGreaterThan;
        } else {
            return NSComparisonResultSame;
        }
    }];
    NSLog(@"排序后的数组: %@", sortedNumbers);
    
  • 在这个例子中,sortedArrayUsingComparator:方法接受一个Block作为参数。这个Block用于定义两个元素(obj1obj2)的比较规则。通过比较两个元素对应的整数值,返回NSComparisonResultLessThanNSComparisonResultGreaterThanNSComparisonResultSame来确定元素的顺序,从而实现数组的排序。这种方式允许开发者根据自己的需求灵活地定义排序规则,而不是局限于固定的排序方式。

2. Block逆向分析

转载自:https://blog.imjun.net/posts/restore-symbol-of-iOS-app/
因为这篇博客介绍的十分清楚、简洁,所以直接摘录其内容

2.1 Block在内存中的结构

block在内存中是以一个结构体的形式存在的,大致的结构如下:

struct __block_impl {
  /**
  block在内存中也是类NSObject的结构体,
  结构体开始位置是一个isa指针
  */
  Class isa;
  
  /** 这两个变量暂时不关心 */
  int flags;
  int reserved;
  
  /**
  真正的函数指针!!
  */
  void (*invoke)(...);
  ...
}

block中的isa指针,根据实际情况会有三种不同的取值,来表示不同类型的block:

  1. _NSConcreteStackBlock
    栈上的block,一般block创建时是在栈上分配了一个block结构体的空间,然后对其中的isa等变量赋值。

  2. _NSConcreteMallocBlock
    堆上的block,当block被加入到GCD或者被对象持有时,将栈上的block复制到堆上,此时复制得到的block类型变为了_NSConcreteMallocBlock。

  3. _NSConcreteGlobalBlock
    全局静态的block,当block不依赖于上下文环境,比如不持有block外的变量、只使用block内部的变量的时候,block的内存分配可以在编译期就完成,分配在全局的静态常量区。

第2种block在运行时才会出现,我们只关注1、3两种,下面就分析这两种isa指针和block符号地址之间的关联。

2.2 Block的isa指针

分析这部分需要用到IDA

1._NSConcreteStackBlock
假设我们的源代码是这样很简单的一个block:
在这里插入图片描述
编译完后,实际的汇编长这个样子:
在这里插入图片描述
实际运行时,block的构造过程是这样:

  1. 为block开辟栈空间
  2. 为block的isa指针赋值(一定会引用全局变量:_NSConcreteStackBlock)
  3. 获取函数地址,赋值给函数指针

所以我们可以整理出这样一个特征:

重点来了!!!
凡是代码里用到了栈上的block,一定会获取__NSConcreteStackBlock作为isa指针,同时会紧接着获取一个函数地址,那个函数地址就是block的函数地址。

结合下面这个图,仔细理解上面这句话
(这张图和上面那张图是同一个文件,不过裁掉了符号表)
在这里插入图片描述

利用这个特征,逆向分析时我们可以做如下推断:

在一个OC方法里发现引用了__NSConcreteStackBlock这个变量,那么在这附近,一定会出现一个函数地址,这个函数地址就是这个OC方法里的一个block。

比如上面图中,我们发现 viewDidLoad 里,引用了__NSConcreteStackBlock,同时紧接着加载了 sub_100049D4 的函数地址,那我们就可以认定sub_100049D4是viewDidLoad里的一个block, sub_100049D4函数的符号名应该是 viewDidLoad_block.

2. _NSConcreteGlobalBlock

全局的静态block,是那种不引用block外变量的block,他因为不引用外部变量,所以他可以在编译期就进行内存分配操作,也不用担心block的复制等等操作,他存在于可执行文件的常量区里。

比如,我们把源代码改成这样:

@implementation ViewController
 1. (void)viewDidLoad {
   
    void (^ foo)() = ^(){
        //block 不引用外部的变量
        NSLog(@"%d", 123);
    };
    foo();
}
@end

那么在编译后会变成这样:
在这里插入图片描述
那么借鉴上面的思路,在逆向分析的时候,我们可以这么推断

  1. 在静态常量区发现一个_NSConcreteGlobalBlock的引用
  2. 这个地方必然存在一个block的结构体数据
  3. 在这个结构体第16个字节的地方会出现一个值,这个值是一个block的函数地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/942631.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C# 中的记录类型简介 【代码之美系列】

&#x1f380;&#x1f380;&#x1f380;代码之美系列目录&#x1f380;&#x1f380;&#x1f380; 一、C# 命名规则规范 二、C# 代码约定规范 三、C# 参数类型约束 四、浅析 B/S 应用程序体系结构原则 五、浅析 C# Async 和 Await 六、浅析 ASP.NET Core SignalR 双工通信 …

查询 MySQL 默认的存储引擎(SELECT @@default_storage_engine;)

要查询 MySQL 默认的存储引擎&#xff0c;可以使用以下 SQL 查询语句&#xff1a; SELECT default_storage_engine;解释&#xff1a; SELECT: 表示你要执行一个查询。default_storage_engine: 这是一个 MySQL 系统变量&#xff0c;它存储着当前 MySQL 服务器的默认存储引擎。…

大数据技术-Hadoop(二)HDFS的介绍与使用

目录 1、HDFS简介 1.1 什么是HDFS 1.2 HDFS的优点 1.3、HDFS的架构 1.3.1、 NameNode 1.3.2、 NameNode的职责 1.3.3、DataNode 1.3.4、 DataNode的职责 1.3.5、Secondary NameNode 1.3.6、Secondary NameNode的职责 2、HDFS的工作原理 2.1、文件存储 2.2 、数据写…

SpringBoot项目的5种搭建方式(以idea2017为例)

目录 1. idea中使用官方API 2. idea中使用阿里云API 3. 在spring官网创建 4. 在阿里云官网创建 5. Maven项目改造成springboot项目 SpringBoot项目的创建细分一共有5种&#xff0c;其实主要分为以下三种&#xff1a; ①使用开发工具idea创建springboot项目&#xff08; Sp…

Android 设置铃声和闹钟

Android设置铃声和闹钟使用的方法是一样的&#xff0c;但是要区别的去获取对应的权限。 统一权限&#xff0c;不管是设置闹钟还是铃声&#xff0c;他们都需要一个系统设置权限如下: //高版本需要WRITE_SETTINGS权限//此权限是敏感权限&#xff0c;无法动态申请&#xff0c;需要…

三维扫描在汽车/航空行业应用

三维扫描技术应用范围广泛&#xff0c;从小型精密零件到大型工业设备&#xff0c;都能实现快速、准确的测量。 通过先进三维扫描技术获取产品和物体的形面三维数据&#xff0c;建立实物的三维图档&#xff0c;满足各种实物3D模型数据获取、三维数字化展示、3D多媒体开发、三维…

optuna和 lightgbm

文章目录 optuna使用1.导入相关包2.定义模型可选参数3.定义训练代码和评估代码4.定义目标函数5.运行程序6.可视化7.超参数的重要性8.查看相关信息9.可视化的一个完整示例10.lightgbm实验 optuna使用 1.导入相关包 import torch import torch.nn as nn import torch.nn.functi…

【Yonghong 企业日常问题 06】上传的文件不在白名单,修改allow.jar.digest属性添加允许上传的文件SH256值?

文章目录 前言问题描述问题分析问题解决1.允许所有用户上传驱动文件2.如果是想只上传白名单的驱动 前言 该方法适合永洪BI系列产品&#xff0c;包括不限于vividime desktop&#xff0c;vividime z-suit&#xff0c;vividime x-suit产品。 问题描述 当我们连接数据源的时候&a…

[项目][boost搜索引擎#4] cpp-httplib使用 log.hpp 前端 测试及总结

目录 编写http_server模块 1. 引入cpp-httplib到项目中 2. cpp-httplib的使用介绍 3. 正式编写http_server 九、添加日志到项目中 十、编写前端模块 十一. 详解传 gitee 十二、项目总结 项目的扩展 写在前面 [项目详解][boost搜索引擎#1] 概述 | 去标签 | 数据清洗 |…

项目练习:若依系统的svg-icon功能实现

文章目录 一、svg图片准备二、自定义Svg组件三、svg插件开发四、Svg组件使用 一、svg图片准备 src/assets/icons/svg 其中svg目录里&#xff0c;存放了所需要的图片 index.js import Vue from vue import SvgIcon from /components/SvgIcon// svg component// register glob…

水库大坝三维模型的开发和使用3Dmax篇

成果图 开发过程 工具插件three.js先加载模型做水体衔接水位测量标尺水位标记断面标记大坝监测点打点 上代码&#xff0c;技术交流V: bloxed <template><div class"box w100 h100"><el-row :gutter"20" v-loading"loading"e…

Win10提示“缺少fbgemm.dll”怎么办?缺失fbgemm.dll文件的修复方法来啦!

fbgemm.dll文件的作用 fbgemm.dll&#xff08;Facebook GEMM library&#xff09;是一个动态链接库文件&#xff0c;它主要用于优化矩阵乘法运算&#xff0c;提高计算性能。虽然它不是Windows 10系统的核心组件&#xff0c;但在某些应用程序或游戏中&#xff0c;尤其是那些需要…

Petalinux使用QSPI FLASH引导启动

目录 1. 预分配Flash空间 1.1 大小估计 1.2 其他注意事项 2. 配置Flash分区 3. 配置各主要文件在Flash中的地址范围 4. 配置boot.scr的偏移 5. 修改U-Boot环境变量在Flash的偏移量 6. 配置设备树中的Flash 7. 开启对EXT4分区管理的支持(根据需要) 8. 编译u-boot 9.…

Android——自定义按钮button

项目中经常高频使用按钮&#xff0c;要求&#xff1a;可设置颜色&#xff0c;有圆角且有按下效果的Button 一、自定义按钮button button的代码为 package com.fslihua.clickeffectimport android.annotation.SuppressLint import android.content.Context import android.gra…

黑龙江等保测评费用怎么收?

‌黑龙江二级等保测评费用‌&#xff1a;费用区间大致在3万至6万人民币之间&#xff0c;具体费用取决于测评机构的定价策略、所提供的服务内容以及企业的实际需求‌&#xff0c;服务内容包括防火墙、Web应用防火墙(WAF)、堡垒机、日志审计、漏洞扫描以及等保安全整改等‌。 ‌…

中文拼写检测纠正 Read, Listen, and See Leveraging Multimodal Information 论文

拼写纠正系列 NLP 中文拼写检测实现思路 NLP 中文拼写检测纠正算法整理 NLP 英文拼写算法&#xff0c;如果提升 100W 倍的性能&#xff1f; NLP 中文拼写检测纠正 Paper java 实现中英文拼写检查和错误纠正&#xff1f;可我只会写 CRUD 啊&#xff01; 一个提升英文单词拼…

vue2 elementui if导致的rules判断失效

优化目标 和 目标转化出价必填的 切换的时候还会隐藏掉 这时候的if语句会导致rules判断失效 我的办法是把判断拉到外面 别放在el-form-item里 <section v-if"unitForm.baseTarget OCPM && unitForm.cpaTargetOptions ! undefined && unitForm.cpaTa…

前端(Ajax)

1.客户端请求 向https://jsonplaceholder.typicode.com/users发送get请求 const xhr new XMLHttpRequest(); console.log(xhr.readyState); xhr.open(‘get’, ‘https://jsonplaceholder.typicode.com/users’) console.log(xhr.readyState); xhr.send(); console.log(xhr.…

uboot, s5pv210 , main_loop 分析(16)

main_loop 的代码如下&#xff1a; 4443 void main_loop (void)42 {41 #ifndef CONFIG_SYS_HUSH_PARSER E 40 ▎ static char lastcommand[CONFIG_SYS_CBSIZE] { 0, }; ■ Use of undeclared identifier CONFIG_SYS_CBSIZE39 ▎ int len;38 ▎ int rc 1;37 ▎ …

信号强劲,通信清晰:北斗三号多模对讲机TD70——专业通信解决方案

在边防海防等国家安全的关键领域&#xff0c;通信的稳定性和可靠性关乎着任务的成败和战士们的安全。北斗三号多模对讲机TD70&#xff0c;凭借其卓越的性能和全面的功能&#xff0c;成为了边防海防通信的利器&#xff0c;守护着国家安全的前沿哨兵。 一、三网融合&#xff0c;…