The crack procedure involves cracking both the Jump Desktop
binary as well as muting an annoying popup from the Sparkle
binary of the Sparkle Framework.
Jump Desktop's protection is minor and usually revolves around this type of construct that you can observe predominantly in the disassembly at each step where a license check or trial days check is involved:
00000001000c5a51 803D50E5050100 cmp byte [ds:0x101123fa8], 0x0 00000001000c5a58 E994040000 jne 0x1000c5ef1
after which, license and trial checks follow.
A simple example of this sequence can be found in sub_1000c5a40
, the one responsible for popping-up the annoying nag window when the application launches in case the application is not registered:
; Basic Block Input Regs: <nothing> - Killed Regs: <nothing> sub_1000c5a40: 00000001000c5a40 55 push rbp ; XREF=0x100004eaf, 0x1000c5f05 00000001000c5a41 4889E5 mov rbp, rsp 00000001000c5a44 4157 push r15 00000001000c5a46 4156 push r14 00000001000c5a48 4155 push r13 00000001000c5a4a 4154 push r12 00000001000c5a4c 53 push rbx 00000001000c5a4d 4883EC68 sub rsp, 0x68 00000001000c5a51 803D50E5050100 cmp byte [ds:0x101123fa8], 0x0 00000001000c5a58 0F8593040000 jne 0x1000c5ef1 ; Basic Block Input Regs: rax - Killed Regs: rdx rbx rsi rdi r13 00000001000c5a5e 488B3DFB510201 mov rdi, qword [ds:objc_classref_FileHelpers] 00000001000c5a65 488B35342C0201 mov rsi, qword [ds:objc_sel_getApplicaitonDocumentsPath] ; @selector(getApplicaitonDocumentsPath) 00000001000c5a6c 4C8B2DE5FEF900 mov r13, qword [ds:imp___got__objc_msgSend] 00000001000c5a73 41FFD5 call r13 00000001000c5a76 488B352B2C0201 mov rsi, qword [ds:objc_sel_stringByAppendingPathComponent_] ; @selector(stringByAppendingPathComponent:) 00000001000c5a7d 488D151C67FE00 lea rdx, qword [ds:cfstring_License_jdlicense] ; @"License.jdlicense" ; ... bla bla bla ... ; Basic Block Input Regs: <nothing> - Killed Regs: rbx rsp rbp r12 r13 r14 r15 00000001000c5ef1 4883C468 add rsp, 0x68 ; XREF=0x1000c5a58, 0x1000c5acf 00000001000c5ef5 5B pop rbx 00000001000c5ef6 415C pop r12 00000001000c5ef8 415D pop r13 00000001000c5efa 415E pop r14 00000001000c5efc 415F pop r15 00000001000c5efe 5D pop rbp 00000001000c5eff C3 ret
That being said, it is sufficient to search for XFREF 0x101123fa8
and turn the jne
into a jmp
for each reference. This takes care of everything including license checks, trial days remaining, and so on, and so forth…
The Sparkle framework uses some ridiculous cryptographic check to verify that the binary Jump Desktop
has not been altered. If it has, then it displays an annoying error but without any other consequences.
So, reaching into Frameworks/Sparkle.framework/Versions/Current
and loading-up the Sparkle
binary, we find the following construct in methImpl_SUUpdater_initForBundle_
:
nput Regs: rdx rdi - Killed Regs: rax rbp rsi rdi r12 r14 methImpl_SUUpdater_initForBundle_: 000000000001324c 4154 push rbp 000000000001324f 4883EC18 sub rsp, 0x18 0000000000013253 4989D4 mov r12, rdx 0000000000013256 48897DC8 mov qword [ss:rbp-0x40+var_8], rdi 000000000001325a 488B05D7790100 mov rax, qword [ds:0x2ac38] 0000000000013261 488945D0 mov qword [ss:rbp-0x40+var_16], rax 0000000000013265 488B352C670100 mov rsi, qword [ds:objc_sel_init] ; @selector(init) 000000000001326c 488D7DC8 lea rdi, qword [ss:rbp-0x40+var_8] 0000000000013270 E83B2D0000 call imp___stubs__objc_msgSendSuper2 0000000000013275 4989C6 mov r14, rax 0000000000013278 4D85E4 test r12, r12 000000000001327b 7517 jne 0x13294 ; Basic Block Input Regs: rax - Killed Regs: rsi rdi r12 000000000001327d 488B3DE4770100 mov rdi, qword [ds:bind__OBJC_CLASS_$_NSBundle] 0000000000013284 488B351D6F0100 mov rsi, qword [ds:objc_sel_mainBundle] ; @selector(mainBundle) 000000000001328b FF156FFE0000 call qword [ds:imp___got__objc_msgSend] 0000000000013291 4989C4 mov r12, rax ; Basic Block Input Regs: r14 - Killed Regs: <nothing> 0000000000013294 4D85F6 test r14, r14 ; XREF=0x1327b 0000000000013297 7410 je 0x132a9 ; Basic Block Input Regs: r14 - Killed Regs: rsi rdi 0000000000013299 488B3508750100 mov rsi, qword [ds:objc_sel_registerAsObserver] ; @selector(registerAsObserver) 00000000000132a0 4C89F7 mov rdi, r14 00000000000132a3 FF1557FE0000 call qword [ds:imp___got__objc_msgSend] ; Basic Block Input Regs: rax r12 - Killed Regs: rdx rbx rsi rdi r13 00000000000132a9 488B1D28B00100 mov rbx, qword [ds:_sharedUpdaters] ; XREF=0x13297 00000000000132b0 488B3DC1780100 mov rdi, qword [ds:bind__OBJC_CLASS_$_NSValue] 00000000000132b7 488B35DA740100 mov rsi, qword [ds:objc_sel_valueWithNonretainedObject_] ; @selector(valueWithNonretainedObject:) 00000000000132be 4C8B2D3BFE0000 mov r13, qword [ds:imp___got__objc_msgSend] 00000000000132c5 4C89E2 mov rdx, r12 00000000000132c8 41FFD5 call r13 00000000000132cb 488B3596660100 mov rsi, qword [ds:objc_sel_objectForKeyedSubscript_] ; @selector(objectForKeyedSubscript:) 00000000000132d2 4889DF mov rdi, rbx 00000000000132d5 4889C2 mov rdx, rax 00000000000132d8 41FFD5 call r13 00000000000132db 4889C3 mov rbx, rax 00000000000132de 4885DB test rbx, rbx ; HERE IS THE INTERESTING PART 00000000000132e1 90 nop ; used to be je 0x13305 00000000000132e2 90 nop 00000000000132e3 488B35C6670100 mov rsi, qword [ds:objc_sel_release] ; @selector(release) 00000000000132ea 4C89F7 mov rdi, r14 00000000000132ed 41FFD5 call r13 00000000000132f0 488B35B1670100 mov rsi, qword [ds:objc_sel_retain] ; @selector(retain) 00000000000132f7 4889DF mov rdi, rbx 00000000000132fa 41FFD5 call r13 00000000000132fd 4989C6 mov r14, rax 0000000000013300 E964010000 jmp 0x13469 ; ... bla bla bla... 0000000000013469 4C89F0 mov rax, r14 ; XREF=0x13300, 0x13308 000000000001346c 4883C418 add rsp, 0x18 0000000000013470 5B pop rbx 0000000000013471 415C pop r12 0000000000013473 415D pop r13 0000000000013475 415E pop r14 0000000000013477 415F pop r15 0000000000013479 5D pop rbp 000000000001347a C3 ret
Around 0x132e1
, we find a je
that would lead to the part displaying the nag modal screen. So we eliminate the je
and replace it with two nop
s leading up to the jmp
at 0x13300
, which throws us out of the function without nagging us.
With the nags out of the way and the Sparkle popup removed, we obtain a fully-functional Jump Desktop application.