Reveal简介
Reveal能查看iOS App的视图布局,而且能在App运行时进行视图调试。
破解过程(本教程使用的Reveal版本为21)
下载下来打开后,出现一个Welcome窗口挡在上面
想看看这个Welcome窗口属于哪个类,考虑用Xcode的
View UI Hierarchy
:打开
Xcode
,File -> New -> Project...
,选择 macOS -> Cocoa Framework
工程创建好后,
Debug -> Attach to Process
,选择Reveal
Attach失败,应该是开启了反调试。
hopper
打开Reveal.app/Contents/MacOS/Reveal
,搜索ptrace
:
imp___stubs__ptrace:
0000000100442380 jmp qword [_ptrace_ptr] ; _ptrace, CODE XREF=EntryPoint+23
x
查找引用,跳到调用的地方:
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
函数,直接jmp到NSApplicationMain
即可:
选中函数的第一条指令,Modify -> Assemble Instruction...
,输入jmp imp___stubs__NSApplicationMain
:
EntryPoint:
00000001003df9bb jmp imp___stubs__NSApplicationMain
修改完成后command+shift+e -> Remove Signature -> Save -> Replace
,重新打开Reveal,此时Xcode Debug -> Attach to Process
已经能连接上了,但是报损坏:
应该是验证签名了,hopper
搜索SecStaticCodeCheckValidity
,没有搜索到,可能是隐藏了符号。Xcode
添加Symbolic Breakpoint...
试试,果然没有失望:
(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
通过堆栈,找到验证签名的地方为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;
}
这里出现了几个地址: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
找到了对应关系,简单整理就可以得出源码为:
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;
}
这个函数就是校验签名,没干别的,整个函数直接return true
吧:
sub_100418109:
0000000100418109 mov rax, 0x1
0000000100418110 ret
重现打开reveal,又能看到Welcome界面了
看到类名DMActivationController
,在Reveal.app/Contents/Frameworks/DevMateKit.framework/Versions/A/DevMateKit
里面找到它的定义。
GitHub搜索DevMateKit
,发现是一个第三方库:
https://github.com/DevMate/DevMateKit。
(以后看到这种Welcome界面,第一时间要想到是这个第三方库了。)
hopper
打开DevMateKit
找到下面的函数,直接ret完事:
-[DMActivationController runActivationWindowInMode:initialActivationInfo:withCompletionHandler:]:
000000000002564d ret
重新打开,基本功能都能用了,唯独点击help
弹出的菜单项有些还是灰的:
搜索validateMenuItem:
,将下面函数直接return YES
试试:
-[IBAAppDelegate validateMenuItem:]:
000000010029bad0 mov rax, 0x1
000000010029bad7 ret
重新打开,完美破解!