PoC of function hooking in Swift

Related tags

Guides SWRoute
Overview

SWRoute is a tiny Swift wrapper over rd_route(). It allows you to route (hook) quite any function/method with another function/method or even a closure.

This code hasn't been updated since Xcode beta 1, so it may be outdated. Remember, it's just a proof-of-concept of what you can do in Swift.

If you're curious how it works, check out an article „Function hooking in Swift“.

Going to use it in your iOS project? Please, read the corresponding section below.

Exported interface

class SwiftRoute {
    class func replace<MethodT>(function targetMethod : MethodT, with replacement : MethodT) -> Int
}
Arguments
Argument Type (in/out) Description
function in (required) a function/method to override
with in (required) any other function/method or closure to overrride a function with
Return value

KERN_SUCCESS (== 0) upon success, > 0 otherwise.

Example usage

(see SWRouteTests/SWRouteTests.swift for more)

class DemoClass {
    func demoMethod(arg: Int) -> Int {
        return (42 + arg);
    }
}

var err = SwiftRoute.replace(function: DemoClass().demoMethod, with: {
    (arg : Int) -> Int in
        return (90 + arg)
})

SWRoute and iOS

Unfortunately rd_route (the back-end of SWRoute) doesn't work well on iOS (until jailbroken), because it does some tricks with memory pages that aren't allowed there. But you can choose any other library for function hooking instead! I recommend libevil by Landon Fuller.

You'll only need rd_get_func_impl.c source file included into your project to create your version of SWRoute:

// Route functions in Swift using libevil and rd_get_func_impl()
import Darwin

@asmname("_rd_get_func_impl")
    func rd_get_func_impl<Q>(Q) -> UInt64;
@asmname("evil_init")
    func evil_init();
@asmname("evil_override_ptr")
    func evil_override_ptr(UInt64, UInt64, CMutablePointer<UInt64>) -> CInt;

class EvilRoute {
    struct onceToken {
        static var token : dispatch_once_t = 0
    }

    class func replace<MethodT>(function targetMethod : MethodT, with replacement : MethodT) -> Int
    {
        dispatch_once(&onceToken.token, {
            evil_init()
        })

        let err: CInt = evil_override_ptr(rd_get_func_impl(DemoClass().demoMethod),
                                          rd_get_func_impl(someFunction),
                                          nil)

        return Int(err)
    }
}

License

WTFPL.

//  Copyright © 2014 Dmitry Rodionov <[email protected]>
//  This work is free. You can redistribute it and/or modify it under the
//  terms of the Do What The Fuck You Want To Public License, Version 2,
//  as published by Sam Hocevar. See the COPYING file for more details.

If you found any bug(s) or something, please open an issue or a pull request — I'd appreciate your help! (^,,^)


Dmitry Rodionov, 2014
[email protected]

You might also like...
📖 Design Patterns implemented in Swift 5.0

📖 Design Patterns implemented in Swift 5.0

List of awesome iOS & Swift stuff!!
List of awesome iOS & Swift stuff!!

Awesome iOS Developer Feel free to fork this repository and pull requests!! 🔎 Content Coding Convention Swift Lint Design Pattern Adaptor Delegation

This repo shows how to set up and use GitHub Actions as a CI for Swift Packages
This repo shows how to set up and use GitHub Actions as a CI for Swift Packages

SwiftPackageWithGithubActionsAsCI This repo shows how to set up and use GitHub Actions as a CI for Swift Packages. Available environments on GitHib Li

The first HackingWithSwift project from the 100 Days of Swift series.

StormViwer A gallery to display images included in the app's internal assets folder. This is my first ever swift project and it is a part of the serie

Swift optional desugaring

Swift optional desugaring Setup Make sure you have installed Swift according to the instructions from you earlier assignment. Open a terminal / consol

Mini-application iOS native avec Xcode et Swift exploitant l'architecture MVVM et le framework Combine d'Apple pour la mise en place de la programmation réactive fonctionnelle, le tout avec UIKit.
Mini-application iOS native avec Xcode et Swift exploitant l'architecture MVVM et le framework Combine d'Apple pour la mise en place de la programmation réactive fonctionnelle, le tout avec UIKit.

iOS (Swift 5): Test MVVM avec Combine et UIKit L'architecture MVVM et la programmation réactive fonctionnelle sont très utlisées dans le développement

iOS native app demo with Xcode and Swift using MVVM architecture and Apple's Combine framework for functional reactive programming, all with UIKit
iOS native app demo with Xcode and Swift using MVVM architecture and Apple's Combine framework for functional reactive programming, all with UIKit

iOS (Swift 5): MVVM test with Combine and UIKit MVVM and functional reactive programming (FRP) are very used in iOS development inside companies. Here

A treelist ViewController that implemented with Uikit (swift).
A treelist ViewController that implemented with Uikit (swift).

TreeList ViewController A treelist viewcontroller that implemented with Uikit (swift). Features The sections could be expanded and folded by clicking

USC's ITP342 iOS Development Swift Final Project

READMEBlogs USC's ITP342 iOS Development Swift Final Project NOTE: You'll need to attach your own Firebase to the app LINK TO APP ZIP FILE: https://dr

Comments
  • Routing is unavailable when in Release mode

    Routing is unavailable when in Release mode

    Due to compiler optimizations, some class methods and functions are inlined/removed, so we're unable to get their addresses to route.
    rd_get_func_imp() returns some value for these ones though, but it's invalid and points outside a target memory region.

    bug 
    opened by rodionovd 0
  • Doesn't work with struct methods

    Doesn't work with struct methods

    So the following code generates a compiler error

    Error: Partial application of struct method is not allowed

    var err = SwiftRoute.replace(function: String().substringFromIndex, with: {
                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
        (index : Int) -> String in
            return "routed"
    })
    

    because String is a struct, not a real class.

    bug 
    opened by rodionovd 0
  • Consume a function's original implementation

    Consume a function's original implementation

    For now, we don't pass a third argument original_ptr to the rd_route() call:

    rd_route(rd_get_func_impl(targetMethod), rd_get_func_impl(replacement), nil)
    

    so we lose an original implementation — that's a big problem, e.g. when we need to call it from new implementation (see issue #3).

    Is there a way we can consume original_ptr in Swift?

    bug 
    opened by rodionovd 0
  • Support for getters/setters

    Support for getters/setters

    AFAIK, setters and getters are shared between all instances of a class in Swift. They seem to have the following structure:

    const int foo_offset = 0x48;
    
    int getFoo(void *self)
    {
        return *(uinptr_t *)(self + foo_offset);
    }
    
    
    void setFoo(int new_value, void *self)
    {
        // there will be release/retain for non-scalar types 
        // ...
       *(uintptr_t *)(self + foo_offset) = new_value;
    }
    

    So it's impossible (?) to hook a getter/setter for the only instance of a class.
    Needs some research, though.

    nicetohave help wanted question 
    opened by rodionovd 1
Owner
Dmitry Rodionov
Every time I start a new project I hope I won't find myself in the middle of the night staring at HIToolbox.framework disassembly. And yet…
Dmitry Rodionov
Sweet-swift - Make Swift Sweet by Gracefully Introducing Syntactic Sugar, Helper Functions and Common Utilities

Sweet Swift Make Swift Sweet by Gracefully Introducing Syntactic Sugar, Helper F

Yanzhan Yang 2 Feb 6, 2022
Airbnb's Swift Style Guide.

Airbnb Swift Style Guide Goals Following this style guide should: Make it easier to read and begin understanding unfamiliar code. Make code easier to

Airbnb 1.8k Jan 3, 2023
LinkedIn's Official Swift Style Guide

Swift Style Guide Make sure to read Apple's API Design Guidelines. Specifics from these guidelines + additional remarks are mentioned below. This guid

LinkedIn 1.4k Jan 5, 2023
The Official raywenderlich.com Swift Style Guide.

The Official raywenderlich.com Swift Style Guide. Updated for Swift 5 This style guide is different from others you may see, because the focus is cent

raywenderlich 12.5k Jan 3, 2023
A self-taught project to learn Swift.

30 Days of Swift Hi Community I am Allen Wang, a product designer and currently learning Swift. This project was totally inspired by Sam Lu's 100 Days

Allen Wang 11.4k Dec 31, 2022
Explanations and samples about the Swift programming language

About Swift Contents Explanations and samples about: Swift Programming Language Swift Standard Library Target audience Developers familiar with object

Nicola Lancellotti - About 74 Dec 29, 2022
A collection useful tips for the Swift language

SwiftTips The following is a collection of tips I find to be useful when working with the Swift language. More content is available on my Twitter acco

Vincent Pradeilles 929 Dec 10, 2022
Swift Featured Projects in brain Mapping

Swift 开源精选   自 2014年 WWDC 发布 Swift 语言以来,本项目 一直致力于将主流 Swift 中文学习、开发资源汇集于此,并且尽力紧密地跟踪、甄选优秀 Swift 开源项目,以方便开发者快速获得并使用。考虑 Swift 已经正式发布超过四年半(更无力管理维护海量的 Swift

iPader 15.8k Jan 9, 2023
A collection of Swift tips & tricks that I've shared on Twitter

⚠️ This list is no longer being updated. For my latest Swift tips, checkout the "Tips" section on Swift by Sundell. Swift tips & tricks ⚡️ One of the

John Sundell 3.9k Dec 30, 2022
An Xcode playground showcasing the new features in Swift 4.0.

What’s new in Swift 4 An Xcode playground showcasing the new features in Swift 4.0. As seen in the What’s New in Swift session at WWDC 2017. Written b

Ole Begemann 1.8k Dec 23, 2022