ProxyCap is a tool, similar to Little Snitch that allows you to set per-application proxy settings. The registration is a simple license-check that can be circumvented by forcing the application to register and then blocking any re-validations. The result is that we managed to register the application using a picture instead of the license file…
====== B E G I N O F P R O C E D U R E ====== ; Basic Block Input Regs: <nothing> - Killed Regs: eax ebx esp meth_Controller_aboutRegister_: 00003edc 55 push ebp 00003edd 89E5 mov ebp, esp 00003edf 57 push edi 00003ee0 56 push esi 00003ee1 53 push ebx 00003ee2 83EC5C sub esp, 0x5C ... 00004028 E929000000 jmp 0x4056 0000402d 90 nop 0000402e 90 nop 0000402f 90 nop 00004030 90 nop 00004031 E80A830600 call imp___jump_table____cxa_allocate_exception 00004036 8B1510C00600 mov edx, dword [ds:imp___pointers___ZTIi] 0000403c C70001000000 mov dword [ds:eax], 0x1 00004042 C744240800000000 mov dword [ss:esp+0x8], 0x0 0000404a 89542404 mov dword [ss:esp+0x4], edx 0000404e 890424 mov dword [ss:esp], eax 00004051 E812830600 call imp___jump_table____cxa_throw ; Basic Block Input Regs: eax ebp - Killed Regs: eax edx esp ebp esi 00004056 C7042400020000 mov dword [ss:esp], 0x200 ; XREF=0x4028 ... ; Basic Block Input Regs: eax ebp - Killed Regs: eax edx esp ebp esi 00004056 C7042400020000 mov dword [ss:esp], 0x200 ; XREF=0x4028 0000405d E8D4820600 call imp___jump_table___Znam ; operator new[](unsigned long) 00004062 8B55BC mov edx, dword [ss:ebp-0x68+var_36] 00004065 89C6 mov esi, eax 00004067 8945C4 mov dword [ss:ebp-0x68+var_44], eax 0000406a C744240800020000 mov dword [ss:esp+0x8], 0x200 00004072 89442404 mov dword [ss:esp+0x4], eax 00004076 891424 mov dword [ss:esp], edx 00004079 E8300C0100 call sub_14cae 0000407e 8D45D8 lea eax, dword [ss:ebp-0x68+var_64] 00004081 890424 mov dword [ss:esp], eax 00004084 E8C1120200 call sub_2534a 00004089 E95C010000 jmp 0x41EA ... 00004293 E9A3000000 jmp 0x433B 00004298 90 nop 00004299 8B55B8 mov edx, dword [ss:ebp+0xFFFFFFFFFFFFFFB8] 0000429c C7442404E4E50200 mov dword [ss:esp+0x4], 0x2E5E4 ; "$canceled" 000042a4 891424 mov dword [ss:esp], edx 000042a7 E8F47F0600 call imp___jump_table___ZNKSs7compareEPKc ; std::string::compare(char const*) const ... ; Basic Block Input Regs: ebp - Killed Regs: eax edx esp 0000433b A178A00600 mov eax, dword [ds:objc_msg_syncDisabled] ; XREF=0x4293 00004340 89442404 mov dword [ss:esp+0x4], eax 00004344 8B4508 mov eax, dword [ss:ebp-0x68+arg_0] 00004347 890424 mov dword [ss:esp], eax 0000434a E822810600 call imp___jump_table__objc_msgSend 0000434f 8B4508 mov eax, dword [ss:ebp-0x68+arg_0] 00004352 8B5024 mov edx, dword [ds:eax+0x24] 00004355 A14CA00600 mov eax, dword [ds:objc_msg_setStringValue_] 0000435a C7442408EC4C0600 mov dword [ss:esp+0x8], 0x64CEC ; @"This copy is registered"
The successive jmp
s make sure to skip most of the license validation procedures and end in the valid registration zone.
The next target is the showAbout
method at 0x3768
:
meth_Controller_showAbout_: 00003768 55 push ebp 00003769 89E5 mov ebp, esp ... 00003789 E922000000 jmp 0x37B0 0000378e 90 nop 0000378f 90 nop 00003790 891C24 mov dword [ss:esp], ebx 00003793 89442404 mov dword [ss:esp+0x4], eax 00003797 E8D58C0600 call imp___jump_table__objc_msgSend 0000379c 8B5310 mov edx, dword [ds:ebx+0x10] 0000379f A164A00600 mov eax, dword [ds:objc_msg_center] 000037a4 891424 mov dword [ss:esp], edx 000037a7 89442404 mov dword [ss:esp+0x4], eax 000037ab E8C18C0600 call imp___jump_table__objc_msgSend 000037b0 A114C00600 mov eax, dword [ds:imp___pointers__NSApp] ; XREF=0x3789
The jmp
at 0x3789
prevents the application from re-validating the license.
The result is that you can use absolutely any irrelevant file to activate the application.
We can avoid all the above and just modify the aboutReinitLicenseStatus
so that it will permanently indicate that the application is registered:
meth_Controller_aboutReinitLicenseStatus: 00003b74 55 push ebp 00003b75 89E5 mov ebp, esp 00003b77 56 push esi 00003b78 53 push ebx 00003b79 83EC20 sub esp, 0x20 ... 00003b96 7420 je 0x3BB8 ; Basic Block Input Regs: ebp - Killed Regs: <nothing> 00003b98 807DF500 cmp byte [ss:ebp-0x28+var_29], 0x0 00003b9c 740A je 0x3BA8 ; Basic Block Input Regs: <nothing> - Killed Regs: esp 00003b9e C7442404C3A00200 mov dword [ss:esp+0x4], 0x2A0C3 ; "This copy is registered" 00003ba6 EB08 jmp 0x3BB0 ; Basic Block Input Regs: <nothing> - Killed Regs: esp 00003ba8 C7442404DBA00200 mov dword [ss:esp+0x4], 0x2A0DB ; "30 days trial copy" XREF=0x3b9c ; Basic Block Input Regs: esi - Killed Regs: esp 00003bb0 893424 mov dword [ss:esp], esi ; XREF=0x3ba6 00003bb3 E829870600 call imp___jump_table___ZNSs6assignEPKc ; std::string::assign(char const*) ; Basic Block Input Regs: ebp - Killed Regs: eax ebx esp 00003bb8 8B4508 mov eax, dword [ss:ebp-0x28+arg_0] ; XREF=0x3b96
We use nop
s to slide to the registered zone by cancelling out both je
s at 0x3b96
respectively 0x3b9c
:
00003b92 807DF400 cmp byte [ss:ebp+0xFFFFFFFFFFFFFFF4], 0x0 00003b96 90 nop 00003b97 90 nop 00003b98 807DF500 cmp byte [ss:ebp+0xFFFFFFFFFFFFFFF5], 0x0 00003b9c 90 nop 00003b9d 90 nop 00003b9e C7442404C3A00200 mov dword [ss:esp+0x4], 0x2A0C3 ; "This copy is registered" 00003ba6 EB08 jmp 0x3BB0
The result is that the about window will always show ProxyCap registered as in the image above.