破解《Reveal》

Reveal简介

Reveal能查看iOS App的视图布局,而且能在App运行时进行视图调试。

破解过程(本教程使用的Reveal版本为21)

下载下来打开后,出现一个Welcome窗口挡在上面

Welcome

想看看这个Welcome窗口属于哪个类,考虑用Xcode的View UI Hierarchy
打开XcodeFile -> New -> Project...,选择 macOS -> Cocoa Framework
工程创建好后,Debug -> Attach to Process,选择Reveal
Could not attach

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 已经能连接上了,但是报损坏:

damaged

应该是验证签名了,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 。回到hopperg -> 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

看到类名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:

搜索validateMenuItem:,将下面函数直接return YES试试:

                     -[IBAAppDelegate validateMenuItem:]:
000000010029bad0         mov        rax, 0x1
000000010029bad7         ret

重新打开,完美破解!

你可能感兴趣的:(破解《Reveal》)