iOS开发-hook之Method Swizzle更改原有方法实现流程

iOS开发-hook之Method Swizzle更改原有方法实现流程

一 Hook是什么?

Hook 简介

Hook,中文译为“挂钩”或“钩子”。通过hook可以让别人的程序执行自己所写的代码。

一段程序的执行流程是 A -> B -> C,现在我们在 A 和 B 之间插入一段代码或者直接改变 B ,这样程序原有的执行流程就发生了改变。如下图所示:

Hook的方式:

    • Method Swizzle
    • fishhook
    • Cydia Substrate

Hook实现方式:利用Objective-C的Runtime(运行时)特性,动态去改变SEL(方法编号)和IMP(方法实现)的对应关系,达到Objective-C方法调用流程改变的目的主要用于Objective-C方法。

Hook中主要用到的方法(参数: Class、SEL、IMP、Method):

  • method_exchangeImplementations
  • class_replaceMethod
  • method_setImplementation
  • class_getMethodImplementation

二、Class与Method Swizzle

Class 一个 objc_class 类型的结构体指针,用于说明对象是哪个类;

Method 一个 objc_method 类型的结构体指针,用于定义一个方法,在objc源码中定义如下:

struct objc_method { SEL _Nonnull method_name OBJC2_UNAVAILABLE; char * _Nullable method_types OBJC2_UNAVAILABLE; IMP _Nonnull method_imp OBJC2_UNAVAILABLE; } OBJC2_UNAVAILABLE;

SEL 可以发现在 Method 的定义中,也能看见SEL。在苹果官方文档中定义这种类型:

typedef struct objc_selector *SEL;

IMP 同样在 Method 的定义中也能看到,在苹果官方文档的定义如下:

id (IMP *)(id, SEL, ...)

SEL是一个C String,用于表示一个方法的名称,IMP是一个方法实现首地址,默认有两个参数 self 和 _cmd。其实SEL和IMP的关系可以类比一本书的目录,SEL就是目录中的内容标题,IMP是后面的页码。一个方法调用时,通过SEL找到对应的IMP,进而找到方法的实现。如下图:

在Hook一个Objective-C方法时,只需要改变其SEL所指向的IMP时,就可以实现方法的交换的目的,或者使用class_replaceMethod 和 method_setImplementation 改变一个类原有方法的实现。

逆向中,Hook一个Objective-C方法其实就是改变其SEL所指向的IMP,从而找到另一个实现地址,执行另一个方法实现。但这种方法的局限在于,其只能针对Objective-C方法进行Hook,对于C函数则无法Hook。

三、使用inline函数

使用inline快速实现在执行系统方法时候执行我们的代码

通过class_replaceMethod与method_exchangeImplementations实现。

#ifndef SSDSwizzlingDefine_h
#define SSDSwizzlingDefine_h#import <objc/Runtime(运行时).h>
static inline void swizzling_exchangeMethod(Class clazz ,SEL originalSelector, SEL swizzledSelector){Method originalMethod = class_getInstanceMethod(clazz, originalSelector);Method swizzledMethod = class_getInstanceMethod(clazz, swizzledSelector);BOOL success = class_addMethod(clazz, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));if (success) {class_replaceMethod(clazz, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));} else {method_exchangeImplementations(originalMethod, swizzledMethod);}
}#endif /* SSDSwizzlingDefine_h */

四、使用swizzling_exchangeMethod函数

通过swizzling_exchangeMethod替换系统方法,如下

@implementation UINavigationBar (SSDSwizzling)+ (void)load{static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{swizzling_exchangeMethod([UINavigationBar class] ,@selector(layoutSubviews), @selector(swizzling_layoutSubviews));});
}

该代码扩展UINavigationBar,在load更改方法顺序swizzling_layoutSubviews -> layoutSubviews

#import "UINavigationBar+SSDSwizzling.h"
#import "SSDSwizzlingDefine.h"@implementation UINavigationBar (SSDSwizzling)+ (void)load{static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{swizzling_exchangeMethod([UINavigationBar class] ,@selector(layoutSubviews), @selector(swizzling_layoutSubviews));});
}#pragma mark - LayoutSubviews
#define TitleMargin 43- (void)swizzling_layoutSubviews{BOOL isIOS11 = ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 11.0);[self swizzling_layoutSubviews];UINavigationItem *navigationItem = [self topItem];UIView *subview  = [[navigationItem leftBarButtonItem] customView];//CGFloat navigationBtnMargin = isIOS11? -10 : 28;CGFloat navigationBtnMargin = isIOS11? -10 : 15;CGRect subViewFrame = subview.frame;subViewFrame.origin.x = navigationBtnMargin;subview.frame = subViewFrame;//解决标题过长时,设置navigationItem.title导致标题偏移的问题UILabel *label = (UILabel *)navigationItem.titleView;if ([label isKindOfClass:[UILabel class]]){label.lineBreakMode = NSLineBreakByTruncatingMiddle;}UIFont *font   = self.titleTextAttributes[NSFontAttributeName];if (font) {label.font = font;}UIColor *color = self.titleTextAttributes[NSForegroundColorAttributeName];if (label && [label isKindOfClass:[UILabel class]] && color) {label.textColor = color;}[label sizeToFit];[self layoutLabel];
}#pragma mark - Private
- (void)layoutLabel{UINavigationItem *navigationItem = [self topItem];UIView *view = navigationItem.titleView;CGPoint centerPonit = CGPointMake(self.frame.size.width * .5f, self.frame.size.height *.5f);UIView *superView = view.superview;centerPonit = [superView convertPoint:centerPonit fromView:self];view.center = centerPonit;
}@end

五、小结

iOS开发-替换方法class_replaceMethod更改执行方法流程
利用Objective-C的Runtime(运行时)特性,动态去改变SEL(方法编号)和IMP(方法实现)的对应关系,达到Objective-C方法调用流程改变的目的主要用于Objective-C方法。

学习记录,每天不停进步。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一款基于过滤器的线程共享变量的清理机制

项目中常常用到线程共享变量。如多个函数或对象之间传递参数。循环读取缓存或数据库时时用共享变量减少读取次数。某类特殊对象的持有等。一般用finally去强制释放共享变量。但释放时机有时并不能准确的把握。为此&#xff0c;基于过滤器写了个个释放机制。 过滤器如下&#x…

ubuntu22.04 DNSSEC(加密DNS服务) configuration

/etx/systemd/resolved.conf是ubuntu下DNS解析服务配置文件&#xff0c;systemd为ubuntu下system and service配置目录 step 1——修改resolved.conf参数 管理员权限打开 /systemd/resolved.conf sudo nano /etc/systemd/resolved.conf修改如下&#xff1a; # This file i…

vr禁毒毒驾模拟体验从源头拒绝毒品,预防毒品

俗话说&#xff0c;一念天堂&#xff0c;一念地狱。吸毒一口&#xff0c;掉入虎口。吸毒对人体的危害非常大&#xff0c;普通人吸毒会导致家破人亡&#xff0c;明星吸毒会毁掉自己的大好星途。没有感同身受&#xff0c;何来悲喜相通&#xff0c;毒品危害认知VR模拟情景体验是VR…

利用频谱仪进行简单的2.4G 频率测试

一、概述 1. 信号源 我们开发2.4G 无线产品的时候&#xff0c;经常需要对产品的无线信号进行测试&#xff0c;以确定精确的频率。在进行频率测试之前&#xff0c;我们的2.4G 射频芯片需要进入单载波模式。 2. 频谱仪 这里选择的是普源的频谱仪。测试范围是 9kHz - 3.2GHz。…

Jtti:Linux内存管理中的slab缓存怎么实现

在Linux内存管理中&#xff0c;slab缓存是一种高效的内存分配机制&#xff0c;用于管理小型对象的内存分配。slab缓存的实现是通过SLAB分配器来完成的&#xff0c;它在Linux内核中对内存分配进行优化。 SLAB分配器将内存分为三个区域&#xff1a;slab、partial、和empty。 Slab…

hive 全量表、增量表、快照表、切片表和拉链表

全量表&#xff1a;记录每天的所有的最新状态的数据&#xff0c;增量表&#xff1a;记录每天的新增数据&#xff0c;增量数据是上次导出之后的新数据。快照表&#xff1a;按日分区&#xff0c;记录截止数据日期的全量数据切片表&#xff1a;切片表根据基础表&#xff0c;往往只…

Java-day03(程序流程控制)

程序流程控制 1.顺序结构 程序从上至下逐行执行&#xff0c;无判断与跳转 public class Test1{ public static void main(String[] args){int i 1;int j i 1; System.out.println(j);} }2.分支结构 依据条件&#xff0c;选择性执行某段语句 主要有以下两种 2.1 i…

知识图谱实战应用22-数据导入技巧与基于py2neo的金融领域风险评估的应用

大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用22-数据导入技巧与基于py2neo的金融领域风险评估的应用。本文的金融领域风险评估的应用旨在利用知识图谱技术对金融风险进行评估和管理。该项目利用py2neo库与Neo4j图数据库进行交互,构建一个金融领域的知识图谱,并根…

vue 封装一个鼠标拖动选择时间段功能

<template><div class"timeRange"><div class"calendar"><table><thead><tr><th rowspan"6" class"weekRow"><b>周/时间</b></th><th colspan"24"><…

【机器学习】西瓜书习题3.3Python编程实现对数几率回归

参考代码 结合自己的理解&#xff0c;添加注释。 代码 导入相关的库 import numpy as np import pandas as pd import matplotlib from matplotlib import pyplot as plt from sklearn import linear_model导入数据&#xff0c;进行数据处理和特征工程 # 1.数据处理&#x…

Linux 学习记录60(ARM篇)

Linux 学习记录60(ARM篇) 本文目录 Linux 学习记录60(ARM篇)一、SPI总线1. 概念2. 硬件连接 二、SPI总线协议三、SPI总线通信模式四、对比IIC总线和SPI总线1. 相同点2. 不同点 思维导图 一、SPI总线 1. 概念 1、SPI总结是Motorola首先提出的全双工三线/四线同步串行总线 2、采…

Rust- 模块

&#xff08;1&#xff09;在项目根目录下创建mylib&#xff08;里面实现自定义的外部模块&#xff09; cargo new --lib mylib &#xff08;2&#xff09;在 项目名\mylib\src\lib.rs文件中实现新模块 pub mod add_salary {pub fn study(name: String) {println!("Rust…

WEB浏览器轻松读写NDEF智能海报、地图坐标、文本标签信息

本示例使用的发卡器&#xff1a;Android Linux RFID读写器NFC发卡器WEB可编程NDEF文本/智能海报/-淘宝网 (taobao.com) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&…

Python状态模式介绍、使用

一、Python状态模式介绍 Python状态模式&#xff08;State Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许对象在不同的状态下表现不同的行为&#xff0c;从而避免在代码中使用多重条件语句。该模式将状态封装在独立的对象中&#xff0c;并根据当前状态选择不同的…

flutter开发实战-图片保存到相册

flutter开发实战-图片保存到相册。保存相册使用的是image_gallery_saver插件 一、引入image_gallery_saver插件 在pubspec.yaml中引入插件 # 保存图片到相册image_gallery_saver: ^1.7.1# 权限permission_handler: ^10.0.0二、保存到相册的代码 使用image_gallery_saver将图…

使用pikachu管理工具下的XSS后台进行实战

写在前面的重要提示&#xff1a; Attention&#xff1a;技术没有好坏之分&#xff0c;关键在于使用技术的人或组织。网络安全技术是一把双刃剑 – 作为网络安全人&#xff0c;虽然无法控制头上的帽子是否会变绿&#xff0c;但能控制不让它变黑&#xff1b;无论我们在物质上面对…

redis主从复制哨兵Cluster

目录 前言 一、模式介绍 1.1 主从复制 1.2 哨兵 1.3 集群 二、主从复制 2.1 主从复制的作用 2.2 主从复制流程 2.3 搭建Redis 主从复制 三、Redis 哨兵模式 3.1 哨兵模式原理 3.2 哨兵模式的作用 3.3 哨兵组成结构 3.4 哨兵故障转移机制 3.5 搭建Redis 哨兵模式…

史上最全react面试题

react面试题 react生命周期面试题1.react 生命周期函数2.react生命周期中&#xff0c;最适合与服务端进行数据交互的是哪个函数3.运行阶段生命周期调用顺序4.shouldComponentUpdate 是做什么的&#xff0c;&#xff08;react 性能优化是哪个周期函数&#xff1f;&#xff09;5.…

..\obj\project.assets.json”。运行 NuGet 包还原以生成此文件。

问题 有时拉取一个新的项目后出现&#xff0c;如标题中的问题&#xff0c;不管用的是Vs 还是Rider都有可能出现&#xff1b;当使用IDE的自动还原生成相关文件时&#xff0c;没有效果&#xff0c;一般第一次打开项目时IDE是会自动生成的。 解决办法 dotnet msbuild -t:restor…

科技项目验收测试:验证软件产品功能与性能的有效手段

科技项目验收测试是验证软件产品功能与性能的重要手段&#xff0c;在项目开发中起到了至关重要的作用。本文将从产品质量、需求验证、性能测试等方面&#xff0c;探讨科技项目验收测试的有效手段。 1、产品质量保证是验收测试的核心 科技项目验收测试的核心目标是验证软件产品…