Hopper+LLDB+Radare2 动态调试教程 (MacOS版)

教程背景: 

第一部分 Hopper disassember动态调试: 3

第二部分 LLDB动态调试 14

第三部分 使用Radare2动态调试 27

第四部分 分析整理算法 32

第五部分 使用Python编写keygen 34

第六部分 使用Swift编写keygen 36

 

教程背景:

Youtube闲逛时,无意间发现了飘云阁飞树大神(tree_fly)的频道,地址如下:

https://www.youtube.com/channel/UCcyUJWGHkxVtA59143ojUxA

 

其中一个教程感觉挺经典,链接地址为:https://www.youtube.com/watch?v=pfteHwOmQIM

教程中使用的Crackme地址为:https://reverse.put.as/wp-content/uploads/2010/05/3-Fox.zip

此教程中详细介绍了使用Hopper和LLDB来动态调试程序,爆破注册流程,并且给出如何提取算法以及编写注册机,因为算法相对来讲比较简单,所以适合菜鸟练手使用。于是乎我亲自操作了一遍,觉得有必要分享给菜菜们,本教程中Hopper和LLDB动态调试以及使用Swift编写注册机属完全拷贝大神的操作,如果飞树大神觉得我有侵权行为,请提示删帖。

第一部分 Hopper disassember动态调试:

使用hopper载入程序如图所示:

 

 

点击本地调试器按钮调出动态调试工具,如图所示:

 

大概介绍一下调试工具的几个控制按钮如图所示:

 

我们这里主要用到执行和单步跟踪按钮以及运行到指针位置的按钮,在寄存器选项卡中可以实时观察寄存器值的变化,在命令调试选项卡中我们可以使用命令来查看寄存器的信息。

在动态调试之前,我们必须先分析下程序的执行流程,找到合理的断点位置,设置好断点才可以进行下一步的动态调试。

首先我们运行程序,点击“Open License File”按钮,选择crackme自带的演示license文件,然后点击”Open”按钮,出现如图所示的信息提示。

我们在Hopper中搜索字符串“The license is not valid”,

 

右击该字符串选择“References to...”,在出现的窗口中点击地址跳转到调用处“cfstring_The_license_is_not_valid”,继续使用同样的方法找到调用该字符串的源头,

找到-[FoxAppDelegate openLicenseFile:]这个函数。内容如下:

0000279c         push       ebp                                                 ; Objective C Implementation defined at 0x40f4 (instance method)

0000279d         mov        ebp, esp

0000279f         push       edi

000027a0         push       esi

000027a1         push       ebx

000027a2         sub        esp, 0x3c

000027a5         mov        eax, dword [ebp+self]

000027a8         mov        dword [ebp+var_1C], eax

000027ab         mov        dword [esp+0x48+var_40], 0x3048                     ; @"foxlicense"

000027b3         mov        eax, dword [objc_msg_arrayWithObject_]              ; @selector(arrayWithObject:)

000027b8         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend

000027bc         mov        eax, dword [cls_NSArray]                            ; cls_NSArray

000027c1         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend

000027c4         call       imp___symbol_stub__objc_msgSend

000027c9         mov        esi, eax

000027cb         mov        eax, dword [objc_msg_openPanel]                     ; @selector(openPanel)

000027d0         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend

000027d4         mov        eax, dword [cls_NSOpenPanel]                        ; cls_NSOpenPanel

000027d9         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend

000027dc         call       imp___symbol_stub__objc_msgSend

000027e1         mov        ebx, eax

000027e3         mov        dword [esp+0x48+var_40], 0x0

000027eb         mov        eax, dword [objc_msg_setAllowsMultipleSelection_]   ; @selector(setAllowsMultipleSelection:)

000027f0         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend

000027f4         mov        dword [esp+0x48+var_48], ebx                        ; argument "instance" for method imp___symbol_stub__objc_msgSend

000027f7         call       imp___symbol_stub__objc_msgSend

000027fc         call       imp___symbol_stub__NSHomeDirectory

00002801         mov        dword [esp+0x48+var_38], esi

00002805         mov        dword [esp+0x48+var_3C], 0x0

0000280d         mov        dword [esp+0x48+var_40], eax

00002811         mov        eax, dword [objc_msg_runModalForDirectory_file_types_] ; @selector(runModalForDirectory:file:types:)

00002816         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend

0000281a         mov        dword [esp+0x48+var_48], ebx                        ; argument "instance" for method imp___symbol_stub__objc_msgSend

0000281d         call       imp___symbol_stub__objc_msgSend

00002822         mov        eax, dword [objc_msg_filename]                      ; @selector(filename)

00002827         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend

0000282b         mov        dword [esp+0x48+var_48], ebx                        ; argument "instance" for method imp___symbol_stub__objc_msgSend

0000282e         call       imp___symbol_stub__objc_msgSend

00002833         mov        dword [esp+0x48+var_40], eax

00002837         mov        eax, dword [objc_msg_dictionaryWithContentsOfFile_] ; @selector(dictionaryWithContentsOfFile:)

0000283c         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend

00002840         mov        eax, dword [cls_NSDictionary]                       ; cls_NSDictionary

00002845         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend

00002848         call       imp___symbol_stub__objc_msgSend

0000284d         mov        edi, eax

0000284f         mov        dword [esp+0x48+var_40], 0x3058                     ; @"regName"

00002857         mov        edx, dword [objc_msg_objectForKey_]                 ; @selector(objectForKey:)

0000285d         mov        dword [esp+0x48+var_44], edx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend

00002861         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend

00002864         call       imp___symbol_stub__objc_msgSend

00002869         mov        ebx, eax

0000286b         mov        dword [esp+0x48+var_40], 0x3068                     ; @"regNumber"

00002873         mov        eax, dword [objc_msg_objectForKey_]                 ; @selector(objectForKey:)

00002878         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend

0000287c         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend

0000287f         call       imp___symbol_stub__objc_msgSend

00002884         mov        dword [esp+0x48+var_3C], ebx

00002888         mov        dword [esp+0x48+var_40], eax

0000288c         mov        eax, dword [objc_msg_validateSerial_forName_]       ; @selector(validateSerial:forName:)

00002891         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend

00002895         mov        edx, dword [ebp+var_1C]

00002898         mov        dword [esp+0x48+var_48], edx                        ; argument "instance" for method imp___symbol_stub__objc_msgSend

0000289b         call       imp___symbol_stub__objc_msgSend

000028a0         test       al, al

000028a2         jne        loc_2908

Pseudo-code 如下:

void -[FoxAppDelegate openLicenseFile:](void * self, void * _cmd, void * arg_8) {

    stack[2049] = _cmd;

    stack[2048] = self;

    var_1C = self;

    esi = [NSArray arrayWithObject:@"foxlicense", stack[2032], stack[2033], stack[2034], stack[2035], stack[2036], stack[2037], stack[2038], stack[2039], stack[2040], stack[2041], stack[2042], stack[2043], stack[2044], stack[2045], stack[2046], stack[2047], stack[2048]];

    ebx = [NSOpenPanel openPanel];

    [ebx setAllowsMultipleSelection:0x0];

    eax = NSHomeDirectory();

    [ebx runModalForDirectory:eax file:0x0 types:esi];

    eax = [ebx filename];

    eax = [NSDictionary dictionaryWithContentsOfFile:eax];

    edi = eax;

    if ([var_1C validateSerial:[edi objectForKey:@"regNumber"] forName:[eax objectForKey:@"regName"]] == 0x0) {

            NSRunAlertPanel(@"Error!", @"The license is not valid.", @"Try again", 0x0, 0x0);

            eax = *(var_1C + 0x8);

            [eax setStringValue:@""];

    }

    else {

            NSRunAlertPanel(@"Success!", @"The license is valid.", @"OK", 0x0, 0x0);

            ebx = *(var_1C + 0x8);

            eax = [edi objectForKey:@"regName"];

            [ebx setStringValue:eax];

            ebx = *(var_1C + 0xc);

            [NSString stringWithFormat:@"%@...", [[edi objectForKey:@"regNumber"] substringToIndex:0xf]];

    }

    objc_msgSend(stack[2048], stack[2049]);

    return;

}

分析得到这个函数调用一个函数名包含validateSerial的判断函数,在函数列表中搜索包含此字符串的函数,得到如下函数信息,此函数为判断序列号的关键函数。

 

 

在此函数的开始位置使用F9下一个断点,如图所示:

 

下面我们开始动态调试

点击执行按钮,会有几次系统中断,我们继续点击执行按钮,直到程序运行起来,然后打开license文件后,程序会停到我们设置的断点位置,如图:

 

我们可以单步跟踪到想要到位置,也可以选中我们要跳转的位置然后点击运行到指针位置按钮直接跳转到该位置,使用po $eax显示用户名的内容,如图所示:

 

继续单步执行或者跳转到特定指针位置,来到下图位置:

 

继续单步跟踪或者运行到指定位置,如图:

继续单步跟踪,来到如图位置:

 

继续单步跟踪或者按F6,来到如图位置:

 

  

切换GPR选项卡,手动将eax的值设置为1,即al值为1,如图所示:

 

点击执行按钮,程序提示license有效,如图:

 

使用Hopper动态调试并且爆破成功。

 

第二部分 LLDB动态调试

使用lldb命令加载目标程序,重要的一步当然是设置断点,参考hopper分析出的函数名,我们在函数-[FoxAppDelegate validateSerial:forName:]的起始位置下个断点,操作如下:

 

zyjsupers-MacBook-Air:~ zyjsuper$ lldb ~/Desktop/3-Fox/Fox.app      #加载目标程序

(lldb) target create "/Users/zyjsuper/Desktop/3-Fox/Fox.app"

Current executable set to '/Users/zyjsuper/Desktop/3-Fox/Fox.app' (i386).

(lldb) r                                                              #运行目标程序

Process 995 launched: '/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox' (i386)

/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.200.3/Common/ChunkCompression.cpp:49: Error: unsupported compressor 8

/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.200.3/Libraries/CompressData/CompressData.c:353: Error: Unknown compression scheme encountered for file '/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/Exceptions.plist'

/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.200.3/Common/ChunkCompression.cpp:49: Error: unsupported compressor 8

/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.200.3/Libraries/CompressData/CompressData.c:353: Error: Unknown compression scheme encountered for file '/System/Library/CoreServices/CoreTypes.bundle/Contents/Library/AppExceptions.bundle/Exceptions.plist'

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP     #Ctrl+C中断运行,程序暂停。

    frame #0: 0xa7c191d2 libsystem_kernel.dylib`mach_msg_trap + 10

libsystem_kernel.dylib`mach_msg_trap:

->  0xa7c191d2 <+10>: retl   

    0xa7c191d3 <+11>: nop    

 

libsystem_kernel.dylib`mach_msg_overwrite_trap:

    0xa7c191d4 <+0>:  movl   $0xffffffe0, %eax         ; imm = 0xFFFFFFE0 

    0xa7c191d9 <+5>:  calll  0xa7c20a9c                ; _sysenter_trap

Target 0: (Fox) stopped.

(lldb) b -[FoxAppDelegate validateSerial:forName:]                               #设置断点

Breakpoint 1: where = Fox`-[FoxAppDelegate validateSerial:forName:], address = 0x00002721

(lldb) br list                                                                    #列出断点

Current breakpoints:

1: name = '-[FoxAppDelegate validateSerial:forName:]', locations = 1, resolved = 1, hit count = 0

  1.1: where = Fox`-[FoxAppDelegate validateSerial:forName:], address = 0x00002721, resolved, hit count = 0 

 

(lldb) c                                                                    #继续执行程序

 

程序重新运行,点击打开license文件按钮,选择license文件路径后点击打开按钮,

.......................

 

/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.200.3/Common/ChunkCompression.cpp:49: Error: unsupported compressor 8

/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.200.3/Libraries/CompressData/CompressData.c:353: Error: Unknown compression scheme encountered for file '/System/Library/PrivateFrameworks/FinderKit.framework/Resources/Base.lproj/ColumnPreview.nib'

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1     #程序中断在我们设置的断点位置。

    frame #0: 0x00002721 Fox`-[FoxAppDelegate validateSerial:forName:]

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2721 <+0>: pushl  %ebp

    0x2722 <+1>: movl   %esp, %ebp

    0x2724 <+3>: subl   $0x18, %esp

    0x2727 <+6>: movl   0x4008, %eax

Target 0: (Fox) stopped.

(lldb) 

Process 995 resuming

 

(lldb) dis                             #反汇编-[FoxAppDelegate validateSerial:forName:]这个函数

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2721 <+0>:  pushl  %ebp

    0x2722 <+1>:  movl   %esp, %ebp

    0x2724 <+3>:  subl   $0x18, %esp

    0x2727 <+6>:  movl   0x4008, %eax

    0x272c <+11>: movl   %eax, 0x4(%esp)

    0x2730 <+15>: movl   0x14(%ebp), %eax

    0x2733 <+18>: movl   %eax, (%esp)

    0x2736 <+21>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x273b <+26>: movl   0x4004, %edx

    0x2741 <+32>: movl   %edx, 0x4(%esp)

    0x2745 <+36>: movl   %eax, (%esp)

    0x2748 <+39>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x274d <+44>: movl   0x10(%ebp), %edx

    0x2750 <+47>: movl   %edx, 0x8(%esp)

    0x2754 <+51>: movl   0x4000, %edx

    0x275a <+57>: movl   %edx, 0x4(%esp)

    0x275e <+61>: movl   %eax, (%esp)

    0x2761 <+64>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x2766 <+69>: testb  %al, %al

    0x2768 <+71>: setne  %al

    0x276b <+74>: leave  

0x276c <+75>: retl   

 

(lldb) po (char *)*(int *)0x4008                           #将0x4008这个地址的内容转化为字符串

"sha1HexHash"                                         #此处对应为调用sha1HexHash

 

(lldb) po (char *)*(int *)0x4004

"uppercaseString"                                      #此处对应为调用uppercaseString

 

(lldb) po (char *)*(int *)0x4000

"isEqualToString:"                                      #此处对应为调用isEqualToString

 

按照Hopper分析的流程,我们需要分析这个验证序列号的函数每一步都在做什么,那么我在关键位置设置几个断点,下面我就一步步分析来决定断点设置在什么位置。

(lldb) si                                #单步步进跟踪

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x00002722 Fox`-[FoxAppDelegate validateSerial:forName:] + 1

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2722 <+1>:  movl   %esp, %ebp

    0x2724 <+3>:  subl   $0x18, %esp

    0x2727 <+6>:  movl   0x4008, %eax

    0x272c <+11>: movl   %eax, 0x4(%esp)

Target 0: (Fox) stopped.

(lldb) si

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x00002724 Fox`-[FoxAppDelegate validateSerial:forName:] + 3

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2724 <+3>:  subl   $0x18, %esp

    0x2727 <+6>:  movl   0x4008, %eax

    0x272c <+11>: movl   %eax, 0x4(%esp)

    0x2730 <+15>: movl   0x14(%ebp), %eax

Target 0: (Fox) stopped.

(lldb) si

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x00002727 Fox`-[FoxAppDelegate validateSerial:forName:] + 6

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2727 <+6>:  movl   0x4008, %eax

    0x272c <+11>: movl   %eax, 0x4(%esp)

    0x2730 <+15>: movl   0x14(%ebp), %eax

    0x2733 <+18>: movl   %eax, (%esp)

Target 0: (Fox) stopped.

(lldb) po $eax

10017

 

(lldb) si

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x0000272c Fox`-[FoxAppDelegate validateSerial:forName:] + 11

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x272c <+11>: movl   %eax, 0x4(%esp)

    0x2730 <+15>: movl   0x14(%ebp), %eax

    0x2733 <+18>: movl   %eax, (%esp)

    0x2736 <+21>: calll  0x2bda                    ; symbol stub for: objc_msgSend

Target 0: (Fox) stopped.

(lldb) po $eax

11782

 

(lldb) si

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x00002730 Fox`-[FoxAppDelegate validateSerial:forName:] + 15

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2730 <+15>: movl   0x14(%ebp), %eax

    0x2733 <+18>: movl   %eax, (%esp)

    0x2736 <+21>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x273b <+26>: movl   0x4004, %edx

Target 0: (Fox) stopped.

(lldb) po $eax

11782

 

(lldb) si

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x00002733 Fox`-[FoxAppDelegate validateSerial:forName:] + 18

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2733 <+18>: movl   %eax, (%esp)

    0x2736 <+21>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x273b <+26>: movl   0x4004, %edx

    0x2741 <+32>: movl   %edx, 0x4(%esp)

Target 0: (Fox) stopped.

(lldb) po $eax                                   #这一步得到license文件用户名信息

hawke

 

(lldb) dis

Fox`-[FoxAppDelegate validateSerial:forName:]:

    0x2721 <+0>:  pushl  %ebp

    0x2722 <+1>:  movl   %esp, %ebp

    0x2724 <+3>:  subl   $0x18, %esp

    0x2727 <+6>:  movl   0x4008, %eax

    0x272c <+11>: movl   %eax, 0x4(%esp)

    0x2730 <+15>: movl   0x14(%ebp), %eax

->  0x2733 <+18>: movl   %eax, (%esp)

    0x2736 <+21>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x273b <+26>: movl   0x4004, %edx

    0x2741 <+32>: movl   %edx, 0x4(%esp)

    0x2745 <+36>: movl   %eax, (%esp)

    0x2748 <+39>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x274d <+44>: movl   0x10(%ebp), %edx

    0x2750 <+47>: movl   %edx, 0x8(%esp)

    0x2754 <+51>: movl   0x4000, %edx

    0x275a <+57>: movl   %edx, 0x4(%esp)

    0x275e <+61>: movl   %eax, (%esp)

    0x2761 <+64>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x2766 <+69>: testb  %al, %al

    0x2768 <+71>: setne  %al

    0x276b <+74>: leave  

    0x276c <+75>: retl   

(lldb) b *0x2733                                              #在0x2733位置设置断点

Breakpoint 2: where = Fox`-[FoxAppDelegate validateSerial:forName:] + 18, address = 0x00002733

(lldb) si

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x00002736 Fox`-[FoxAppDelegate validateSerial:forName:] + 21

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2736 <+21>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x273b <+26>: movl   0x4004, %edx

    0x2741 <+32>: movl   %edx, 0x4(%esp)

    0x2745 <+36>: movl   %eax, (%esp)

Target 0: (Fox) stopped.

(lldb) ni                                                    #遇到call函数调用使用单步步过跟踪

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step over

    frame #0: 0x0000273b Fox`-[FoxAppDelegate validateSerial:forName:] + 26

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x273b <+26>: movl   0x4004, %edx

    0x2741 <+32>: movl   %edx, 0x4(%esp)

    0x2745 <+36>: movl   %eax, (%esp)

    0x2748 <+39>: calll  0x2bda                    ; symbol stub for: objc_msgSend

Target 0: (Fox) stopped.

(lldb) dis

Fox`-[FoxAppDelegate validateSerial:forName:]:

    0x2721 <+0>:  pushl  %ebp

    0x2722 <+1>:  movl   %esp, %ebp

    0x2724 <+3>:  subl   $0x18, %esp

    0x2727 <+6>:  movl   0x4008, %eax

    0x272c <+11>: movl   %eax, 0x4(%esp)

    0x2730 <+15>: movl   0x14(%ebp), %eax

    0x2733 <+18>: movl   %eax, (%esp)

    0x2736 <+21>: calll  0x2bda                    ; symbol stub for: objc_msgSend

->  0x273b <+26>: movl   0x4004, %edx

    0x2741 <+32>: movl   %edx, 0x4(%esp)

    0x2745 <+36>: movl   %eax, (%esp)

    0x2748 <+39>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x274d <+44>: movl   0x10(%ebp), %edx

    0x2750 <+47>: movl   %edx, 0x8(%esp)

    0x2754 <+51>: movl   0x4000, %edx

    0x275a <+57>: movl   %edx, 0x4(%esp)

    0x275e <+61>: movl   %eax, (%esp)

    0x2761 <+64>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x2766 <+69>: testb  %al, %al

    0x2768 <+71>: setne  %al

    0x276b <+74>: leave  

    0x276c <+75>: retl   

(lldb) po $eax                                   #用户名经过sha1HexHash函数加密得到hash值

587377f4518ef068e17b393074c0a2183cd055d2

 

(lldb) b * 0x273b

Breakpoint 3: no locations (pending).

WARNING:  Unable to resolve breakpoint to any actual locations.

(lldb) b *0x273b

Breakpoint 4: where = Fox`-[FoxAppDelegate validateSerial:forName:] + 26, address = 0x0000273b

(lldb) si

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x00002741 Fox`-[FoxAppDelegate validateSerial:forName:] + 32

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2741 <+32>: movl   %edx, 0x4(%esp)

    0x2745 <+36>: movl   %eax, (%esp)

    0x2748 <+39>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x274d <+44>: movl   0x10(%ebp), %edx

Target 0: (Fox) stopped.

(lldb) po $edx

2437303558

 

(lldb) si

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x00002745 Fox`-[FoxAppDelegate validateSerial:forName:] + 36

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2745 <+36>: movl   %eax, (%esp)

    0x2748 <+39>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x274d <+44>: movl   0x10(%ebp), %edx

    0x2750 <+47>: movl   %edx, 0x8(%esp)

Target 0: (Fox) stopped.

(lldb) po $edx

2437303558

 

(lldb) po $eax

587377f4518ef068e17b393074c0a2183cd055d2

 

(lldb) po $eax

587377f4518ef068e17b393074c0a2183cd055d2

 

(lldb) po $edx

2437303558

 

(lldb) si

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x00002748 Fox`-[FoxAppDelegate validateSerial:forName:] + 39

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2748 <+39>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x274d <+44>: movl   0x10(%ebp), %edx

    0x2750 <+47>: movl   %edx, 0x8(%esp)

    0x2754 <+51>: movl   0x4000, %edx

Target 0: (Fox) stopped.

(lldb) po $edx

2437303558

 

(lldb) po $eax

587377f4518ef068e17b393074c0a2183cd055d2

 

(lldb) ni

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step over

    frame #0: 0x0000274d Fox`-[FoxAppDelegate validateSerial:forName:] + 44

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x274d <+44>: movl   0x10(%ebp), %edx

    0x2750 <+47>: movl   %edx, 0x8(%esp)

    0x2754 <+51>: movl   0x4000, %edx

    0x275a <+57>: movl   %edx, 0x4(%esp)

Target 0: (Fox) stopped.

(lldb) po $eax                                                #得到的hash值转换成大写

587377F4518EF068E17B393074C0A2183CD055D2

 

(lldb) dis

Fox`-[FoxAppDelegate validateSerial:forName:]:

    0x2721 <+0>:  pushl  %ebp

    0x2722 <+1>:  movl   %esp, %ebp

    0x2724 <+3>:  subl   $0x18, %esp

    0x2727 <+6>:  movl   0x4008, %eax

    0x272c <+11>: movl   %eax, 0x4(%esp)

    0x2730 <+15>: movl   0x14(%ebp), %eax

    0x2733 <+18>: movl   %eax, (%esp)

    0x2736 <+21>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x273b <+26>: movl   0x4004, %edx

    0x2741 <+32>: movl   %edx, 0x4(%esp)

    0x2745 <+36>: movl   %eax, (%esp)

    0x2748 <+39>: calll  0x2bda                    ; symbol stub for: objc_msgSend

->  0x274d <+44>: movl   0x10(%ebp), %edx

    0x2750 <+47>: movl   %edx, 0x8(%esp)

    0x2754 <+51>: movl   0x4000, %edx

    0x275a <+57>: movl   %edx, 0x4(%esp)

    0x275e <+61>: movl   %eax, (%esp)

    0x2761 <+64>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x2766 <+69>: testb  %al, %al

    0x2768 <+71>: setne  %al

    0x276b <+74>: leave  

    0x276c <+75>: retl   

(lldb) b *0x274d

Breakpoint 5: where = Fox`-[FoxAppDelegate validateSerial:forName:] + 44, address = 0x0000274d

(lldb) po $edx

<nil>

 

(lldb) si

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into

    frame #0: 0x00002750 Fox`-[FoxAppDelegate validateSerial:forName:] + 47

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2750 <+47>: movl   %edx, 0x8(%esp)

    0x2754 <+51>: movl   0x4000, %edx

    0x275a <+57>: movl   %edx, 0x4(%esp)

    0x275e <+61>: movl   %eax, (%esp)

Target 0: (Fox) stopped.

(lldb) po $edx                                           #获取license文件中序列号的值

XXXX

 

(lldb) b *0x2750

Breakpoint 6: where = Fox`-[FoxAppDelegate validateSerial:forName:] + 47, address = 0x00002750

(lldb) br list

Current breakpoints:

1: name = '-[FoxAppDelegate validateSerial:forName:]', locations = 1, resolved = 1, hit count = 3

  1.1: where = Fox`-[FoxAppDelegate validateSerial:forName:], address = 0x00002721, resolved, hit count = 3 

 

2: address = Fox[0x00002733], locations = 1, resolved = 1, hit count = 0

  2.1: where = Fox`-[FoxAppDelegate validateSerial:forName:] + 18, address = 0x00002733, resolved, hit count = 0 

 

3: name = '* 0x273b', locations = 0 (pending)

 

4: address = Fox[0x0000273b], locations = 1, resolved = 1, hit count = 0

  4.1: where = Fox`-[FoxAppDelegate validateSerial:forName:] + 26, address = 0x0000273b, resolved, hit count = 0 

 

5: address = Fox[0x0000274d], locations = 1, resolved = 1, hit count = 0

  5.1: where = Fox`-[FoxAppDelegate validateSerial:forName:] + 44, address = 0x0000274d, resolved, hit count = 0 

 

6: address = Fox[0x00002750], locations = 1, resolved = 1, hit count = 0

  6.1: where = Fox`-[FoxAppDelegate validateSerial:forName:] + 47, address = 0x00002750, resolved, hit count = 0

 

经过一步步分析,我添加了上述5个断点,方便重新运行分析。

继续分析..........

 

(lldb) dis

Fox`-[FoxAppDelegate validateSerial:forName:]:

    0x2721 <+0>:  pushl  %ebp

    0x2722 <+1>:  movl   %esp, %ebp

    0x2724 <+3>:  subl   $0x18, %esp

    0x2727 <+6>:  movl   0x4008, %eax

    0x272c <+11>: movl   %eax, 0x4(%esp)

    0x2730 <+15>: movl   0x14(%ebp), %eax

    0x2733 <+18>: movl   %eax, (%esp)

    0x2736 <+21>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x273b <+26>: movl   0x4004, %edx

    0x2741 <+32>: movl   %edx, 0x4(%esp)

    0x2745 <+36>: movl   %eax, (%esp)

    0x2748 <+39>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x274d <+44>: movl   0x10(%ebp), %edx

->  0x2750 <+47>: movl   %edx, 0x8(%esp)

    0x2754 <+51>: movl   0x4000, %edx

    0x275a <+57>: movl   %edx, 0x4(%esp)

    0x275e <+61>: movl   %eax, (%esp)

    0x2761 <+64>: calll  0x2bda                    ; symbol stub for: objc_msgSend

    0x2766 <+69>: testb  %al, %al

    0x2768 <+71>: setne  %al

    0x276b <+74>: leave  

    0x276c <+75>: retl   

(lldb) b *0x2766                                       #在比较license序列号函数之后设置断点                                  

Breakpoint 7: where = Fox`-[FoxAppDelegate validateSerial:forName:] + 69, address = 0x00002766

(lldb) c

Process 995 resuming

Process 995 stopped

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 7.1

    frame #0: 0x00002766 Fox`-[FoxAppDelegate validateSerial:forName:] + 69

Fox`-[FoxAppDelegate validateSerial:forName:]:

->  0x2766 <+69>: testb  %al, %al

    0x2768 <+71>: setne  %al

    0x276b <+74>: leave  

    0x276c <+75>: retl   

Target 0: (Fox) stopped.

(lldb) register read al                  #读取寄存器al的值

      al = 0x00

(lldb) register write al 1                                           #手动将寄存器al的值置为1

(lldb) c      

  

license验证成功,使用lldb动态调试加手动爆破成功,如图所示:

 

 

 第三部分 使用Radare2动态调试

使用r2命令调试程序,-d参数进入调试模式。

 -A    run 'aaa' command to analyze all referenced code

 -d    debug the executable 'file' or running process 'pid'

 

zyjsupers-MacBook-Air:~ zyjsuper$ r2 -Ad ~/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox   

= attach 2181 2181

bin.baddr 0x00001000

Using 0x1000

asm.bits 32

[x] Analyze all flags starting with sym. and entry0 (aa)

[Warning: Invalid range. Use different search.in=? or anal.in=dbg.maps.x

Warning: Invalid range. Use different search.in=? or anal.in=dbg.maps.x

[x] Analyze function calls (aac)

[x] Analyze len bytes of instructions for references (aar)

[x] Check for objc references

[x] Check for vtables

[TOFIX: aaft can't run in debugger mode.ions (aaft)

[x] Type matching analysis for all functions (aaft)

[x] Use -AA or aaaa to perform additional experimental analysis.

 -- ♥ --

[0x0001101c]> afl                        #显示函数列表

0x00002698    3 63           entry0

0x000026fa    1 9            main

0x00002bd4    1 6            sym.imp.exit

0x00004068   99 4716 -> 4803 sym..objc_class_name_FoxAppDelegate

0x00003104    6 3924         sym._NXArgc

0x00003100    6 3928         sym._NXArgv

0x000030f8    6 3936         sym.___progname

0x00001000    1 1            map.Fox.r_x

0x000026d8    1 20           sym.dyld_stub_binding_helper

0x000026ec    1 14           sym.__dyld_func_lookup

0x00002703    1 5            sym.public_int_FoxAppDelegate::applicationDidFinishLaunching_int

0x00002708    1 11           sym.public_int_FoxAppDelegate::window

0x00002713    1 14           sym.public_int_FoxAppDelegate::setWindow_int

0x00002721    1 76           sym.public_int_FoxAppDelegate::validateSerial_int__int

0x00002bda    1 6            sym.imp.objc_msgSend

0x0000276d    1 47           sym.public_int_FoxAppDelegate::awakeFromNib

0x0000279c    4 575          sym.public_int_FoxAppDelegate::openLicenseFile_int

0x000029db    1 60           sym.public_int_NSString_CocoaCryptoHashing_::sha1HexHash

0x00002a17    1 60           sym.public_int_NSString_CocoaCryptoHashing_::sha1Hash

0x00002a53    3 143          sym.public_int_NSData_CocoaCryptoHashing_::sha1Hash

0x00002bb6    1 6            sym.imp.CC_SHA1

0x00002bce    1 6            sym.imp.__stack_chk_fail

0x00002ae2    5 211          sym.public_int_NSData_CocoaCryptoHashing_::sha1HexHash

0x00002be0    1 6            sym.imp.sprintf

0x00002be6    3 36           sym._stub_helpers

0x00002bbc    1 6            sym.imp.NSApplicationMain

0x00002bc2    1 6            sym.imp.NSHomeDirectory

0x00002bc8    1 6            sym.imp.NSRunAlertPanel

[0x0001101c]> db sym.public_int_FoxAppDelegate::validateSerial_int__int     #在函数起始位置设置断点。

[0x0001101c]> dc                                                        #运行程序

程序运行起来,打开license文件验证..........

.....................

/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.200.3/Libraries/CompressData/CompressData.c:353: Error: Unknown compression scheme encountered for file '/System/Library/PrivateFrameworks/FinderKit.framework/Resources/Base.lproj/ColumnPreview.nib'

hit breakpoint at: 2721

[0x00002721]> pdf                                               #显示函数内容

    ;-- eax:

            ;-- eip:

┌ (fcn) sym.public_int_FoxAppDelegate::validateSerial_int__int 76

│   sym.public_int_FoxAppDelegate::validateSerial_int__int (int32_t arg_10h, int32_t arg_14h);

│           ; arg int32_t arg_10h @ ebp+0x10

│           ; arg int32_t arg_14h @ ebp+0x14

│           ; var int32_t var_4h @ esp+0x4

│           ; var int32_t var_8h @ esp+0x8

│           0x00002721 b    55             push ebp

│           0x00002722      89e5           mov ebp, esp

│           0x00002724      83ec18         sub esp, 0x18

│           0x00002727      a108400000     mov eax, dword str.sha1HexHash ; [0x4008:4]=0x2e06 str.sha1HexHash

│           ; DATA XREF from segment.LINKEDIT (+0x9599)

│           0x0000272c      89442404       mov dword [var_4h], eax

│           0x00002730      8b4514         mov eax, dword [arg_14h]    ; [0x14:4]=-1 ; 20

│           0x00002733      890424         mov dword [esp], eax

│           0x00002736      e89f040000     call sym.imp.objc_msgSend   ; void *objc_msgSend(void *instance, char *selector)

│           0x0000273b      8b1504400000   mov edx, dword [0x4004]     ; [0x4004:4]=0x91464d06

│           0x00002741      89542404       mov dword [var_4h], edx

│           0x00002745      890424         mov dword [esp], eax

│           0x00002748      e88d040000     call sym.imp.objc_msgSend   ; void *objc_msgSend(void *instance, char *selector)

│           0x0000274d      8b5510         mov edx, dword [arg_10h]    ; [0x10:4]=-1 ; 16

│           0x00002750      89542408       mov dword [var_8h], edx

│           0x00002754      8b1500400000   mov edx, dword map.Fox.rw   ; [0x4000:4]=0x9018aad3

│           0x0000275a      89542404       mov dword [var_4h], edx

│           0x0000275e      890424         mov dword [esp], eax

│           0x00002761      e874040000     call sym.imp.objc_msgSend   ; void *objc_msgSend(void *instance, char *selector)

│           0x00002766      84c0           test al, al

│           0x00002768      0f95c0         setne al

│           0x0000276b      c9             leave

└           0x0000276c      c3             ret

[0x00002721]> db 0x00002733                            #在合适位置设置以下几个断点

[0x00002721]> db 0x0000273b

[0x00002721]> db 0x0000274d

[0x00002721]> db 0x00002750

[0x00002721]> db 0x00002766

[0x00002721]> db                                        #显示断点列表

0x00002721 - 0x00002722 1 --x sw break enabled cmd="" cond="" name="sym.public_int_FoxAppDelegate::validateSerial_int__int" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"

0x00002733 - 0x00002734 1 --x sw break enabled cmd="" cond="" name="0x00002733" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"

0x0000273b - 0x0000273c 1 --x sw break enabled cmd="" cond="" name="0x0000273b" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"

0x0000274d - 0x0000274e 1 --x sw break enabled cmd="" cond="" name="0x0000274d" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"

0x00002750 - 0x00002751 1 --x sw break enabled cmd="" cond="" name="0x00002750" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"

0x00002766 - 0x00002767 1 --x sw break enabled cmd="" cond="" name="0x00002766" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"

 

[0x00002721]> dc

hit breakpoint at: 2733

[0x00002721]> pf xxS @eax                                  #显示eax寄存器的内存数据

0x08d7b2c0 = 0xa83f7870

0x08d7b2c4 = 0x0100078c

0x08d7b2c8 = 0x08d7b2c8 -> 0x77616805 

[0x00002721]> psz @ 0x08d7b2c8                            #显示此参数的值,即用户名

hawke

[0x00002721]> dc

hit breakpoint at: 273b

[0x00002721]> pf xxS @ eax

0x00209f90 = 0xa83f7870

0x00209f94 = 0x0100078c

0x00209f98 = 0x00209f98 -> 0x37383528 

[0x00002721]> psz @ 0x00209f98                #用户名经过sha1HexHash 函数加密后的字符串

(587377f4518ef068e17b393074c0a2183cd055d2

[0x00002721]> dc

hit breakpoint at: 274d

[0x00002721]> pf xxS @eax

0x006569a0 = 0xa83f7870

0x006569a4 = 0x010007ad

0x006569a8 = 0x006569a8 -> 0x006cd3e0 

[0x00002721]> psz @ 0x006cd3e0

(587377F4518EF068E17B393074C0A2183CD055D2           #转换成大写字母

[0x00002721]> dc

hit breakpoint at: 2750

[0x00002721]> pf xxS @ edx

0x08da1180 = 0xa83f7870

0x08da1184 = 0x0100078c

0x08da1188 = 0x08da1188 -> 0x58585804 

[0x00002721]> psz @ 0x08da1188                         #显示license文件中的序列号

XXXX

[0x00002721]> dc 

hit breakpoint at: 2766

[0x00002766]> dr al

0x00000000

[0x00002766]> dr al=1                                   #手动将寄存器al的值改成1

0x00000000 ->0x00000001

[0x00002766]> dr al

0x00000001

[0x00002766]> dc

程序验证license通过,至此,使用radare2动态调试分析爆破成功。

第四部分 分析整理算法

算法比较简单,此处引用加密与解密第四版中的介绍如下:

序列号保护的本质就是验证用户名和序列号之间的映射关系,越复杂的映射关系越难破解,根据映射关系的不同,程序检测序列号有以下几种方式:

序列号 = F (用户名)

如果把这个过程看作加密解密并进行密文对比的过程,那么用户名就是明文,而序列号则是密文,F函数就是加密算法了。这种保护方法虽然简单,但极为不安全,因为在程序运行的某一时刻,内存中一定会出现正确的序列号,也就是加密函数结束后。只要找到正确的时间点,甚至完全不用关心算法就可以完成验证。

用户名 = F (序列号)

这里是把序列号作为明文,用户名作为密文了,这种方式通常需要F函数是一种对称加密算法的解密函数,而官方生成序列号时则使用加密函数对用户名进行加密得到的,这样就不会出现内存中有正确序列号的情况。这种保护方式的关键就是解密算法了,一旦得到解密算法就有机会逆向出加密算法,这样也就完成了验证。

F1 (用户名) = F2 (序列号)

 

这种方式是上一种的扩展,它相当于多套了几层加密而已。验证方式是:用户名 = F( F2(序列号) )

特殊值 = F (用户名, 序列号)

这种保护方式的数学原理就比较复杂了,但保护效果相比前几种有了很大提升。不过在设计上有难度,并且可能出现用户名与序列号映射不唯一的情况。

 

Crackme使用的算法逻辑为: 序列号 = F (用户名)

Serial(序列号)=uppercaseString(sha1HexHash(name)),将用户名经过sha1算法加密得到的hash值,再将hash值中的字母转化成大写,就得到了用户名对应的序列号。得到了算法逻辑,我们就可以按照此算法去编写注册机。

 

第五部分 使用Python编写keygen

#!/usr/bin/env python2

#-*-coding:utf-8-*-

 

'''

@version: python2.7

@author: ‘zyjsuper‘

@license: Apache Licence

@software: PyCharm

@file: Crackme3.py

@time: $2019-08-06 18:27

'''

 

import string

import random

from hashlib import sha1

 

ch =  string.ascii_letters

 

#生成一个5到8位长度的随机用户名

def gen_name():

    result = ""

    for i in range(random.randint(5,8)):

        result = result+random.choice(ch)

    return result

 

name = gen_name()

 

#将用户名使用sha1加密

psw=sha1()

psw.update(name.encode('utf8'))

 

#将加密后的hash值转化大写字母

serial=string.upper(psw.hexdigest())

 

 

#生成对应的license文件内容

license = ('''

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>regName</key>

<string>%s</string>

<key>regNumber</key>

<string>%s</string>

</dict>

</plist>

'''  %(name,serial))

 

#将license写入文件

with open("reg.foxlicense","w") as file:

    file.write(license)

 

print '*'*55

print "Valid license file has been generated successfully!"

print '*'*55

 

第六部分 使用Swift编写keygen

zyjsupers-MacBook-Air:CrackMe3 zyjsuper$ cd ~/Desktop/3-Fox/

zyjsupers-MacBook-Air:3-Fox zyjsuper$ mkdir CrackMe3

zyjsupers-MacBook-Air:3-Fox zyjsuper$ cd CrackMe3

zyjsupers-MacBook-Air:CrackMe3 zyjsuper$ swift package init --type executable

Creating executable package: CrackMe3

Creating Package.swift

Creating README.md

Creating .gitignore

Creating Sources/

Creating Sources/CrackMe3/main.swift

Creating Tests/

Creating Tests/LinuxMain.swift

Creating Tests/CrackMe3Tests/

Creating Tests/CrackMe3Tests/CrackMe3Tests.swift

Creating Tests/CrackMe3Tests/XCTestManifests.swift

zyjsupers-MacBook-Air:CrackMe3 zyjsuper$ swift package generate-xcodeproj

generated: ./CrackMe3.xcodeproj

zyjsupers-MacBook-Air:CrackMe3 zyjsuper$ xed .

因为需要用到sha1加密函数,我们需要导入一个包cryptoswift,官方网址为:

https://cryptoswift.io/

关于此包管理的介绍如下:

Swift Package Manager

You can use Swift Package Manager and specify dependency in Package.swift by adding this:

dependencies: [

    .package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMinor(from: "1.0.0"))]

 

Package.swift文件内容改成如下:

// swift-tools-version:5.0

// The swift-tools-version declares the minimum version of Swift required to build this package.

 

import PackageDescription

 

let package = Package(

    name: "CrackMe3",

    dependencies: [

        // Dependencies declare other packages that this package depends on.

        .package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMinor(from: "1.0.0"))   //添加此行

    ],

    targets: [

        // Targets are the basic building blocks of a package. A target can define a module or a test suite.

        // Targets can depend on other targets in this package, and on products in packages which this package depends on.

        .target(

            name: "CrackMe3",

            dependencies: ["CryptoSwift"]),

        .testTarget(

            name: "CrackMe3Tests",

            dependencies: ["CrackMe3"]),

    ]

)

运行一次编译操作

zyjsupers-MacBook-Air:CrackMe3 zyjsuper$ swift run

Fetching https://github.com/krzyzanowskim/CryptoSwift.git     //需要下载CryptoSwift

[2/2] Linking /Users/zyjsuper/Desktop/3-Fox/CrackMe3/.build/x86_64-apple-macosx/debug/CrackMe3

Hello, world!

main.swift文件内容改成如下:

import CryptoSwift

 

let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +

            "abcdefghijklmnopqrstuvwxyz"

 

let name = (1...6)

    .map{ _ in chars.randomElement()!.description }

    .reduce("", +)

 

let serial = name

    .sha1()

    .uppercased()

 

let xmlstring = """

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>regName</key>

<string>\(name)</string>

<key>regNumber</key>

<string>\(serial)</string>

</dict>

</plist>

"""

print(xmlstring)

 

 

zyjsupers-MacBook-Air:CrackMe3 zyjsuper$ swift run  > ~/Desktop/Reg.Foxlicense 

生成注册license文件,验证通过。

 

 

 

 

 

posted @ 2019-08-07 19:53  heycomputer  阅读(2527)  评论(0)    收藏  举报