Let us proceed to the removal of the annoyances.
Contrary to other applications, PhotoSweeper X inserts the Registration menu item in the code instead of using the NIB files. Since the Registration
menu item first appears at application startup, this actually is easy to find and occurs in applicationDidFinishLaunching
. The culprit is the following sequence of lines:
00000001000c92b0 488B0D690B2E00 mov rcx, qword [ds:objc_sel_registerProduct_] ; @selector(registerProduct:) 00000001000c92b7 488B355A0B2E00 mov rsi, qword [ds:objc_sel_insertItemWithTitle_action_keyEquivalent_atIndex_] ; @selector(insertItemWithTitle:action:keyEquivalent:atIndex:) 00000001000c92be 4889DF mov rdi, rbx 00000001000c92c1 4889C2 mov rdx, rax 00000001000c92c4 4D89F0 mov r8, r14 00000001000c92c7 4D89E1 mov r9, r12 00000001000c92ca 41FFD5 call r13
located half-way during the initialisation process. The easiest way to go about this is to nop
the entire sequence - or, of course, using the flow-equivalence described on the cracks page, jump from the first instruction right to the next one after the last.
A few lines of code later, in the applicationDidFinishLaunching
function, we find:
00000001000c944a 488B35FF092E00 mov rsi, qword [ds:objc_sel_startLicensing_timeTrial_withWindow_] ; @selector(startLicensing:timeTrial:withWindow:) 00000001000c9451 B901000000 mov ecx, 0x1 00000001000c9456 4531C0 xor r8d, r8d 00000001000c9459 4889DF mov rdi, rbx 00000001000c945c 4889C2 mov rdx, rax 00000001000c945f 41FFD5 call r13 00000001000c9462 488B35EF092E00 mov rsi, qword [ds:objc_sel_productActivated] ; @selector(productActivated) 00000001000c9469 4889DF mov rdi, rbx 00000001000c946c 41FFD5 call r13 00000001000c946f 84C0 test al, al 00000001000c9471 7419 je 0x1000c948c
again, this entire sequence can be nop
-ed.
One interesting thing to notice here is the objc_sel_productActivated
, which will je
in case the product is not activated.
Having said that, for the rest of the procedure, we will find references to objc_sel_productActivated
and nop
all the je
s after that and turn jne
into jmp
.
There is one trial notification that remains and that is in the handleTrialNotification
function. It can be left alone, but to make sure, let's turn jmp
to safety:
methImpl_MCAppDelegate_handleTrialNotification_: 00000001000c953d 55 push rbp 00000001000c953e 4889E5 mov rbp, rsp 00000001000c9541 4157 push r15 00000001000c9543 4156 push r14 00000001000c9545 4154 push r12 00000001000c9547 53 push rbx 00000001000c9548 4989D4 mov r12, rdx 00000001000c954b 4989FE mov r14, rdi 00000001000c954e 488B3D93342E00 mov rdi, qword [ds:bind__OBJC_CLASS_$_NSNotification] 00000001000c9555 488B35ECCB2D00 mov rsi, qword [ds:objc_sel_class] ; @selector(class) 00000001000c955c 488B1D8D432700 mov rbx, qword [ds:imp___got__objc_msgSend] 00000001000c9563 FFD3 call rbx 00000001000c9565 488B35E4CB2D00 mov rsi, qword [ds:objc_sel_isKindOfClass_] ; @selector(isKindOfClass:) 00000001000c956c 4C89E7 mov rdi, r12 00000001000c956f 4889C2 mov rdx, rax 00000001000c9572 FFD3 call rbx 00000001000c9574 4889D9 mov rcx, rbx 00000001000c9577 84C0 test al, al 00000001000c9579 E9A1000000 jmp 0x1000c961f ;... application is not registered 00000001000c961f 5B pop rbx ; XREF=0x1000c9579, 0x1000c95cf 00000001000c9620 415C pop r12 00000001000c9622 415E pop r14 00000001000c9624 415F pop r15 00000001000c9626 5D pop rbp 00000001000c9627 C3 ret
Since we will modify the binaries, Sparkle will complain about checksumming and will pop-up a nag screen that we have not signed the application with a DSA key. We can silence this issue by opening up PhotoSweeper X.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Sparkle
and changing a few things in the initialisation routines.
In the SUUpdater_initForBundle
function, we hop over the error message to suppress the popup:
000000000001aa9f 4885DB test rbx, rbx 000000000001aaa2 E93E000000 jmp 0x1aae5 000000000001aaa7 90 nop 000000000001aaa8 90 nop 000000000001aaa9 90 nop 000000000001aaaa 90 nop 000000000001aaab 4C89EF mov rdi, r13 000000000001aaae 41FFD4 call r12 000000000001aab1 488D3D08750100 lea rdi, qword [ds:cfstring_Insecure_update_error_] ; @"Insecure update error!" 000000000001aab8 488D3521750100 lea rsi, qword [ds:cfstring_For_security_reasons__you_need_to_sign_your_updates_with_a_DSA_key__See_Sparkle_s_documenta] ; @"For security reasons, you need to sign your updates with a DSA key. See Sparkle's documentation for more information." 000000000001aabf 488D15FA6F0100 lea rdx, qword [ds:cfstring_OK] ; @"OK" 000000000001aac6 31C9 xor ecx, ecx 000000000001aac8 4531C0 xor r8d, r8d 000000000001aacb 31C0 xor eax, eax 000000000001aacd E8404E0000 call imp___stubs__NSRunAlertPanel 000000000001aad2 488B35CFF40100 mov rsi, qword [ds:objc_sel_notifyDidShowModalAlert] ; @selector(notifyDidShowModalAlert) 000000000001aad9 4C89EF mov rdi, r13 000000000001aadc 41FFD4 call r12 000000000001aadf 4C8B7DC0 mov r15, qword [ss:rbp+0xffffffffffffffc0] 000000000001aae3 EB52 jmp 0x1ab37 ; Basic Block Input Regs: rax rdx rbx rbp - Killed Regs: rcx rdx r15 000000000001aae5 4885DB test rbx, rbx ; XREF=0x1aa9d, 0x1aaa2 000000000001aae8 0F94C1 sete cl 000000000001aaeb 84D2 test dl, dl 000000000001aaed 0F95C2 setne dl 000000000001aaf0 84C0 test al, al 000000000001aaf2 4C8B7DC0 mov r15, qword [ss:rbp-0x50+var_16] 000000000001aaf6 753F jne 0x1ab37 ; Basic Block Input Regs: rcx - Killed Regs: rdx 000000000001aaf8 20CA and dl, cl 000000000001aafa E938000000 jmp 0x1ab37 000000000001aaff 90 nop 000000000001ab00 90 nop 000000000001ab01 90 nop 000000000001ab02 90 nop 000000000001ab03 4C89EF mov rdi, r13 000000000001ab06 41FFD4 call r12 000000000001ab09 488D3DB0740100 lea rdi, qword [ds:cfstring_Insecure_update_error_] ; @"Insecure update error!" 000000000001ab10 488D35E9740100 lea rsi, qword [ds:cfstring_For_security_reasons__you_need_to_code_sign_your_application_or_sign_your_updates_with_a_DS] ; @"For security reasons, you need to code sign your application or sign your updates with a DSA key. See Sparkle's documentation for more information." 000000000001ab17 488D15A26F0100 lea rdx, qword [ds:cfstring_OK] ; @"OK" 000000000001ab1e 31C9 xor ecx, ecx 000000000001ab20 4531C0 xor r8d, r8d 000000000001ab23 31C0 xor eax, eax 000000000001ab25 E8E84D0000 call imp___stubs__NSRunAlertPanel 000000000001ab2a 488B3577F40100 mov rsi, qword [ds:objc_sel_notifyDidShowModalAlert] ; @selector(notifyDidShowModalAlert) 000000000001ab31 4C89EF mov rdi, r13 000000000001ab34 41FFD4 call r12 ; Basic Block Input Regs: rcx r13 xmm0 - Killed Regs: rcx rdx rsi rdi xmm0 000000000001ab37 488B1572F40100 mov rdx, qword [ds:objc_sel_startUpdateCycle] ; @selector(startUpdateCycle) XREF=0x1aaf6, 0x1aafa, 0x1aae3
Notice the two jmp
followed by the padding nop
s.