Snippets is a snippet manager that allows you to search previous snippets and then paste them conveniently using a spotlight-like search bar. The application costs USD15 and it is fairly poor in features and easily replaced by ClipMenu.
The difference between Snippets and ClipMenu is that Snippets costs money and offers less and obtrusive features compared to ClipMenu. There is no reason to use Snippets over ClipMenu. After we cracked Snippets, we threw it into the trash, where it belongs, after a few minutes of use.
The copy-protection is also insanely easy to circumvent. When the application starts it triggers a few trial-based checks based on boolean calls such as isTrial
.
Insanely easy, just find updateTrialControls
and shortwire the procedure so it does nothing. We just jump from 0x1000072b0
to 0x10000746a
where the procedure just returns. The trial stuff is never even activated.
methImpl_MainWindowController_updateTrialControls: 00000001000072a1 55 push rbp 00000001000072a2 4889E5 mov rbp, rsp 00000001000072a5 4157 push r15 00000001000072a7 4156 push r14 00000001000072a9 4154 push r12 00000001000072ab 53 push rbx 00000001000072ac 4883EC10 sub rsp, 0x10 00000001000072b0 E9B5010000 jmp 0x10000746a ... 000000010000746a 4883C410 add rsp, 0x10 ; XREF=0x1000072ec, 0x10000732d, 0x1000072b0 000000010000746e 5B pop rbx 000000010000746f 415C pop r12 0000000100007471 415E pop r14 0000000100007473 415F pop r15 0000000100007475 5D pop rbp 0000000100007476 C3 ret
That's it (yes, really) for version 1.4.1, it just doesn't even warrant the effort to be cracked . . .
This is not necessary, but let's skip some of the checks when the application starts up. We jump at 0x100003540
over the date-check.
methImpl_AppDelegate_applicationDidFinishLaunching_: 000000010000351d 55 push rbp 000000010000351e 4889E5 mov rbp, rsp 0000000100003521 4156 push r14 0000000100003523 53 push rbx 0000000100003524 4883EC30 sub rsp, 0x30 0000000100003528 4889FB mov rbx, rdi 000000010000352b 30C0 xor al, al 000000010000352d E878A80400 call _PFMoveToApplicationsFolderIfNecessary_10004ddaa 0000000100003532 E89D000700 call imp___stubs__NSUpdateDynamicServices 0000000100003537 30C0 xor al, al 0000000100003539 E8D0960500 call _SALicenseIsValid_10005cc0e 000000010000353e 84C0 test al, al 0000000100003540 E924000000 jmp 0x100003569 0000000100003545 90 nop 0000000100003546 90 nop 0000000100003547 90 nop 0000000100003548 90 nop ... 0000000100003569 488B35C8000D00 mov rsi, qword [ds:objc_sel_standardUserDefaults] ; @selector(standardUserDefaults) XREF=0x100003540, 0x100003555 0000000100003570 488B3D49490D00 mov rdi, qword [ds:bind__OBJC_CLASS_$_NSUserDefaults] 0000000100003577 4C8B35E2DD0A00 mov r14, qword [ds:imp___got__objc_msgSend]
The trial timer is started when the application finished loading and we have disabled that. For reference, one could also disable the trial timer and then the date check above.
methImpl_MainWindowController_startTrialTimer: 0000000100007117 55 push rbp 0000000100007118 4889E5 mov rbp, rsp 000000010000711b 4156 push r14 000000010000711d 53 push rbx 000000010000711e 4883EC10 sub rsp, 0x10 0000000100007122 E9DE000000 jmp 0x100007205 .. 0000000100007205 4883C410 add rsp, 0x10 ; XREF=0x100007122 0000000100007209 5B pop rbx 000000010000720a 415E pop r14 000000010000720c 5D pop rbp 000000010000720d FFE0 jmp rax
methImpl_MainWindowController_stopTrialTimer: 000000010000720f 55 push rbp 0000000100007210 4889E5 mov rbp, rsp 0000000100007213 53 push rbx 0000000100007214 E93E000000 jmp 0x100007257 0000000100007219 90 nop 000000010000721a 90 nop 000000010000721b 90 nop 000000010000721c 90 nop 000000010000721d 90 nop 000000010000721e 90 nop ... 0000000100007257 4883C408 add rsp, 0x8 ; XREF=0x100007214 000000010000725b 5B pop rbx 000000010000725c 5D pop rbp 000000010000725d C3 ret
This is a little more challenging. On first sight, if we run:
strings Snippets.app/Contents/Resources/English.lproj/MainMenu.nib | grep Reg
and there are no "Registration…" results, slightly misleading us into believing that the "Registration…" menu item is not present in the NIB - but it has to be.
So, Using NIBUnlocker, we dump the Snippets.app/Contents/Resources/English.lproj/MainMenu.nib
and find the showRegistrationWindow
string. Following the ref="22"
, we find a menu item with ID 22, but with a base64 encoded name.
Decoding, we get:
echo "UmVnaXN0cmF0aW9u4oCm" | base64 -d Registration…
There it is.
Now we proceed to eliminate all references to id="22"
. The lines below are snippets that were taken out.
<object class="NSMenuItem" id="22"> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSMenu" ref="9"/> <string key="NSKeyEquiv"></string> <string type="base64-UTF8" key="NSTitle">UmVnaXN0cmF0aW9u4oCm</string> <reference key="NSOnImage" ref="311"/> <reference key="NSMixedImage" ref="312"/> </object> ... <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">showRegistrationWindow:</string> <reference key="source" ref="307"/> <reference key="destination" ref="22"/> </object> <int key="connectionID">852</int> </object> ... <reference ref="22"/> <object class="IBObjectRecord"> <int key="objectID">705</int> <reference key="object" ref="22"/> <reference key="parent" ref="9"/> </object>
Now it is time to produce the new NIB, so we run:
ibtool --errors --warnings --notices --output-format human-readable-text --compile MainMenu.nib MainMenu.xib
and replace the original file.
Starting up Snippets, we get a nice clean menu without any ''Registration…" option.