Reveal簡(jiǎn)介
Reveal能查看iOS App的視圖布局,而且能在App運(yùn)行時(shí)進(jìn)行視圖調(diào)試。
破解過(guò)程(本教程使用的Reveal版本為21)
下載下來(lái)打開(kāi)后,出現(xiàn)一個(gè)Welcome窗口擋在上面

想看看這個(gè)Welcome窗口屬于哪個(gè)類,考慮用Xcode的
View UI Hierarchy:打開(kāi)
Xcode,File -> New -> Project...,選擇 macOS -> Cocoa Framework工程創(chuàng)建好后,
Debug -> Attach to Process,選擇Reveal
Attach失敗,應(yīng)該是開(kāi)啟了反調(diào)試。
hopper打開(kāi)Reveal.app/Contents/MacOS/Reveal,搜索ptrace:
imp___stubs__ptrace:
0000000100442380 jmp qword [_ptrace_ptr] ; _ptrace, CODE XREF=EntryPoint+23
x查找引用,跳到調(diào)用的地方:
EntryPoint:
00000001003df9bb push rbp
00000001003df9bc mov rbp, rsp
00000001003df9bf push r14
00000001003df9c1 push rbx
00000001003df9c2 mov r14, rsi
00000001003df9c5 mov ebx, edi
00000001003df9c7 mov edi, 0x1f ; argument "request" for method imp___stubs__ptrace
00000001003df9cc xor esi, esi ; argument "pid" for method imp___stubs__ptrace
00000001003df9ce xor edx, edx ; argument "addr" for method imp___stubs__ptrace
00000001003df9d0 xor ecx, ecx ; argument "data" for method imp___stubs__ptrace
00000001003df9d2 call imp___stubs__ptrace
00000001003df9d7 mov edi, ebx ; argument "argc" for method imp___stubs__NSApplicationMain
00000001003df9d9 mov rsi, r14 ; argument "argv" for method imp___stubs__NSApplicationMain
00000001003df9dc pop rbx
00000001003df9dd pop r14
00000001003df9df pop rbp
00000001003df9e0 jmp imp___stubs__NSApplicationMain
這里明顯就是main函數(shù),直接jmp到NSApplicationMain即可:
選中函數(shù)的第一條指令,Modify -> Assemble Instruction...,輸入jmp imp___stubs__NSApplicationMain:
EntryPoint:
00000001003df9bb jmp imp___stubs__NSApplicationMain
修改完成后command+shift+e -> Remove Signature -> Save -> Replace,重新打開(kāi)Reveal,此時(shí)Xcode Debug -> Attach to Process 已經(jīng)能連接上了,但是報(bào)損壞:

應(yīng)該是驗(yàn)證簽名了,hopper搜索SecStaticCodeCheckValidity,沒(méi)有搜索到,可能是隱藏了符號(hào)。Xcode添加Symbolic Breakpoint...試試,果然沒(méi)有失望:
(lldb) thread backtrace
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x00007fff3e0681aa Security`SecStaticCodeCheckValidity
frame #1: 0x000000010cb02191 Reveal`___lldb_unnamed_symbol16110$$Reveal + 136
(lldb) image lookup --address 0x000000010cb02191
Address: Reveal[0x0000000100418191] (Reveal.__TEXT.__text + 4281425)
Summary: Reveal`___lldb_unnamed_symbol16110$$Reveal + 136
通過(guò)堆棧,找到驗(yàn)證簽名的地方為0x0000000100418191 。回到hopper,g -> 0x0000000100418191 -> Go,查看偽代碼:
int sub_100418109() {
r14 = [*0x100609aa0 retain];
*var_30 = 0x0;
r15 = (*0x100609a00)(0x0, var_30);
if (r15 == 0x0) {
*var_28 = 0x0;
r15 = (*0x100609a08)(var_30, 0x0, var_28);
if (r15 == 0x0) {
*var_20 = 0x0;
r15 = (*0x100609a10)(r14, 0x0, var_20);
if (r15 == 0x0) {
r15 = (*0x100609a18)(var_28, 0x1, var_20);
}
rdi = var_20;
if (rdi != 0x0) {
CFRelease(rdi);
}
}
rdi = var_28;
if (rdi != 0x0) {
CFRelease(rdi);
}
}
rdi = var_30;
if (rdi != 0x0) {
CFRelease(rdi);
}
[r14 release];
rax = r15 == 0x0 ? 0x1 : 0x0;
return rax;
}
這里出現(xiàn)了幾個(gè)地址:0x100609aa0、0x100609a00、0x100609a08、0x100609a10、0x100609a18
(lldb) image list
[ 0] D63C46A4-4A6C-3559-BF02-9A41B3AAF2CB 0x000000010c6ea000 /var/folders/nn/xpy1hqrn6s19d6dp4r69m4hr0000gn/T/AppTranslocation/FCEBF1A4-C20B-4140-AFAB-B357ACCCA528/d/Reveal.app/Contents/MacOS/Reveal
(lldb) memory read --size 8 --format x ’0x100609aa0+0xc6ea000‘
0x10ccf3aa0: 0x00007ffa52002a90 0x0000000000000000
(lldb) po 0x7ffa52002a90
anchor apple generic and identifier = "com.ittybittyapps.Reveal2" and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.13] exists or certificate leaf[field.1.2.840.113635.100.6.1.14] exists) and certificate leaf[subject.OU] = "KBY3G4JPGC"
(lldb) memory read --size 8 --format x ’0x100609a00+0xc6ea000‘
0x10ccf3a00: 0x00007fff3e0608db 0x00007fff3e060df6
0x10ccf3a10: 0x00007fff3e06596a 0x00007fff3e0681aa
(lldb) image lookup --address 0x00007fff3e0608db
Address: Security[0x000000000015c8db] (Security.__TEXT.__text + 1421739)
Summary: Security`SecCodeCopySelf
(lldb) image lookup --address 0x00007fff3e060df6
Address: Security[0x000000000015cdf6] (Security.__TEXT.__text + 1423046)
Summary: Security`SecCodeCopyStaticCode
(lldb) image lookup --address 0x00007fff3e06596a
Address: Security[0x000000000016196a] (Security.__TEXT.__text + 1442362)
Summary: Security`SecRequirementCreateWithString
(lldb) image lookup --address 0x00007fff3e0681aa
Address: Security[0x00000000001641aa] (Security.__TEXT.__text + 1452666)
Summary: Security`SecStaticCodeCheckValidity
找到了對(duì)應(yīng)關(guān)系,簡(jiǎn)單整理就可以得出源碼為:
bool sub_100418109() {
CFStringRef text = (__bridge CFStringRef)@"anchor apple generic and identifier = \"com.ittybittyapps.Reveal2\" and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.13] exists or certificate leaf[field.1.2.840.113635.100.6.1.14] exists) and certificate leaf[subject.OU] = \"KBY3G4JPGC\"";
SecCodeRef code;
OSStatus status = SecCodeCopySelf(kSecCSDefaultFlags, &code);
if (status == errSecSuccess) {
SecStaticCodeRef staticCode;
status = SecCodeCopyStaticCode(code, kSecCSDefaultFlags, &staticCode);
if (status == errSecSuccess) {
SecRequirementRef requirement;
status = SecRequirementCreateWithString(text, kSecCSDefaultFlags, &requirement);
if (status == errSecSuccess) {
status = SecStaticCodeCheckValidity(staticCode, kSecCSDefaultFlags, requirement);
}
if (requirement != NULL) {
CFRelease(requirement);
}
}
if (staticCode != NULL) {
CFRelease(staticCode);
}
}
if (code != NULL) {
CFRelease(code);
}
return status == errSecSuccess ? true : false;
}
這個(gè)函數(shù)就是校驗(yàn)簽名,沒(méi)干別的,整個(gè)函數(shù)直接return true吧:
sub_100418109:
0000000100418109 mov rax, 0x1
0000000100418110 ret
重現(xiàn)打開(kāi)reveal,又能看到Welcome界面了

看到類名DMActivationController,在Reveal.app/Contents/Frameworks/DevMateKit.framework/Versions/A/DevMateKit里面找到它的定義。
GitHub搜索DevMateKit,發(fā)現(xiàn)是一個(gè)第三方庫(kù):
https://github.com/DevMate/DevMateKit。
(以后看到這種Welcome界面,第一時(shí)間要想到是這個(gè)第三方庫(kù)了。)
hopper打開(kāi)DevMateKit
找到下面的函數(shù),直接ret完事:
-[DMActivationController runActivationWindowInMode:initialActivationInfo:withCompletionHandler:]:
000000000002564d ret
重新打開(kāi),基本功能都能用了,唯獨(dú)點(diǎn)擊help彈出的菜單項(xiàng)有些還是灰的:

搜索validateMenuItem:,將下面函數(shù)直接return YES試試:
-[IBAAppDelegate validateMenuItem:]:
000000010029bad0 mov rax, 0x1
000000010029bad7 ret
重新打開(kāi),完美破解!