iOS9获取手机序列号serialNumber(UDID)
iOS9獲取手機(jī)序列號(hào)serialNumber(UDID)
http://www.jianshu.com/p/b48524a4aff2
? 作者? LeonLei? 關(guān)注 2016.10.26 11:44*? 字?jǐn)?shù) 2631? 閱讀 358 評(píng)論 1 喜歡 1
前言
在iOS7之前我們可以通過- (NSString *)uniqueIdentifier這個(gè)方法獲取iPhone的唯一標(biāo)識(shí)符,也叫作UDID。不過自從iOS7蘋果就把這個(gè)方法給禁了,此時(shí)我們想要獲取iPhone的唯一標(biāo)識(shí)符就很困難。
不過蘋果提供一個(gè)叫做IDFA的標(biāo)識(shí)符,這個(gè)IDFA是廣告標(biāo)識(shí)符用來追蹤廣告投放的,不過用戶可以在設(shè)置中手動(dòng)重置IDFA,可靠性很低,目前常見的兩種標(biāo)記iPhone的方式為?
- openUDID?
- IDFA或UUID+keychain?
這兩種模式都有個(gè)弊端,用戶重置手機(jī)或者刷機(jī)唯一標(biāo)識(shí)符會(huì)發(fā)生變化,不過對(duì)于大多數(shù)情況是夠用了。看來蘋果是把路給封死了,有沒有辦法拿到之前的UDID呢?我們注意到iPhone的設(shè)置通用關(guān)于里面有手機(jī)的硬件信息,其中有一個(gè)serialNumber,這個(gè)serialnumber就是我們查詢手機(jī)是否過保的依據(jù),那么它肯定是唯一的,所以下文是圍繞這個(gè)進(jìn)行的探索。最終是可以拿到這個(gè)serialNumber的, 不過由于蘋果的沙盒限制,所以只能在越獄機(jī)中拿到,如果想在非越獄機(jī)中拿到必須添加entitlements文件來獲取權(quán)限,可想而知這個(gè)應(yīng)用是無法上架的。下文僅作為逆向工程的一種思路和探索。
正文
一、SSH連接手機(jī)(USB模式)
1.映射端口
LeonLei-MBP:~ gaoshilei$ /Users/gaoshilei/Desktop/reverse/USBSSH/tcprelay.py -t 22:6666 Forwarding local port 6666 to remote port 222.連接手機(jī),并且用grep命令快速篩選當(dāng)前我們要調(diào)試的應(yīng)用Preferences,附加debugserver開始1234端口等待lldb調(diào)試
LeonLei-MBP:~ gaoshilei$ ssh root@localhost -p 6666 iPhone-5S:~ root# ps -e | grep Pre270 ?? 0:00.29 /System/Library/PrivateFrameworks/MobileSoftwareUpdate.framework/XPCServices/com.apple.MobileSoftwareUpdate.CleanupPreparePathService.xpc/com.apple.MobileSoftwareUpdate.CleanupPreparePathService1192 ?? 0:14.26 /var/db/stash/_.fP74Fg/Applications/Preferences.app/Preferences1289 ttys000 0:00.01 grep Pre iPhone-5S:~ root# debugserver *:1234 -a "Preferences" debugserver-@(#)PROGRAM:debugserver PROJECT:debugserver-340.3.51.1for arm64. Attaching to process Preferences... Listening to port 1234 for a connection from *...3.完成以上兩步接下來就可以進(jìn)行l(wèi)ldb調(diào)試了,首先要把遠(yuǎn)端(手機(jī))的1234端口映射到本地,跟前面提到的SSH端口映射一樣
LeonLei-MBP:~ gaoshilei$ /Users/gaoshilei/Desktop/reverse/USBSSH/tcprelay.py -t 1234:1234 Forwarding local port 1234 to remote port 1234二、通過LLDB、IDA尋找線索
lldb的調(diào)試端口已經(jīng)打開,此時(shí)我們可以進(jìn)入調(diào)試
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, #0x1f0x19a3c8a48 <+4>: svc #0x800x19a3c8a4c <+8>: ret此時(shí)我們已經(jīng)成功進(jìn)入Preferences的調(diào)試階段,先c一下,讓程序繼續(xù)運(yùn)行
(lldb) c Process 1192 resuming這么做的原因是我們待會(huì)要打印image的基地址偏移,有可能在我們打印的image list中沒有我們想要的image。
此時(shí)我們已經(jīng)找到到Preference.framework的基地址偏移,見下圖
我們要找的image的序號(hào)在這里是44,它的基地址偏移為0x2e50000,我們把從iPhone中導(dǎo)出的PrivateFrameworks中的Preferences.framework丟到IDA中進(jìn)行分析,這個(gè)二進(jìn)制文件比較小,很快就分析完成,在前面我們已經(jīng)知道iPhone的唯一序列號(hào)serial number是通過PSListController生成的,并且我們知道這是一個(gè)cell,我們要去調(diào)試[PSListController tableView:cellForRowAtIndexPath:]這個(gè)方法,從中找到cell值的來源,從而找到獲取序列號(hào)的方法。
__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, __text:00000001908040CC STP X26, X25, [SP, __text:00000001908040D0 STP X24, X23, [SP, __text:00000001908040D4 STP X22, X21, [SP, __text:00000001908040D8 STP X20, X19, [SP, __text:00000001908040DC STP X29, X30, [SP, __text:00000001908040E0 ADD X29, SP, __text:00000001908040E4 SUB SP, SP, __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, __text:0000000190804100 LDR X1, [X8, __text:0000000190804104 MOV X0, X20 __text:0000000190804108 MOV X2, X21 __text:000000019080410C BL 0x96C39BC0 __text:0000000190804110 MOV X2, X0 __text:0000000190804114 ADRP X8, __text:0000000190804118 LDRSW X27, [X8, __text:000000019080411C LDR X0, [X20,X27] __text:0000000190804120 ADRP X8, ……我們?cè)赑reference.framework中基地址為0x190804114的位置打個(gè)斷點(diǎn),具體的做法是:
(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.1frame #0: 0x0000000193654114 Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 76 Preferences`-[PSListController tableView:cellForRowAtIndexPath:]: -> 0x193654114 <+76>: adrp x8, 539650x193654118 <+80>: ldrsw x27, [x8, #516]0x19365411c <+84>: ldr x0, [x20, x27]0x193654120 <+88>: adrp x8, 53960這里斷點(diǎn)這樣打是因?yàn)橄到y(tǒng)加載可執(zhí)行文件和各種framework的時(shí)候會(huì)有一個(gè)地址偏移,我們?cè)诖驍帱c(diǎn)的時(shí)候要把這個(gè)偏移量加上,這樣我們打的斷點(diǎn)才是準(zhǔn)確的。
可以看到我們已經(jīng)成功打了一個(gè)斷點(diǎn),斷點(diǎn)的address = 0x193654114。此時(shí)我們打印變量x0和x27的值
我們執(zhí)行ni讓程序繼續(xù)(這里的ni命令相當(dāng)于Xcode的那個(gè)下箭頭命令,也就是下一行)
(lldb) ni Process 1192 stopped * thread #1: tid = 0x523a6, 0x0000000193654118 Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 80, queue = 'com.apple.main-thread', stop reason = instruction step overframe #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, 539600x193654124 <+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 overframe #0: 0x000000019365411c Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 84 Preferences`-[PSListController tableView:cellForRowAtIndexPath:]: -> 0x19365411c <+84>: ldr x0, [x20, x27]0x193654120 <+88>: adrp x8, 539600x193654124 <+92>: ldr x22, [x8, #1368]0x193654128 <+96>: mov x1, x22 (lldb) po $x27 848(lldb) po $x0 13我們ni的兩次,程序已經(jīng)走到0x19080411C的位置,然后我們繼續(xù)打印變量x0和x27的值
(lldb) po $x0 13 (lldb) po $x27 1104打印出來的x0和x27都是隨機(jī)數(shù),還是沒有什么收獲,我們繼續(xù)
(lldb) ni Process 1192 stopped * thread #1: tid = x523a6, x0000000193654120 Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 88, queue = 'com.apple.main-thread', stop reason = instruction step overframe #0: x0000000193654120 Preferences`-[PSListController tableView:cellForRowAtIndexPath:] + 88 Preferences`-[PSListController tableView:cellForRowAtIndexPath:]: -> x193654120 <+88>: adrp x8, 53960x193654124 <+92>: ldr x22, [x8, #1368]x193654128 <+96>: mov x1, x22x19365412c <+100>: bl x199a89bc0 ; objc_msgSend (lldb) po $x0 <__NSArrayI x13105a780>( G: <PSSpecifier x12ff50cf0: ID 0, Name '' target <(null): x0>> x12ff50cf0, <PSSpecifier x12ff50f50: ID NAME_CELL_ID, Name 'Name' target <AboutDataSource: x131028390>>, G: <PSSpecifier x12ff51680: ID 2, Name '' target <(null): x0>> x12ff51680, <PSSpecifier x12ff52360: ID NETWORK, Name 'Network' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff52420: ID SONGS, Name 'Songs' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff519f0: ID VIDEOS, Name 'Videos' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff51ab0: ID PHOTOS, Name 'Photos' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff51b70: ID APPLICATIONS, Name 'Applications' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff524e0: ID User Data Capacity, Name 'Capacity' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff525a0: ID User Data Available, Name 'Available' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff526a0: ID ProductVersion, Name 'Version' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff52850: ID CARRIER_VERSION, Name 'Carrier' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff52980: ID ProductModel, Name 'Model' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff52a60: ID SerialNumber, Name 'Serial Number' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff52b90: ID MACAddress, Name 'Wi-Fi Address' target <AboutDataSource: x131028390>>, <PSSpecifier x12ff51050: ID BTMACAddress, Name 'Bluetooth' target <AboutDataSource: x131028390>>, <PSSpecifier x12fde95d0: ID ModemVersion, Name 'Modem Firmware' target <AboutDataSource: x131028390>>, G: <PSSpecifier x131031e90: ID 17, Name '' target <(null): x0>> x131031e90, <PSSpecifier x12fde9c40: ID LEGAL_AND_REGULATORY, Name 'Legal' target <(null): x0>>, G: <PSSpecifier x131029dc0: ID TRUST_STORE_GROUP, Name '' target <(null): x0>> x131029dc0, <PSSpecifier x131033520: ID TRUST_STORE, Name 'Trust Store' target <AboutDataSource: x131028390>> )我們讓程序執(zhí)行下一步,發(fā)現(xiàn)此時(shí)x0已經(jīng)有值了,可以明顯的看出,x0的值是在0x190804114~0x19080411C這段代碼生成的,下面我們的工作重點(diǎn)就是尋找這段代碼干了什么,勝利就在眼前!下面我們驗(yàn)證一下這里面到底有沒有我們要的序列號(hào):
(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; }我們打印數(shù)組中存放cell數(shù)據(jù)的object屬于哪個(gè)類,發(fā)現(xiàn)是PSSpecifier,我們找到之前導(dǎo)出的類的頭文件,發(fā)現(xiàn)這個(gè)類有一個(gè)叫做properties的實(shí)例方法,我們調(diào)用一下發(fā)現(xiàn)我們要的序列號(hào)就在里面value = DNPMVG0EFF9V,這跟iPhone設(shè)置中看到的序列號(hào)是一致的。猜測(cè)這個(gè)數(shù)組里面存放著系統(tǒng)設(shè)置中PSUIAboutController中所有cel的數(shù)據(jù),這個(gè)數(shù)組下一個(gè)肯定要傳遞到cell生成的方法中,這個(gè)就不做驗(yàn)證了,大事重要,我們繼續(xù)找序列號(hào)的生成方法。
這個(gè)PSSpecifier中有一個(gè)AboutDataSource對(duì)象,這個(gè)非常可疑,從名稱上可以判斷,這個(gè)類是專門用于數(shù)據(jù)處理的,不過在這之前我們還是先驗(yàn)證一下,在0x190804114~0x19080411C這段地址中,執(zhí)行了_PSListController._specifiers,我們從PSListController的頭文件(下文有講怎么獲取)中可以看到有一個(gè)specifiers屬性,我們?cè)贗DA分析的文件中找到[PSListController specifiers],我們先定位到方法在二進(jìn)制文件中的位置:
然后在這里面下個(gè)斷點(diǎn)看看會(huì)發(fā)生什么
(lldb) br s -a 0x1907FE4D0+0x198e58640 Breakpoint 9: where = Preferences`-[PSListController specifiers] + 40, address = 0x000000019364e4d0我們從設(shè)置中進(jìn)入通用>關(guān)于,發(fā)現(xiàn)一開始就走到了這個(gè)斷點(diǎn),我們猜測(cè),一進(jìn)入關(guān)于頁面,系統(tǒng)會(huì)首先把所有cell的數(shù)據(jù)都準(zhǔn)備好,然后加載UI
Process 1192 stopped * thread #1: tid = 0x523a6, 0x000000019364e4d0 Preferences`-[PSListController specifiers] + 40, queue = 'com.apple.main-thread', stop reason = breakpoint 9.1frame #0: 0x000000019364e4d0 Preferences`-[PSListController specifiers] + 40 Preferences`-[PSListController specifiers]: -> 0x19364e4d0 <+40>: adrp x8, 539710x19364e4d4 <+44>: ldrsw x8, [x8, #536]0x19364e4d8 <+48>: ldr x9, [x19, x8]0x19364e4dc <+52>: cbz x9, 0x19364e550 ; <+168>我們打印變量x8和x9的值,看一下系統(tǒng)做了什么
(lldb) po $x8 <nil> (lldb) po $x9 PSUIAboutController并沒有數(shù)據(jù)之類的東西值得我們關(guān)注,讓斷點(diǎn)繼續(xù)往下走,走到0x19364e4dc的位置,我們?cè)俅未蛴∽兞縳8和x9的值
(lldb) n Process 1192 stopped * thread #1: tid = 0x523a6, 0x000000019364e4dc Preferences`-[PSListController specifiers] + 52, queue = 'com.apple.main-thread', stop reason = instruction step overframe #0: 0x000000019364e4dc Preferences`-[PSListController specifiers] + 52 Preferences`-[PSListController specifiers]: -> 0x19364e4dc <+52>: cbz x9, 0x19364e550 ; <+168>0x19364e4e0 <+56>: adrp x9, 539710x19364e4e4 <+60>: ldrsw x23, [x9, #540]0x19364e4e8 <+64>: orr w9, wzr, #0x1 (lldb) po $x8 952 (lldb) po $x9 <AboutDataSource: 0x131130730>此時(shí)的變量x9已經(jīng)變成了AboutDataSource,這里驗(yàn)證了我們上一步的猜想,所以我們重點(diǎn)來研究它,我們先找到這個(gè)類在哪個(gè)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: AboutDataSource : PSSpecifierDataSource {這里要說明一下iOS-Runtime-Headers-9.1這個(gè)文件夾是iOS9.1系統(tǒng)的所有頭文件(共有+私有),這個(gè)你可以自己導(dǎo)(iOS9之后只能用runtime導(dǎo),class-dump已經(jīng)不行了),你也可以拿現(xiàn)成的用,github上面已經(jīng)有雷鋒把所有系統(tǒng)的頭文件都導(dǎo)出來了,直接下載就可以了。我們發(fā)現(xiàn)AboutDataSource這個(gè)類在PrivateFrameworks/PreferencesUI.framework中,先看一下這個(gè)類里面有什么方法和屬性,有一個(gè)方法- (void)_loadValues;?我們對(duì)它進(jìn)行分析。這里又要借助IDA分析,把PreferencesUI這個(gè)二進(jìn)制文件丟到IDA里面,在0x19091EBB8這個(gè)位置打個(gè)斷點(diǎn)
(lldb) br s -a 0x19091EBB8+0x2e50000 Breakpoint 3: where = PreferencesUI`-[AboutDataSource _loadValues] + 1956, address = 0x000000019376ebb8接下來我們進(jìn)入關(guān)于來觸發(fā)斷點(diǎn)
(lldb) po (char *) $x28 "_setValue:forSpecifierWithKey:"在這里打印變量x28的值,發(fā)現(xiàn)它是一個(gè)方法名,從名稱來看是給specifier賦值的,看來我們要尋找的真相已經(jīng)很近了,讓代碼走到下面的位置0x19376ebd8
Process 2107 stopped * thread #1: tid = 0xe8e23, 0x000000019376ebd8 PreferencesUI`-[AboutDataSource _loadValues] + 1988, queue = 'com.apple.main-thread', stop reason = instruction step overframe #0: 0x000000019376ebd8 PreferencesUI`-[AboutDataSource _loadValues] + 1988 PreferencesUI`-[AboutDataSource _loadValues]: -> 0x19376ebd8 <+1988>: bl 0x198e58640 ; MGCopyAnswer0x19376ebdc <+1992>: mov x22, x00x19376ebe0 <+1996>: mov x1, x190x19376ebe4 <+2000>: bl 0x199a89bc0 ; objc_msgSend (lldb) po $x0 SerialNumber此時(shí)我們打印的x0是一個(gè)NSCFConstantString,本質(zhì)就是一個(gè)NSString,繼續(xù)ni讓程序運(yùn)行到0x19376ebdc
Process 2107 stopped * thread #1: tid = 0xe8e23, 0x000000019376ebdc PreferencesUI`-[AboutDataSource _loadValues] + 1992, queue = 'com.apple.main-thread', stop reason = instruction step overframe #0: 0x000000019376ebdc PreferencesUI`-[AboutDataSource _loadValues] + 1992 PreferencesUI`-[AboutDataSource _loadValues]: -> 0x19376ebdc <+1992>: mov x22, x00x19376ebe0 <+1996>: mov x1, x190x19376ebe4 <+2000>: bl 0x199a89bc0 ; objc_msgSend 0x19376ebe8 <+2004>: cbnz x0, 0x19376ec4c ; <+2104> (lldb) po $x0 DNPMVG0EFF9V在這里我們打印了變量x0的值為DNPMVG0EFF9V,這就是我們苦苦尋找的序列號(hào)。不難看出,序列號(hào)就是在0x19376ebd8這行拿到的,范圍越來越小,敵人無路可逃!下面我們就要對(duì)這行進(jìn)行分析,我們按照之前的步驟,再次走到0x19376ebd8這個(gè)位置,這不過這次我們不要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 intoframe #0: 0x0000000198e58640 libMobileGestalt.dylib`MGCopyAnswer libMobileGestalt.dylib`MGCopyAnswer: -> 0x198e58640 <+0>: movz x1, #00x198e58644 <+4>: b 0x198e58648 ; ___lldb_unnamed_symbol64$$libMobileGestalt.dyliblibMobileGestalt.dylib`___lldb_unnamed_symbol64$$libMobileGestalt.dylib:0x198e58648 <+0>: stp x24, x23, [sp, #-64]!0x198e5864c <+4>: stp x22, x21, [sp, #16]此時(shí)跳入了一個(gè)靜態(tài)庫libMobileGestalt.dylib,我們可以在usr/lib/ibMobileGestalt.dylib找到它,我們將它扔進(jìn)IDA,用當(dāng)前的addr減去libMobileGestalt.dylib的基地址偏移得到它的靜態(tài)地址0x196008640,對(duì)應(yīng)的是一個(gè)函數(shù)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, __text:0000000196008644 B sub_196008648 __text:0000000196008644 ; End of function _MGCopyAnswer這個(gè)函數(shù)最外層只有兩行代碼,將立即數(shù)0賦給x1,然后跳進(jìn)了子程序sub_196008648,跳進(jìn)去之后進(jìn)行了一些很復(fù)雜的運(yùn)算,這里就不做介紹了,里面的實(shí)現(xiàn)大概是這樣的:
x0是作為一個(gè)參數(shù)傳入的,并且這里x0的值為SerialNumber,在地址為0x196008678的地方,這個(gè)函數(shù)中x1變成了一串隨機(jī)數(shù),有點(diǎn)像MD5加密之后的東西,應(yīng)該是“鑰匙”
在0x196008690這里,我們setp-into這個(gè)函數(shù),在函數(shù)的末尾返回值的地方0x196007474打個(gè)斷點(diǎn),打印返回值x0
(lldb) po $x0 DNPMVG0EFF9V這里的x0由SerialNumber變成了真正的序列號(hào),并且就是在0x196008690對(duì)應(yīng)的子程序sub_19600738C里面拿到的,所以我們就這樣一個(gè)猜測(cè),在MGCopyAnswer函數(shù)中,x0作為一個(gè)參數(shù)傳入,并且在內(nèi)部進(jìn)行了一系列復(fù)雜的運(yùn)算,拿到了獲取序列號(hào)的“鑰匙”x1,然后在sub_19600738C中拿到了最終的序列號(hào)。這里筆者也沒有對(duì)序列號(hào)的拿到在進(jìn)行進(jìn)一步的深究,這里蘋果做了很大的限制,再繼續(xù)研究恐怕也是收獲不大,而且我們?cè)谶@里已經(jīng)能拿到序列號(hào)了。?
三、驗(yàn)證結(jié)果
接下來就是驗(yàn)證的過程了,我們寫一個(gè)tweak來驗(yàn)證,當(dāng)然也可以用其他方式來驗(yàn)證:
tweak的創(chuàng)建這里就不贅述了,我把我的tweak和makefile文件內(nèi)容貼一下:
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這里注入系統(tǒng)的SpringBoard,在SB啟動(dòng)的時(shí)候hook住applicationDidFinishLaunching:函數(shù),并且在這個(gè)函數(shù)里面添加獲取序列號(hào)的代碼,并且以彈框的形式展現(xiàn)出來。?
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千萬要注意,使用的時(shí)候要加載這個(gè)靜態(tài)庫,因?yàn)镾pringBoard加載的時(shí)候我也不確定是否有加載這個(gè)庫,然后我們驗(yàn)證一下吧!
序列號(hào)驗(yàn)證-獲取
序列號(hào)驗(yàn)證-系統(tǒng)
總結(jié)
以上是生活随笔為你收集整理的iOS9获取手机序列号serialNumber(UDID)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蹦迪--我的黑白玫瑰~!
- 下一篇: 微信小程序 - 商城项目 - 图片详情预