程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> 簡略剖析Swift說話的一些根本特點

簡略剖析Swift說話的一些根本特點

編輯:更多關於編程

簡略剖析Swift說話的一些根本特點。本站提示廣大學習愛好者:(簡略剖析Swift說話的一些根本特點)文章只能為提供參考,不一定能成為您想要的結果。以下是簡略剖析Swift說話的一些根本特點正文


Swift是蘋果公司最新推出的編程說話,據許多人說,是用來”取代“Objective-C。然則沒有確實的證據。我花了一些時光對Swift二進制和運轉情況實行逆向工程技巧,然後我對Swift有些少量的發明。今朝為止,結論就是:Swift是沒有新聞機制的Objective-C。

對象

信不信由你,Swift中的對象就是Objective-C的對象。在Mach-O二進制文件中,__objc_classlist包括每一個二進制文件中類的數據。其構造以下所示:
 
struct objc_class {
    uint64_t isa;
    uint64_t superclass;
    uint64_t cache;
    uint64_t vtable;
    uint64_t data;
};

(注:一切構造都來自64位版本)

留意data記載,它指向了類中的一個列出辦法、實例變量和協定等外容的構造體。平日,data是8個字節對齊的,然則關於Swift類,data的最初一名僅為1個字節。


Swift類的真正構造是有一點奇異的。Swift類沒有Objective-C辦法。我們將在今後完成它。Swift類的變量存儲為實例變量。Swift的getter和setter辦法真正修正的是實例變量的值。奇異的是swift類的實例變量沒有類型編碼。平日應當指向類型編碼的指針為NULL。這年夜概是因為現實上Objective-C運轉時是不支撐處置Swift變量自己。

繼續

Swift的繼續是你所等待的。在Swift中,Square是shape的子類也是Objective-C類Shape的子類。但是,在Swift類中沒有超類?

例如

class Shape { }

在這個例子中,Shape類是SwiftObject的子類。SwiftObject是一個根Objective-C類,相似於NSObject。它沒有超類,意味著isa指向本身。它的目標是應用Swift運轉時辦法好比allocation和deallocation取代尺度的Objective-C運轉時辦法。例如,(void)retain不會挪用objc_retain,然則它會挪用swift_retain。

類辦法

就像我之條件到的,Swift對象的類沒無方法,以此取代的是相似C++的函數,稱號改編和一切器械。這能夠是為何Swift宣稱比Objective-C更快的緣由。不再須要為 objc_msgSend  尋覓和挪用辦法完成。

在Objective-C外面,辦法像如許完成:

type method(id self, SEL _cmd, id arg1, id arg2, ...)

Swift 辦法異常相似,然則稍微應用了分歧的參數排布, self 作為最初一個參數傳遞,而且沒有選擇器。

type method(id arg1, id arg2, ..., id self)


虛表

相似C++一樣,Swift類也具有一個虛表,用於列出類中的辦法。它直接被放置在二進制文件中的類數據以後,而且看起來是如許的:
 
struct swift_vtable_header {
    uint32_t vtable_size;
    uint32_t unknown_000;
    uint32_t unknown_001;
    uint32_t unknown_002;
    void* nominalTypeDescriptor;
    // vtable pointers
}

據我所知,Swift類中的虛表僅在編譯時代可見時被應用。不然,它將看起來就是一堆亂糟糟的符號。

定名重整

Swift堅持函數的元數據在各自的符號,這就叫做定名重整。元數據寶庫奧函數的稱號(不言而喻的),屬性,模塊稱號,參數類型,前往值類型,還有更多的數據,例如這個例子
 
class Shape{
    func numberOfSides() -> Int {
        return 5
    }
}

simpleDescription辦法的重整定名是:

_TFC9swifttest5Shape17simpleDescriptionfS0_FT_Si。上面是具體解釋:

_T - 一切Swift符號的前綴,每個符號都是從_T開端。

F - 函數

C - 類的函數(辦法)

9swifttest - 帶有長度前綴的模塊名

5Shape - 函數所屬的類,帶有長度前綴

17simpleDescription - 函數名

f - 函數屬性。 在這個例子中它是f,這是一個通俗函數。

S0_FT- 我不是特殊肯定這是甚麼意思,然則它是參數和前往類型開端的標志

‘_' - 這個下劃線朋分了參數和前往值的類型。由於函數沒有帶參數,它直接跟在了S0_FT的前面

S - 前往值的開端。'S'代表Swift;前往類型是Swift的內建類型,下一個字符決議了類型

i - 這是Swift的內建類型。一個小寫的"I"代表了Int.


函數屬性

字符類型

f        通俗函數

s        setter

g        getter

d        析構函數

D        釋放器

c        結構函數

C        分派器

Swift外部函數

字符類型

a        數組

b        布爾型

c        字符常量

d        雙精度浮點數

f        單精度浮點型

i        整型

u        UInt類型

Q        隱式可選

S        字符串型

除函數以外,還有許多定名轉換機制,此處我僅給出一個冗長的概述。

掛鉤函數

受夠了語義這部門,讓我們接觸點風趣的器械!比喻說我們有一個像如許的類:
 
class Shape {
    var numberOfSides: Int;
 
    init(){
        numberOfSides = 5;
    }
}

好比我們想將numberOfSides的值改成4,許多種辦法可以做到。我們可使用MobileSubstrate掛到getter辦法中,然後更改前往值,就像如許:

 
int (*numberOfSides)(id self);
 
MSHook(int, numberOfSides, id self){
    return 4;
}
 
%ctor{
    numberOfSides = (int (*)(id self)) dlsym(RTLD_DEFAULT, "_TFC9swifttest5Shapeg13numberOfSidesSi");
    MSHookFunction(numberOfSides, MSHake(numberOfSides));
}

假如我們創立了一個外形的實例,而且打印出numberOfSides的值,我們獲得了4!看起來不錯,對不?如今,我曉得你能夠在想,豈非我們不該該是前往一個對象而異常量4嗎?


好吧,在Swift裡,很多內建類型是書面量來的。一個Int型, 舉個例子,和C說話外面的int型一樣(雖然它可所以一個長整形——不要讓我碰著這類情形)。一個小小的提醒,String 類型有點陳舊,這是一個低位優先的UTF-16字符串,所以沒有C的字面量能用。

讓我們來做異樣的工作,但這一次,我們不是在獲得器上,而是在獲得器上設鉤。

 
void (*setNumberOfSides)(int newNumber, id self);
 
MSHook(void, setNumberOfSides, int newNumber, id self){
    _setNumberOfSides(4, self);
}
 
%ctor {
    setNumberOfSides = (void (*)(int newNumber, id self)) dlsym(RTLD_DEFAULT, "_TFC9swifttest5Shapes13numberOfSidesSi");
    MSHookFunction(setNumberOfSides, MSHake(setNumberOfSides));
}

再測驗考試一下,然後。。。。。。照樣5。怎樣回事,你問?好吧,在Swift裡某些處所,函數是內聯化的。類結構器就是個中一個的處所。它直接設置numberOfSides 為ivar, 設置器將僅在數值再次被頂層代碼設置的時刻被挪用。在那被挪用,你曉得麼,我們獲得了4。

終究,讓我們經由過程直接設置實例變量的值來修正numberOfSides。

 
void (*setNumberOfSides)(int newNumber, id self);
 
MSHook(void, setNumberOfSides, int newNumber, id self){
    MSHookIvar<int>(self, "numberOfSides") = 4;
}
 
%ctor {
    setNumberOfSides = (void (*)(int newNumber, id self)) dlsym(RTLD_DEFAULT, "_TFC9swifttest5Shapes13numberOfSidesSi");
    MSHookFunction(setNumberOfSides, MSHake(setNumberOfSides));
}

這個函數是可以完成功效的,固然不建議如許做,然則確切有用果。

這是今朝我所要寫的內容。固然,還有許多其他的內容我正在看,包含witness表,因為我懂得不多,所以這裡我也沒方法寫出總結。許多內容在這篇文章裡有變革,他們僅是我今朝對運轉和檢查用Swift說話編譯的二進制文件逆向工程操作所獲得的器械。

我所發明的器械應當長短常不錯的,這意味著MobileSubstrate不會跟著Objective-C一同滅亡,而且,微調依然可以停止!我很想曉得未來在逃獄場景下的運用市肆中將會是如何一番情形……豈非logo可以更新用來主動燒毀定名?乃至是處置罕見的 Swift 類型的庫……

假如你發明更多的關於Swift若何任務的器械,不要遲疑,請讓我曉得!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved