Swift Hook尝试(Telegram Unblock)

Cydia源:http://zlxdike.github.io/repo/

需求

最新得Telegram已经开始全部使用Swift开发了。导致之前得tgunblock tweak失效。于是就想要自己试试hook swift。也当作一个学习过程吧。研究了一半后发现已经有现成插件了,叫nsfwgram,支持swift版的Telegram,不过既然都开始研究了,也顺便继续下去。自己在写一个吧。

分析

Github上其实有Swift版Telegram的源码,能减少很多功夫。项目叫TelegramSwift
git clone下来看了下。hookPeerUtils.swift中的public var restrictionText: String?{}方法就可以解决channel被屏蔽的问题

实施

虽然我们知道了要hook的相关内容了。但是我们知道swift编译后没法使用class-dump把类dump下来,这是因为swift所有的函数名都被mangled类似C++程序编译后的函数名。姑且叫它Swift Name Mangling
举几个例子:

  1. hello.Rect.subscript.getter (hello.Direction) -> Swift.Int重整为_TFV5hello4Rectg9subscriptFOS_9DirectionSi
  2. HookExampleApp.ViewController.viewDidLoad() -> ()重整为_T014HookExampleApp14ViewControllerC11viewDidLoadyyF
  3. SwiftDemo.ViewController.CustomMethod(number: Swift.Int) -> Swift.Int重整为_T09SwiftDemo14ViewControllerC12CustomMethodS2i6number_tF

xcode提供swift-demangle工具可以还原这些。

1
2
zlxdikedeMac:Desktop zlxdike$ xcrun swift-demangle _T09SwiftDemo14ViewControllerC12CustomMethodS2i6number_tF
_T09SwiftDemo14ViewControllerC12CustomMethodS2i6number_tF ---> SwiftDemo.ViewController.CustomMethod(number: Swift.Int) -> Swift.Int

接下来就是找到被重整后的symbol了
首先把TelegramCore扔到IDA Pro里面。结果坑爹了。形如_T函数几乎少的可怜。基本都是形如_$S
一开始我以为是因为上架了AppStroe。Apple对symbol做了修改防止被swift-demangle还原。还试图想要在自己机器(用的还是Swift3)上编译个TelegramCore。然后对比做还原。后来发现。应该是Swift版本编译的问题。从Swift4.2开始都开始用$S
png
使用IDA Pro脚本先导出所有函数名

1
2
3
4
5
6
7
8
9
10
11
from idautils import *
from idaapi import *
from idc import *
abc = []
for segea in Segments():
for funcea in Functions(segea, SegEnd(segea)):
functionName = GetFunctionName(funcea)
if functionName.find("_$") != -1:
abc.append(functionName[2:])
with open("output.txt","wb") as f:
f.write("\n".join(abc))

回到macOS使用用python脚本调用swift-demangle还原

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import os
l = []
i = 0
with open("output.txt" ,"rb") as f:
data=f.read()
dataArr = data.split("\n")
for x in dataArr:
ret = os.popen('./swift-demangle %s' % x)
i = i +1
print i
l.append(ret.read())

with open("result.txt","wb") as f:
f.write("\n".join(l))

找到对应symbol
$S7Postbox4PeerP12TelegramCoreE15restrictionTextSSSgvg ---> (extension in TelegramCore):Postbox.Peer.restrictionText.getter : Swift.String?
接下来用MSFindSymbolMSHookFunctionMSGetImageByName搭配使用即可

踩过的坑

MobileSubstrate(Cydia Substrate),它是由Saurik开发的一个框架。应该是iOS11目前的越狱,不被Saurik所认可吧,所以导致这个框架一直没兼容iOS11。当然也可能是大神没空。目前iOS11上的Substrate很多都是越狱工具作者另外修改的可能基于comex的substitute项目做的修改

测试设备
iPhone 5S iOS10.0.2(yalu beta2越狱)
iPad Air2 iOS9.0.2(盘古越狱)
iPhone7 Plus iOS11.1.1(unc0ver RC9越狱)

这过程中遇到下面的问题,猜测可能是substrate的问题:

  1. MSGetImageByName在iOS9 iOS10上都返回NULL,iOS11正常
    MSImageRef image = MSGetImageByName("@rpath/TelegramCore.framework/TelegramCore");
    即使用绝对路径也是一样情况
  2. MSFindSymbol在iOS9 iOS10上第一参数必为NULL,才能正常获取到函数指针
    MSFindSymbol(NULL,"_$S7Postbox4PeerP12TelegramCoreE15restrictionTextSSSgvg");
    在iOS11上虽然MSGetImageByName能获取到值,但是MSFindSymbol第一参数无论是不是NULL,MSFindSymbol都无法获取到函数指针。
    看了下comex的substitute的MSFindSymbol函数实现。发现都是并不是使用dlsym去查找,他自己写了个find_syms_raw,查找MachO_machHeader,可能类似xcode带的nm工具,nm也无法导出这些symbol,不然就不需要IDA Pro跑脚本获取所有的Function Name
  3. 使用dlsymMSFindSymbol不同。MSFindSymbol以IDA Pro为准,即要带下划线_,而dlsym则不需要,这个估计与MSFindSymbol的实现有一定关系

代码实现

  1. iOS9 iOS10可工作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #import<substrate.h>
    static int (*orig_function)(void) = NULL;
    static int new_function() {
    return 0;
    }
    %ctor {
    void *symbol = MSFindSymbol(NULL,"_$S7Postbox4PeerP12TelegramCoreE15restrictionTextSSSgvg");
    if (symbol) {
    MSHookFunction((void *)symbol,
    (void*)&new_function,
    (void**)&orig_function);
    }
    }
  2. 最原始有效,iOS9-iOS11通杀

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <dlfcn.h>
    #import <substrate.h>
    static int (*orig_function)(void) = NULL;
    static int new_function() {
    return 0;
    }
    %ctor {
    void* handle=dlopen("@rpath/TelegramCore.framework/TelegramCore",RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
    if (handle){
    void* symbol = dlsym(handle,"$S7Postbox4PeerP12TelegramCoreE15restrictionTextSSSgvg");
    if (symbol){
    MSHookFunction((void *)symbol,(void*)&new_function,(void**)&orig_function);
    }
    }
    }

已经上传到Cydia源:http://zlxdike.github.io/repo,本文如有不足,请批评指正。

参考

Swift函数名重整技术
Hooking Swift methods in Theos


本文结束感谢您的阅读