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
。
举几个例子:
hello.Rect.subscript.getter (hello.Direction) -> Swift.Int
重整为_TFV5hello4Rectg9subscriptFOS_9DirectionSi
HookExampleApp.ViewController.viewDidLoad() -> ()
重整为_T014HookExampleApp14ViewControllerC11viewDidLoadyyF
SwiftDemo.ViewController.CustomMethod(number: Swift.Int) -> Swift.Int
重整为_T09SwiftDemo14ViewControllerC12CustomMethodS2i6number_tF
xcode提供swift-demangle工具可以还原这些。1
2zlxdikedeMac: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
了
使用IDA Pro脚本先导出所有函数名
1 | from idautils import * |
回到macOS使用用python脚本调用swift-demangle还原1
2
3
4
5
6
7
8
9
10
11
12
13
14import 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?
接下来用MSFindSymbol
和MSHookFunction
和MSGetImageByName
搭配使用即可
踩过的坑
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的问题:
MSGetImageByName
在iOS9 iOS10上都返回NULL,iOS11正常
MSImageRef image = MSGetImageByName("@rpath/TelegramCore.framework/TelegramCore");
即使用绝对路径也是一样情况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
了- 使用
dlsym
与MSFindSymbol
不同。MSFindSymbol
以IDA Pro为准,即要带下划线_
,而dlsym
则不需要,这个估计与MSFindSymbol
的实现有一定关系
代码实现
iOS9 iOS10可工作
1
2
3
4
5
6
7
8
9
10
11
12
13
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);
}
}最原始有效,iOS9-iOS11通杀
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
,本文如有不足,请批评指正。