教程背景:

第一部分 Hopper disassember動態調試: 3

第二部分 LLDB動態調試 14

第三部分 使用Radare2動態調試 27

第四部分 分析整理算法 32

第五部分 使用Python編寫keygen 34

第六部分 使用Swift編寫keygen 36


教程背景:

在Youtube閒逛時,無意間發現了飄雲閣飛樹大神(tree_fly)的頻道,地址如下:


Hopper Disassembler試用版如何使用_Desktop

其中一個教程感覺挺經典,鏈接地址為: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載入程序如圖所示:

 

Hopper Disassembler試用版如何使用_Desktop_02

 

點擊本地調試器按鈕調出動態調試工具,如圖所示:

 

Hopper Disassembler試用版如何使用_Desktop_03

大概介紹一下調試工具的幾個控制按鈕如圖所示:

 

Hopper Disassembler試用版如何使用_字符串_04

我們這裏主要用到執行和單步跟蹤按鈕以及運行到指針位置的按鈕,在寄存器選項卡中可以實時觀察寄存器值的變化,在命令調試選項卡中我們可以使用命令來查看寄存器的信息。

在動態調試之前,我們必須先分析下程序的執行流程,找到合理的斷點位置,設置好斷點才可以進行下一步的動態調試。

首先我們運行程序,點擊“Open License File”按鈕,選擇crackme自帶的演示license文件,然後點擊”Open”按鈕,出現如圖所示的信息提示。

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

 

Hopper Disassembler試用版如何使用_Desktop_05

右擊該字符串選擇“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;

 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的判斷函數,在函數列表中搜索包含此字符串的函數,得到如下函數信息,此函數為判斷序列號的關鍵函數。

 

Hopper Disassembler試用版如何使用_字符串_06

 

在此函數的開始位置使用F9下一個斷點,如圖所示:

 

Hopper Disassembler試用版如何使用_動態調試_07

下面我們開始動態調試

點擊“執行”按鈕,會有幾次系統中斷,我們繼續點擊“執行”按鈕,直到程序運行起來,然後打開license文件後,程序會停到我們設置的斷點位置,如圖:

 

Hopper Disassembler試用版如何使用_字符串_08

我們可以單步跟蹤到想要到位置,也可以選中我們要跳轉的位置然後點擊“運行到指針位置”按鈕直接跳轉到該位置,使用po $eax顯示用户名的內容,如圖所示:

 

Hopper Disassembler試用版如何使用_字符串_09

繼續單步執行或者跳轉到特定指針位置,來到下圖位置:

Hopper Disassembler試用版如何使用_字符串_10

 

繼續單步跟蹤或者運行到指定位置,如圖:

Hopper Disassembler試用版如何使用_動態調試_11

繼續單步跟蹤,來到如圖位置:

 

Hopper Disassembler試用版如何使用_Desktop_12

繼續單步跟蹤或者按F6,來到如圖位置:

 

Hopper Disassembler試用版如何使用_字符串_13

  

切換GPR選項卡,手動將eax的值設置為1,即al值為1,如圖所示:

 

Hopper Disassembler試用版如何使用_字符串_14

點擊執行按鈕,程序提示license有效,如圖:

 

Hopper Disassembler試用版如何使用_Desktop_15

使用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="" cnotallow="" 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="" cnotallow="" name="0x00002733" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"
0x0000273b - 0x0000273c 1 --x sw break enabled cmd="" cnotallow="" name="0x0000273b" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"
0x0000274d - 0x0000274e 1 --x sw break enabled cmd="" cnotallow="" name="0x0000274d" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"
0x00002750 - 0x00002751 1 --x sw break enabled cmd="" cnotallow="" name="0x00002750" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"
0x00002766 - 0x00002767 1 --x sw break enabled cmd="" cnotallow="" 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 versinotallow="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist versinotallow="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)
 _ in chars.randomElement()!.description }
    .reduce("", +)
 
let serial = name
    .sha1()
    .uppercased()
 
let xmlstring = """
<?xml versinotallow="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist versinotallow="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文件,驗證通過。