iPhone查找序列號生成函數

前言

在iOS7以前咱們能夠經過- (NSString *)uniqueIdentifier這個方法獲取iPhone的惟一標識符,也叫做UDID。不過自從iOS7蘋果就把這個方法給禁了,此時咱們想要獲取iPhone的惟一標識符就很困難。
不過蘋果提供一個叫作IDFA的標識符,這個IDFA是廣告標識符用來追蹤廣告投放的,不過用戶能夠在設置中手動重置IDFA,可靠性很低,目前常見的兩種標記iPhone的方式爲git

  • openUDID
  • IDFA或UUID+keychain

這兩種模式都有個弊端,用戶重置手機或者刷機惟一標識符會發生變化,不過對於大多數狀況是夠用了。看來蘋果是把路給封死了,有沒有辦法拿到以前的UDID呢?咱們注意到iPhone的設置通用關於裏面有手機的硬件信息,其中有一個serialNumber,這個serialnumber就是咱們查詢手機是否過保的依據,那麼它確定是惟一的,因此下文是圍繞這個進行的探索。最終是能夠拿到這個serialNumber的, 不過因爲蘋果的沙盒限制,因此只能在越獄機中拿到,若是想在非越獄機中拿到必須添加entitlements文件來獲取權限,可想而知這個應用是沒法上架的。下文僅做爲逆向工程的一種思路和探索github

轉載請註明出處:來自LeonLei的博客http://www.gaoshilei.comshell

正文

1、SSH鏈接手機(USB模式)

1.映射端口

LeonLei-MBP:~ gaoshilei$ /Users/gaoshilei/Desktop/reverse/USBSSH/tcprelay.py -t 22:6666
Forwarding local port 6666 to remote port 22
複製代碼

2.鏈接手機,而且用grep命令快速篩選當前咱們要調試的應用Preferences,附加debugserver開始1234端口等待lldb調試

LeonLei-MBP:~ gaoshilei$ ssh root@localhost -p 6666
iPhone-5S:~ root# ps -e | grep Pre
  270 ??         0:00.29 /System/Library/PrivateFrameworks/MobileSoftwareUpdate.framework/XPCServices/com.apple.MobileSoftwareUpdate.CleanupPreparePathService.xpc/com.apple.MobileSoftwareUpdate.CleanupPreparePathService
 1192 ??         0:14.26 /var/db/stash/_.fP74Fg/Applications/Preferences.app/Preferences
 1289 ttys000    0:00.01 grep Pre
iPhone-5S:~ root# debugserver *:1234 -a "Preferences"
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-340.3.51.1
 for arm64.
Attaching to process Preferences...
Listening to port 1234 for a connection from *...
複製代碼

3.完成以上兩步接下來就能夠進行lldb調試了,首先要把遠端(手機)的1234端口映射到本地,跟前面提到的SSH端口映射同樣

LeonLei-MBP:~ gaoshilei$ /Users/gaoshilei/Desktop/reverse/USBSSH/tcprelay.py -t 1234:1234
Forwarding local port 1234 to remote port 1234
複製代碼

2、經過LLDB、IDA尋找線索

lldb的調試端口已經打開,此時咱們能夠進入調試數組

LeonLei-MBP:~ gaoshilei$ lldb
(lldb) process connect connect://localhost:1234
Process 1192 stopped  
* thread #1: tid = 0x523a6, 0x000000019a3c8a40 libsystem_kernel.dylib`mach_msg_trap + 8, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP 
    frame #0: 0x000000019a3c8a40 libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
->  0x19a3c8a40 <+8>: ret    
libsystem_kernel.dylib`mach_msg_overwrite_trap:
    0x19a3c8a44 <+0>: movn   x16, #0x1f
    0x19a3c8a48 <+4>: svc    #0x80
    0x19a3c8a4c <+8>: ret    
複製代碼

此時咱們已經成功進入Preferences的調試階段,先c一下,讓程序繼續運行bash

(lldb) c
Process 1192 resuming
複製代碼

這麼作的緣由是咱們待會要打印image的基地址偏移,有可能在咱們打印的image list中沒有咱們想要的image。 此時咱們已經找到到Preference.framework的基地址偏移,見下圖app

(lldb) im li -o -f
[  0] 0x00000000000dc000 /var/db/stash/_.fP74Fg/Applications/Preferences.app/Preferences(0x00000001000dc000)
[  1] 0x0000000100100000 /Library/MobileSubstrate/MobileSubstrate.dylib(0x0000000100100000)
[  2] 0x0000000002e50000 /Users/gaoshilei/Library/Developer/Xcode/iOS DeviceSupport/9.1 (13B143)/Symbols/System/Library/PrivateFrameworks/BulletinBoard.framework/BulletinBoard
[  3] 0x0000000002e50000 /Users/gaoshilei/Library/Developer/Xcode/iOS DeviceSupport/9.1 (13B143)/Symbols/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
[  4] 0x0000000002e50000 /Users/gaoshilei/Library/Developer/Xcode/iOS DeviceSupport/9.1 (13B143)/Symbols/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
…
[ 44] 0x0000000002e50000 /Users/gaoshilei/Library/Developer/Xcode/iOS DeviceSupport/9.1 (13B143)/Symbols/System/Library/PrivateFrameworks/Preferences.framework/Preferences
…  
複製代碼

咱們要找的image的序號在這裏是44,它的基地址偏移爲0x2e50000,咱們把從iPhone中導出的PrivateFrameworks中的Preferences.framework丟到IDA中進行分析,這個二進制文件比較小,很快就分析完成,在前面咱們已經知道iPhone的惟一序列號serial number是經過PSListController生成的,而且咱們知道這是一個cell,咱們要去調試[PSListController tableView:cellForRowAtIndexPath:]這個方法,從中找到cell值的來源,從而找到獲取序列號的方法。ssh

__text:00000001908040C8 ; -[PSListController tableView:cellForRowAtIndexPath:]
__text:00000001908040C8 __PSListController_tableView_cellForRowAtIndexPath__
__text:00000001908040C8                                         ; DATA XREF: __objc_const:000000019C069B88o
__text:00000001908040C8
__text:00000001908040C8 var_80          = -0x80
__text:00000001908040C8 var_78          = -0x78
__text:00000001908040C8 var_70          = -0x70
__text:00000001908040C8 var_68          = -0x68
__text:00000001908040C8 var_60          = -0x60
__text:00000001908040C8 var_50          = -0x50
__text:00000001908040C8 var_40          = -0x40
__text:00000001908040C8 var_30          = -0x30
__text:00000001908040C8 var_20          = -0x20
__text:00000001908040C8 var_10          = -0x10
__text:00000001908040C8
__text:00000001908040C8                 STP             X28, X27, [SP,#var_60]!
__text:00000001908040CC                 STP             X26, X25, [SP,#0x60+var_50]
__text:00000001908040D0                 STP             X24, X23, [SP,#0x60+var_40]
__text:00000001908040D4                 STP             X22, X21, [SP,#0x60+var_30]
__text:00000001908040D8                 STP             X20, X19, [SP,#0x60+var_20]
__text:00000001908040DC                 STP             X29, X30, [SP,#0x60+var_10]
__text:00000001908040E0                 ADD             X29, SP, #0x60+var_10
__text:00000001908040E4                 SUB             SP, SP, #0x20
__text:00000001908040E8                 MOV             X21, X3
__text:00000001908040EC                 MOV             X20, X0
__text:00000001908040F0                 MOV             X0, X2
__text:00000001908040F4                 BL              0x96C400A0
__text:00000001908040F8                 MOV             X26, X0
__text:00000001908040FC                 ADRP            X8, #off_19DACC568@PAGE
__text:0000000190804100                 LDR             X1, [X8,#off_19DACC568@PAGEOFF]
__text:0000000190804104                 MOV             X0, X20
__text:0000000190804108                 MOV             X2, X21
__text:000000019080410C                 BL              0x96C39BC0
__text:0000000190804110                 MOV             X2, X0
__text:0000000190804114                 ADRP            X8, #_OBJC_IVAR_$_PSListController._specifiers@PAGE ; NSArray *_specifiers;
__text:0000000190804118                 LDRSW           X27, [X8,#_OBJC_IVAR_$_PSListController._specifiers@PAGEOFF] ; NSArray *_specifiers;
__text:000000019080411C                 LDR             X0, [X20,X27]
__text:0000000190804120                 ADRP            X8, #off_19DACC558@PAGE
……
複製代碼

咱們在Preference.framework中基地址爲0x190804114的位置打個斷點,具體的作法是:tcp

(lldb) br s -a 0x190804114+0x2e50000
Breakpoint 1: where = Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 76, address = 0x0000000193654114
Process 1192 stopped
* thread #1: tid = 0x523a6, 0x0000000193654114 Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 76, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000193654114 Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 76
Preferences`-[PSListController tableView:cellForRowAtIndexPath:]:
->  0x193654114 <+76>: adrp   x8, 53965
    0x193654118 <+80>: ldrsw  x27, [x8, #516]
    0x19365411c <+84>: ldr    x0, [x20, x27]
    0x193654120 <+88>: adrp   x8, 53960
複製代碼

這裏斷點這樣打是由於系統加載可執行文件和各類framework的時候會有一個地址偏移,咱們在打斷點的時候要把這個偏移量加上,這樣咱們打的斷點纔是準確的。 能夠看到咱們已經成功打了一個斷點,斷點的address = 0x193654114。此時咱們打印變量x0和x27的值ide

(lldb) po $x0
13
(lldb) po $x27
1104
複製代碼

咱們執行ni讓程序繼續(這裏的ni命令至關於Xcode的那個下箭頭命令,也就是下一行)函數

(lldb) ni
Process 1192 stopped
* thread #1: tid = 0x523a6, 0x0000000193654118 Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 80, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x0000000193654118 Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 80
Preferences`-[PSListController tableView:cellForRowAtIndexPath:]:
->  0x193654118 <+80>: ldrsw  x27, [x8, #516]
    0x19365411c <+84>: ldr    x0, [x20, x27]
    0x193654120 <+88>: adrp   x8, 53960
    0x193654124 <+92>: ldr    x22, [x8, #1368]
(lldb) ni
Process 1192 stopped
* thread #1: tid = 0x523a6, 0x000000019365411c Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 84, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x000000019365411c Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 84
Preferences`-[PSListController tableView:cellForRowAtIndexPath:]:
->  0x19365411c <+84>: ldr    x0, [x20, x27]
    0x193654120 <+88>: adrp   x8, 53960
    0x193654124 <+92>: ldr    x22, [x8, #1368]
    0x193654128 <+96>: mov    x1, x22
(lldb) po $x27
848

(lldb) po $x0
13
複製代碼

咱們ni的兩次,程序已經走到0x19080411C的位置,而後咱們繼續打印變量x0和x27的值

(lldb) po $x0
13
(lldb) po $x27
1104
複製代碼

打印出來的x0和x27都是隨機數,仍是沒有什麼收穫,咱們繼續

(lldb) ni
Process 1192 stopped
* thread #1: tid = 0x523a6, 0x0000000193654120 Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 88, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x0000000193654120 Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 88
Preferences`-[PSListController tableView:cellForRowAtIndexPath:]:
->  0x193654120 <+88>:  adrp   x8, 53960
    0x193654124 <+92>:  ldr    x22, [x8, #1368]
    0x193654128 <+96>:  mov    x1, x22
    0x19365412c <+100>: bl     0x199a89bc0               ; objc_msgSend
(lldb) po $x0
<__NSArrayI 0x13105a780>(
G: <PSSpecifier 0x12ff50cf0: ID 0, Name '' target <(null): 0x0>> 0x12ff50cf0,
<PSSpecifier 0x12ff50f50: ID NAME_CELL_ID, Name 'Name' target <AboutDataSource: 0x131028390>>,
G: <PSSpecifier 0x12ff51680: ID 2, Name '' target <(null): 0x0>> 0x12ff51680,
<PSSpecifier 0x12ff52360: ID NETWORK, Name 'Network' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff52420: ID SONGS, Name 'Songs' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff519f0: ID VIDEOS, Name 'Videos' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff51ab0: ID PHOTOS, Name 'Photos' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff51b70: ID APPLICATIONS, Name 'Applications' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff524e0: ID User Data Capacity, Name 'Capacity' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff525a0: ID User Data Available, Name 'Available' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff526a0: ID ProductVersion, Name 'Version' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff52850: ID CARRIER_VERSION, Name 'Carrier' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff52980: ID ProductModel, Name 'Model' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff52a60: ID SerialNumber, Name 'Serial Number' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff52b90: ID MACAddress, Name 'Wi-Fi Address' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12ff51050: ID BTMACAddress, Name 'Bluetooth' target <AboutDataSource: 0x131028390>>,
<PSSpecifier 0x12fde95d0: ID ModemVersion, Name 'Modem Firmware' target <AboutDataSource: 0x131028390>>,
G: <PSSpecifier 0x131031e90: ID 17, Name '' target <(null): 0x0>> 0x131031e90,
<PSSpecifier 0x12fde9c40: ID LEGAL_AND_REGULATORY, Name 'Legal' target <(null): 0x0>>,
G: <PSSpecifier 0x131029dc0: ID TRUST_STORE_GROUP, Name '' target <(null): 0x0>> 0x131029dc0,
<PSSpecifier 0x131033520: ID TRUST_STORE, Name 'Trust Store' target <AboutDataSource: 0x131028390>>
)
複製代碼

咱們讓程序執行下一步,發現此時x0已經有值了,能夠明顯的看出,x0的值是在0x190804114~0x19080411C這段代碼生成的,下面咱們的工做重點就是尋找這段代碼幹了什麼,勝利就在眼前!下面咱們驗證一下這裏面到底有沒有咱們要的序列號:

(lldb) po [[$x0 objectAtIndex:13] class]
PSSpecifier
(lldb) po [[$x0 objectAtIndex:13] properties]
{
    cellObject = "<PSTableCell: 0x130800000; baseClass = UITableViewCell; frame = (0 565; 320 45); text = 'Serial Number'; hidden = YES; autoresize = W; tag = 4; gestureRecognizers = <NSArray: 0x12ff821c0>; layer = <CALayer: 0x12fd7d340>>";
    id = SerialNumber;
    isCopyable = 1;
    value = DNPMVG0EFF9V;
}
複製代碼

咱們打印數組中存放cell數據的object屬於哪一個類,發現是PSSpecifier,咱們找到以前導出的類的頭文件,發現這個類有一個叫作properties的實例方法,咱們調用一下發現咱們要的序列號就在裏面value = DNPMVG0EFF9V,這跟iPhone設置中看到的序列號是一致的。猜想這個數組裏面存放着系統設置中PSUIAboutController中全部cel的數據,這個數組下一個確定要傳遞到cell生成的方法中,這個就不作驗證了,大事重要,咱們繼續找序列號的生成方法。 這個PSSpecifier中有一個AboutDataSource對象,這個很是可疑,從名稱上能夠判斷,這個類是專門用於數據處理的,不過在這以前咱們仍是先驗證一下,在0x190804114~0x19080411C這段地址中,執行了_PSListController._specifiers,咱們從PSListController的頭文件(下文有講怎麼獲取)中能夠看到有一個specifiers屬性,咱們在IDA分析的文件中找到[PSListController specifiers],咱們先定位到方法在二進制文件中的位置:

__text:00000001907FE4A8 ; -[PSListController specifiers]
__text:00000001907FE4A8 __PSListController_specifiers_          ; DATA XREF: __objc_const:000000019C069A08o
__text:00000001907FE4A8
__text:00000001907FE4A8 var_40          = -0x40
__text:00000001907FE4A8 var_30          = -0x30
__text:00000001907FE4A8 var_20          = -0x20
__text:00000001907FE4A8 var_10          = -0x10
__text:00000001907FE4A8
__text:00000001907FE4A8                 STP             X24, X23, [SP,#var_40]!
__text:00000001907FE4AC                 STP             X22, X21, [SP,#0x40+var_30]
__text:00000001907FE4B0                 STP             X20, X19, [SP,#0x40+var_20]
__text:00000001907FE4B4                 STP             X29, X30, [SP,#0x40+var_10]
__text:00000001907FE4B8                 ADD             X29, SP, #0x40+var_10
__text:00000001907FE4BC                 MOV             X19, X0
__text:00000001907FE4C0                 ADRP            X8, #_OBJC_IVAR_$_PSListController._specifiers@PAGE ; NSArray *_specifiers;
__text:00000001907FE4C4                 LDRSW           X22, [X8,#_OBJC_IVAR_$_PSListController._specifiers@PAGEOFF] ; NSArray *_specifiers;
__text:00000001907FE4C8                 LDR             X8, [X19,X22]
__text:00000001907FE4CC                 CBNZ            X8, loc_1907FE5E0
__text:00000001907FE4D0                 ADRP            X8, #_OBJC_IVAR_$_PSListController._dataSource@PAGE ; id <PSSpecifierDataSource> _dataSource;
__text:00000001907FE4D4                 LDRSW           X8, [X8,#_OBJC_IVAR_$_PSListController._dataSource@PAGEOFF] ; id <PSSpecifierDataSource> _dataSource;
__text:00000001907FE4D8                 LDR             X9, [X19,X8]
__text:00000001907FE4DC                 CBZ             X9, loc_1907FE550
__text:00000001907FE4E0                 ADRP            X9, #_OBJC_IVAR_$_PSListController._requestingSpecifiersFromDataSource@PAGE ; bool _requestingSpecifiersFromDataSource;
__text:00000001907FE4E4                 LDRSW           X23, [X9,#_OBJC_IVAR_$_PSListController._requestingSpecifiersFromDataSource@PAGEOFF] ; bool _requestingSpecifiersFromDataSource;
__text:00000001907FE4E8                 MOV             W9, #1
__text:00000001907FE4EC                 STRB            W9, [X19,X23]
__text:00000001907FE4F0                 LDR             X20, [X19,X8]
__text:00000001907FE4F4                 ADRP            X8, #selRef_specifier@PAGE
__text:00000001907FE4F8                 LDR             X1, [X8,#selRef_specifier@PAGEOFF]
__text:00000001907FE4FC                 MOV             X0, X19
__text:00000001907FE500                 BL              0x96C39BC0
__text:00000001907FE504                 MOV             X29, X29
__text:00000001907FE508                 BL              0x96C41EF0
__text:00000001907FE50C                 MOV             X21, X0
__text:00000001907FE510                 ADRP            X8, #selRef_specifiersForSpecifier_observer_@PAGE
__text:00000001907FE514                 LDR             X1, 
……
複製代碼

而後在這裏面下個斷點看看會發生什麼

(lldb) br s -a 0x1907FE4D0+0x198e58640
Breakpoint 9: where = Preferences`-[PSListController specifiers] + 40, address = 0x000000019364e4d0
複製代碼

咱們從設置中進入通用>關於,發現一開始就走到了這個斷點,咱們猜想,一進入關於頁面,系統會首先把全部cell的數據都準備好,而後加載UI

Process 1192 stopped
* thread #1: tid = 0x523a6, 0x000000019364e4d0 Preferences`-[PSListController specifiers] + 40, queue = 'com.apple.main-thread', stop reason = breakpoint 9.1
    frame #0: 0x000000019364e4d0 Preferences`-[PSListController specifiers] + 40
Preferences`-[PSListController specifiers]:
->  0x19364e4d0 <+40>: adrp   x8, 53971
    0x19364e4d4 <+44>: ldrsw  x8, [x8, #536]
    0x19364e4d8 <+48>: ldr    x9, [x19, x8]
    0x19364e4dc <+52>: cbz    x9, 0x19364e550           ; <+168>
複製代碼

咱們打印變量x8和x9的值,看一下系統作了什麼

(lldb) po $x8
<nil>
(lldb) po $x9
PSUIAboutController
複製代碼

並無數據之類的東西值得咱們關注,讓斷點繼續往下走,走到0x19364e4dc的位置,咱們再次打印變量x8和x9的值

(lldb) n
Process 1192 stopped
* thread #1: tid = 0x523a6, 0x000000019364e4dc Preferences`-[PSListController specifiers] + 52, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x000000019364e4dc Preferences`-[PSListController specifiers] + 52
Preferences`-[PSListController specifiers]:
->  0x19364e4dc <+52>: cbz    x9, 0x19364e550           ; <+168>
    0x19364e4e0 <+56>: adrp   x9, 53971
    0x19364e4e4 <+60>: ldrsw  x23, [x9, #540]
    0x19364e4e8 <+64>: orr    w9, wzr, #0x1
(lldb) po $x8
952
(lldb) po $x9
<AboutDataSource: 0x131130730>
複製代碼

此時的變量x9已經變成了AboutDataSource,這裏驗證了咱們上一步的猜測,因此咱們重點來研究它,咱們先找到這個類在哪一個framework中,這裏使用的是grep命令

LeonLei-MBP:~ gaoshilei$ grep AboutDataSource -r /Users/gaoshilei/Desktop/reverse/iOS-Runtime-Headers-9.1 
/Users/gaoshilei/Desktop/reverse/iOS-Runtime-Headers-9.1/PrivateFrameworks/PreferencesUI.framework/AboutDataSource.h:@interface AboutDataSource : PSSpecifierDataSource {
複製代碼

這裏要說明一下iOS-Runtime-Headers-9.1這個文件夾是iOS9.1系統的全部頭文件(共有+私有),這個你能夠本身導(iOS9以後只能用runtime導,class-dump已經不行了),你也能夠拿現成的用,github上面已經有雷鋒把全部系統的頭文件都導出來了,直接下載就能夠了。咱們發現AboutDataSource這個類在PrivateFrameworks/PreferencesUI.framework中,先看一下這個類裏面有什麼方法和屬性,有一個方法- (void)_loadValues; 咱們對它進行分析。這裏又要藉助IDA分析,把PreferencesUI這個二進制文件丟到IDA裏面,在0x19091EBB8這個位置打個斷點

(lldb) br s -a 0x19091EBB8+0x2e50000
Breakpoint 3: where = PreferencesUI`-[AboutDataSource _loadValues] + 1956, address = 0x000000019376ebb8
複製代碼

接下來咱們進入關於來觸發斷點

(lldb) po (char *) $x28
"_setValue:forSpecifierWithKey:"
複製代碼

在這裏打印變量x28的值,發現它是一個方法名,從名稱來看是給specifier賦值的,看來咱們要尋找的真相已經很近了,讓代碼走到下面的位置0x19376ebd8

Process 2107 stopped
* thread #1: tid = 0xe8e23, 0x000000019376ebd8 PreferencesUI`-[AboutDataSource _loadValues] + 1988, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x000000019376ebd8 PreferencesUI`-[AboutDataSource _loadValues] + 1988
PreferencesUI`-[AboutDataSource _loadValues]:
->  0x19376ebd8 <+1988>: bl     0x198e58640               ; MGCopyAnswer
    0x19376ebdc <+1992>: mov    x22, x0
    0x19376ebe0 <+1996>: mov    x1, x19
    0x19376ebe4 <+2000>: bl     0x199a89bc0               ; objc_msgSend
(lldb) po $x0
SerialNumber
複製代碼

此時咱們打印的x0是一個NSCFConstantString,本質就是一個NSString,繼續ni讓程序運行到0x19376ebdc

Process 2107 stopped
* thread #1: tid = 0xe8e23, 0x000000019376ebdc PreferencesUI`-[AboutDataSource _loadValues] + 1992, queue = 'com.apple.main-thread', stop reason = instruction step over
    frame #0: 0x000000019376ebdc PreferencesUI`-[AboutDataSource _loadValues] + 1992
PreferencesUI`-[AboutDataSource _loadValues]:
->  0x19376ebdc <+1992>: mov    x22, x0
    0x19376ebe0 <+1996>: mov    x1, x19
    0x19376ebe4 <+2000>: bl     0x199a89bc0               ; objc_msgSend
    0x19376ebe8 <+2004>: cbnz   x0, 0x19376ec4c           ; <+2104>
(lldb) po $x0
DNPMVG0EFF9V
複製代碼

在這裏咱們打印了變量x0的值爲DNPMVG0EFF9V,這就是咱們苦苦尋找的序列號。不難看出,序列號就是在0x19376ebd8這行拿到的,範圍愈來愈小,敵人無路可逃!下面咱們就要對這行進行分析,咱們按照以前的步驟,再次走到0x19376ebd8這個位置,這不過此次咱們不要step-over,咱們用si跳入看看

(lldb) si
Process 2107 stopped
* thread #1: tid = 0xe8e23, 0x0000000198e58640 libMobileGestalt.dylib`MGCopyAnswer, queue = 'com.apple.main-thread', stop reason = instruction step into
    frame #0: 0x0000000198e58640 libMobileGestalt.dylib`MGCopyAnswer
libMobileGestalt.dylib`MGCopyAnswer:
->  0x198e58640 <+0>: movz   x1, #0
    0x198e58644 <+4>: b      0x198e58648               ; ___lldb_unnamed_symbol64$$libMobileGestalt.dylib

libMobileGestalt.dylib`___lldb_unnamed_symbol64$$libMobileGestalt.dylib:
    0x198e58648 <+0>: stp    x24, x23, [sp, #-64]!
    0x198e5864c <+4>: stp    x22, x21, [sp, #16]
此時跳入了一個靜態庫libMobileGestalt.dylib,咱們能夠在usr/lib/ibMobileGestalt.dylib找到它,咱們將它扔進IDA,用當前的addr減去libMobileGestalt.dylib的基地址偏移獲得它的靜態地址0x196008640,對應的是一個函數MGCopyAnswer
__text:0000000196008640
__text:0000000196008640 ; =============== S U B R O U T I N E =======================================
__text:0000000196008640
__text:0000000196008640
__text:0000000196008640                 EXPORT _MGCopyAnswer
__text:0000000196008640 _MGCopyAnswer                           ; CODE XREF: sub_196005958+30p
__text:0000000196008640                                         ; sub_196006258+28p ...
__text:0000000196008640                 MOV             X1, #0
__text:0000000196008644                 B               sub_196008648
__text:0000000196008644 ; End of function _MGCopyAnswer
複製代碼

這個函數最外層只有兩行代碼,將當即數0賦給x1,而後跳進了子程序sub_196008648,跳進去以後進行了一些很複雜的運算,這裏就不作介紹了,裏面的實現大概是這樣的: x0是做爲一個參數傳入的,而且這裏x0的值爲SerialNumber,在地址爲0x196008678的地方,這個函數中x1變成了一串隨機數,有點像MD5加密以後的東西,應該是「鑰匙」

(lldb) po (char*) $x1
"l92SaBpqIvQs+KBljuwGA"
複製代碼

在0x196008690這裏,咱們setp-into這個函數,在函數的末尾返回值的地方0x196007474打個斷點,打印返回值x0

(lldb) po $x0
DNPMVG0EFF9V
複製代碼

這裏的x0由SerialNumber變成了真正的序列號,而且就是在0x196008690對應的子程序sub_19600738C裏面拿到的,因此咱們就這樣一個猜想,在MGCopyAnswer函數中,x0做爲一個參數傳入,而且在內部進行了一系列複雜的運算,拿到了獲取序列號的「鑰匙」x1,而後在sub_19600738C中拿到了最終的序列號。這裏筆者也沒有對序列號的拿到在進行進一步的深究,這裏蘋果作了很大的限制,再繼續研究恐怕也是收穫不大,並且咱們在這裏已經能拿到序列號了。

3、驗證結果

接下來就是驗證的過程了,咱們寫一個tweak來驗證,固然也能夠用其餘方式來驗證: tweak的建立這裏就不贅述了,我把個人tweak和makefile文件內容貼一下:

tweak文件:

tweak.xm:
extern "C" NSString *MGCopyAnswer(NSString*);
%hook SpringBoard
- (void)applicationDidFinishLaunching:(id)application {
%orig;
NSString *serialNumber = [NSString stringWithFormat:@"%@",[MGCopyAnswer(@"SerialNumber") autorelease]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:serialNumber message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}
%end
複製代碼

這裏注入系統的SpringBoard,在SB啓動的時候hook住applicationDidFinishLaunching:函數,而且在這個函數裏面添加獲取序列號的代碼,而且以彈框的形式展示出來。

makefile文件:

THEOS_DEVICE_IP = 192.168.0.115
include $(THEOS)/makefiles/common.mk
TWEAK_NAME = SerialNumber
SerialNumber_FILES = Tweak.xm
include $(THEOS_MAKE_PATH)/tweak.mk
SerialNumber_LDFLAGS = -lMobileGestalt
after-install::
	install.exec "killall -9 SpringBoard"
複製代碼

其中有一行SerialNumber_LDFLAGS = -lMobileGestalt千萬要注意,使用的時候要加載這個靜態庫,由於SpringBoard加載的時候我也不肯定是否有加載這個庫,而後咱們驗證一下吧!

序列號驗證-獲取
序列號驗證-系統

此文參考了《iOS逆向工程(第二版)》

相關文章
相關標籤/搜索