Giter VIP home page Giter VIP logo

Comments (7)

yulingtianxia avatar yulingtianxia commented on July 19, 2024 15

其实触发方法转发走 forwardInvocation、替换 isa 指针、对象级别 Hook 等等这些都是老生常谈的Hook 技术,很多组件都基于这套方案来 Hook,在长时间使用后也暴露了很多已知的缺陷。我之前写的节流限频组件也是用到了这些技术,文章大部分都是介绍 Aspects 没有处理好的场景:
http://yulingtianxia.com/blog/2018/07/31/MessageThrottle-Safety/

不过凡是基于方法转发的 Hook 方案都有一个无法解决的致命问题,就是父子类都 Hook 了同一个方法,然后子类调用父类 super 的时候会死循环。这也是为何这个方案在多年之后 Aspects 的作者终于声明它不再适用于生产环境。

而此问题需要吴子奇基于桥的 Hook 在汇编层面来解决。

想问下除了原理基本相同,API 略有不同之外,有没有解决 Aspects 相关技术带来的这些通病呢?

from sdmagichook.

623637646 avatar 623637646 commented on July 19, 2024 2

Hi @yulingtianxia

父子类都 Hook 了同一个方法,然后子类调用父类 super 的时候会死循环

关于这个问题,我相信 https://github.com/623637646/SwiftHook 很好的解决了这个问题。

from sdmagichook.

gsdios avatar gsdios commented on July 19, 2024 1

兼容系统KVO已经实现,欢迎更新&反馈

from sdmagichook.

gsdios avatar gsdios commented on July 19, 2024

在开源这份代码之前我并未了解和使用过aspect,发表完https://mp.weixin.qq.com/s/wxigL1Clem1dR8Nkt8LLMw 这篇技术文章之后看到有些留言提到了aspect然后我去github大概看了一下基本思路都是基于类似kvo的isa替换,但是从api设计以及实现上也有明确的区别。具体区别或者异同我最近先研究下aspect源码,随后会给出答案。

from sdmagichook.

Assuner-Lee avatar Assuner-Lee commented on July 19, 2024

以及

还包括了统一hook时替换imp为objc_msgForward,hook forwardInvocation: 这种细节;

from sdmagichook.

gsdios avatar gsdios commented on July 19, 2024

在开源这份代码之前我并未了解和使用过aspects,发表完https://mp.weixin.qq.com/s/wxigL1Clem1dR8Nkt8LLMw 这篇技术文章之后看到有些留言提到了aspects然后我去github大概看了一下基本思路都是基于类似kvo的isa替换,但是从api设计以及实现上也有明确的区别,我们通过以下示例简要介绍下:

假设有这样一个自定义类Test,在其内部定义了一个求和的方法,接收四个int类型的参数。

@implementation Test

- (int)sumWithA:(int)a b:(int)b c:(int)c d:(int)d {
    return a + b + c + d;
}

@end

现在要求将四个参数分别平方然后再求和。

使用aspects实现如下:

    Test *testObj = [Test new];
    [testObj aspect_hookSelector:@selector(sumWithA:b:c:d:) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo> info, int a, int b, int c, int d) {
        int aa = a * a;
        int bb = b * b;
        int cc = c * c;
        int dd = d * d;
        [info.originalInvocation setArgument:&aa atIndex:2];
        [info.originalInvocation setArgument:&bb atIndex:3];
        [info.originalInvocation setArgument:&cc atIndex:4];
        [info.originalInvocation setArgument:&dd atIndex:5];
    } error:NULL];

    int sum = [testObj sumWithA:1 b:2 c:3 d:4];
    NSLog(@">>>> %d", sum); // >>>> 30

使用SDMagicHook实现如下:

    Test *testObj = [Test new];
    [testObj hookMethod:@selector(sumWithA:b:c:d:) impBlock:^(typeof(testObj) this, int a, int b, int c, int d) {
        __block int res;
        [this callOriginalMethodInBlock:^{
            res = [this sumWithA:a * a b:b * b c:c * c d:d * d];
        }];
        return res;
    }];

    int sum = [testObj sumWithA:1 b:2 c:3 d:4];
    NSLog(@">>>> %d", sum); // >>>> 30

由以上demo可以看出:
1.aspects使用AspectOptions来决定自定义方法和原始方法的执行顺序;SDMagicHook使用callOriginalMethodInBlock来调用原始方法,可以将原始方法放在自定义逻辑的前、中、后任意位置执行,更加灵活方便。

2.aspects将原始方法封装在NSInvocation里面,如果想要修改sumWithA:b:c:d:的参数值需要调用setArgument:atIndex:方法来实现,api不够简洁友好;SDMagicHook只需在callOriginalMethodInBlock的block参数内部直接调用原始的sumWithA:b:c:d:方法传参即可,直观简便。

from sdmagichook.

gsdios avatar gsdios commented on July 19, 2024

其实触发方法转发走 forwardInvocation、替换 isa 指针、对象级别 Hook 等等这些都是老生常谈的Hook 技术,很多组件都基于这套方案来 Hook,在长时间使用后也暴露了很多已知的缺陷。我之前写的节流限频组件也是用到了这些技术,文章大部分都是介绍 Aspects 没有处理好的场景:
http://yulingtianxia.com/blog/2018/07/31/MessageThrottle-Safety/

不过凡是基于方法转发的 Hook 方案都有一个无法解决的致命问题,就是父子类都 Hook 了同一个方法,然后子类调用父类 super 的时候会死循环。这也是为何这个方案在多年之后 Aspects 的作者终于声明它不再适用于生产环境。

而此问题需要吴子奇基于桥的 Hook 在汇编层面来解决。

想问下除了原理基本相同,API 略有不同之外,有没有解决 Aspects 相关技术带来的这些通病呢?

关于你提到的第一个问题:
“父子类都 Hook 了同一个方法,然后子类调用父类 super 的时候会死循环”应该是在所有同一类型的对象共享同一个类kvo类指针造成的问题。SDMagicHook是每个对象单独享有一个自定义的新类,对象之间相互隔离互不影响。也就是说假如有这样一个继承关系A->B->C,现在C类有个实例c1(0xa0),B类有个实例b1(0xb0),c1和b1都hook了自己的test方法,那么会生成两个新类SDC_0xa0和SDB_0xb0,其继承关系如下A->B->C->SDC_0xa0、A->B->SDB_0xb0,具体的hook操作发生在SDC_0xa0和SDB_0xb0这两个新类上,原始的A类和B类不受任何影响SDC_0xa0和SDB_0xb0之间也相互隔离所以避开了你提到的这个问题。

关于你提到的Aspects本身遇到但是尚未解决的问题:在aspects的readme中看到了他们介绍到有“KVO works if observers are created after your calls aspect_hookSelector: It most likely will crash the other way around. Still looking for workarounds here - any help appreciated.”这样一个问题。SDMagicHook测试了一下同样遇到了,但是我们已经有了相关解决方案,大概会在下周一前后同步到github上。

还有其他问题的话欢迎持续交流反馈 @yulingtianxia

from sdmagichook.

Related Issues (14)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.