Anonymity 4 Proxy
Interesting
protection for a useful app.
Written by +Tsehp
This is just a shareware, built by a little company, without ready-made commercial protections.When you install it, you see the usual demo.key and say immediatly another serial protection, but this is not as simple as you think. This app is very usuful when unprotected, if you buy it they send you a good serial and a ready-made list of proxies to import, but you can do it also in the demo version using a txt file, big mistake. The work here is not to worry about the demo.key, just leave it like it is, the only restriction is that you just can't check all the proxies in the list at the same time, just one by one. They used a unusual technique to block the trial, let's see what's all about. Just remember that this app is crippled, I just used a trick to enable the all proxies check at once; if you want to have the real functionality, you have to rewrite the code. Note : This app sometimes put some buying msgs in your browser, this might be fixed in a updated essay.
After you installed the prog, you select several proxies and click the check proxy button. A messagebox appears, saying that's not possible in the demo version. You bpx the messageboxa and after one p ret you land here: .text:0040CCF2 jnz short loc_0_40CD0B .text:0040CCF4 mov eax, [esi+0F0h] .text:0040CCFA push 0 .text:0040CCFC push 0 .text:0040CCFE push 1032h .text:0040CD03 push eax .text:0040CD04 call ebx ; SendMessageA .text:0040CD06 cmp eax, 1 .text:0040CD09 jbe short loc_0_40CD2A .text:0040CD0B .text:0040CD0B loc_0_40CD0B: ; CODE XREF: sub_0_40CCE0+12j .text:0040CD0B push 0 .text:0040CD0D push 0 .text:0040CD0F push offset aDemoVersionDoe ; "Demo version does not support simultane"... .text:0040CD14 mov ecx, esi .text:0040CD16 call j_?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint) .text:0040CD1B <-land here mov eax, [esi+118h] .text:0040CD21 test eax, eax .text:0040CD23 jz short loc_0_40CD2A .text:0040CD25 pop esi .text:0040CD26 xor eax, eax .text:0040CD28 pop ebx .text:0040CD29 retn Well, it seems so simple, at line 40cd04, this app sends a wm message to syslistview32 (the a4proxy control list of proxies displayed) that sends back to a4proxy the number of proxies selected. The number is returned in eax and if more than one line selected, the messagebox appears, but the first proxy selected is checked. You just patch 40cd09 to jmp short loc_0_40CD2A, the nag doesn't appears but only the first proxy is still checked.
What's happening ? The demo.key file ? I located the validity checks, used a user.key that this app is asking...No way.
Here's a asm source that +Q from Phrozen crew sent me, it will help to study the serial decryption of this app, but remember that it is crippled, so even if you have a valid serial, it will not work if you don't apply my changes.
***/*** Written by +Q from Phrozen crew. You can download the full prog here.
Extrn CreateFileMappingA:PROC
Extrn MapViewOfFile:PROC
Extrn UnmapViewOfFile:PROC
Extrn lstrcpyA:PROC
.DATA
;---陳陳陳塚様様様様様様様様様様様様様様様様様様様様様様様様様様様幼陳陳陳----
ConstTable1 db
04Dh,042h,048h,044h,046h,04Fh,04Bh,041h,04Ah,049h,043h,04Eh,045h,040h,04Ch,047h
db
0BDh,0B2h,0B8h,0B4h,0B6h,0BFh,0BBh,0B1h,0BAh,0B9h,0B3h,0BEh,0B5h,0B0h,0BCh,0B7h
db
02Dh,022h,028h,024h,026h,02Fh,02Bh,021h,02Ah,029h,023h,02Eh,025h,020h,02Ch,027h
db
0EDh,0E2h,0E8h,0E4h,0E6h,0EFh,0EBh,0E1h,0EAh,0E9h,0E3h,0EEh,0E5h,0E0h,0ECh,0E7h
db
0FDh,0F2h,0F8h,0F4h,0F6h,0FFh,0FBh,0F1h,0FAh,0F9h,0F3h,0FEh,0F5h,0F0h,0FCh,0F7h
db
00Dh,002h,008h,004h,006h,00Fh,00Bh,001h,00Ah,009h,003h,00Eh,005h,000h,00Ch,007h
db
08Dh,082h,088h,084h,086h,08Fh,08Bh,081h,08Ah,089h,083h,08Eh,085h,080h,08Ch,087h
db
0DDh,0D2h,0D8h,0D4h,0D6h,0DFh,0DBh,0D1h,0DAh,0D9h,0D3h,0DEh,0D5h,0D0h,0DCh,0D7h
db
03Dh,032h,038h,034h,036h,03Fh,03Bh,031h,03Ah,039h,033h,03Eh,035h,030h,03Ch,037h
db
0CDh,0C2h,0C8h,0C4h,0C6h,0CFh,0CBh,0C1h,0CAh,0C9h,0C3h,0CEh,0C5h,0C0h,0CCh,0C7h
db
09Dh,092h,098h,094h,096h,09Fh,09Bh,091h,09Ah,099h,093h,09Eh,095h,090h,09Ch,097h
db
07Dh,072h,078h,074h,076h,07Fh,07Bh,071h,07Ah,079h,073h,07Eh,075h,070h,07Ch,077h
db
05Dh,052h,058h,054h,056h,05Fh,05Bh,051h,05Ah,059h,053h,05Eh,055h,050h,05Ch,057h
db
0ADh,0A2h,0A8h,0A4h,0A6h,0AFh,0ABh,0A1h,0AAh,0A9h,0A3h,0AEh,0A5h,0A0h,0ACh,0A7h
db
06Dh,062h,068h,064h,066h,06Fh,06Bh,061h,06Ah,069h,063h,06Eh,065h,060h,06Ch,067h
db
01Dh,012h,018h,014h,016h,01Fh,01Bh,011h,01Ah,019h,013h,01Eh,015h,010h,01Ch,017h
ConstTable2 db
02Ch,021h,02Ah,02Fh,029h,022h,026h,028h,020h,02Dh,023h,024h,02Eh,027h,025h,02Bh
db
0CCh,0C1h,0CAh,0CFh,0C9h,0C2h,0C6h,0C8h,0C0h,0CDh,0C3h,0C4h,0CEh,0C7h,0C5h,0CBh
db
04Ch,041h,04Ah,04Fh,049h,042h,046h,048h,040h,04Dh,043h,044h,04Eh,047h,045h,04Bh
db
01Ch,011h,01Ah,01Fh,019h,012h,016h,018h,010h,01Dh,013h,014h,01Eh,017h,015h,01Bh
db
07Ch,071h,07Ah,07Fh,079h,072h,076h,078h,070h,07Dh,073h,074h,07Eh,077h,075h,07Bh
db
0ACh,0A1h,0AAh,0AFh,0A9h,0A2h,0A6h,0A8h,0A0h,0ADh,0A3h,0A4h,0AEh,0A7h,0A5h,0ABh
db
0BCh,0B1h,0BAh,0BFh,0B9h,0B2h,0B6h,0B8h,0B0h,0BDh,0B3h,0B4h,0BEh,0B7h,0B5h,0BBh
db
06Ch,061h,06Ah,06Fh,069h,062h,066h,068h,060h,06Dh,063h,064h,06Eh,067h,065h,06Bh
db
08Ch,081h,08Ah,08Fh,089h,082h,086h,088h,080h,08Dh,083h,084h,08Eh,087h,085h,08Bh
db
05Ch,051h,05Ah,05Fh,059h,052h,056h,058h,050h,05Dh,053h,054h,05Eh,057h,055h,05Bh
db
03Ch,031h,03Ah,03Fh,039h,032h,036h,038h,030h,03Dh,033h,034h,03Eh,037h,035h,03Bh
db
0FCh,0F1h,0FAh,0FFh,0F9h,0F2h,0F6h,0F8h,0F0h,0FDh,0F3h,0F4h,0FEh,0F7h,0F5h,0FBh
db
0DCh,0D1h,0DAh,0DFh,0D9h,0D2h,0D6h,0D8h,0D0h,0DDh,0D3h,0D4h,0DEh,0D7h,0D5h,0DBh
db
00Ch,001h,00Ah,00Fh,009h,002h,006h,008h,000h,00Dh,003h,004h,00Eh,007h,005h,00Bh
db
0ECh,0E1h,0EAh,0EFh,0E9h,0E2h,0E6h,0E8h,0E0h,0EDh,0E3h,0E4h,0EEh,0E7h,0E5h,0EBh
db
09Ch,091h,09Ah,09Fh,099h,092h,096h,098h,090h,09Dh,093h,094h,09Eh,097h,095h,09Bh
ConstTable3 db
0A7h,0ADh,0AEh,0A3h,0A0h,0A6h,0A9h,0AAh,0A1h,0A2h,0A8h,0A5h,0ABh,0ACh,0A4h,0AFh
db
007h,00Dh,00Eh,003h,000h,006h,009h,00Ah,001h,002h,008h,005h,00Bh,00Ch,004h,00Fh
db
097h,09Dh,09Eh,093h,090h,096h,099h,09Ah,091h,092h,098h,095h,09Bh,09Ch,094h,09Fh
db
0E7h,0EDh,0EEh,0E3h,0E0h,0E6h,0E9h,0EAh,0E1h,0E2h,0E8h,0E5h,0EBh,0ECh,0E4h,0EFh
db
067h,06Dh,06Eh,063h,060h,066h,069h,06Ah,061h,062h,068h,065h,06Bh,06Ch,064h,06Fh
db
037h,03Dh,03Eh,033h,030h,036h,039h,03Ah,031h,032h,038h,035h,03Bh,03Ch,034h,03Fh
db
0F7h,0FDh,0FEh,0F3h,0F0h,0F6h,0F9h,0FAh,0F1h,0F2h,0F8h,0F5h,0FBh,0FCh,0F4h,0FFh
db
057h,05Dh,05Eh,053h,050h,056h,059h,05Ah,051h,052h,058h,055h,05Bh,05Ch,054h,05Fh
db
017h,01Dh,01Eh,013h,010h,016h,019h,01Ah,011h,012h,018h,015h,01Bh,01Ch,014h,01Fh
db
0D7h,0DDh,0DEh,0D3h,0D0h,0D6h,0D9h,0DAh,0D1h,0D2h,0D8h,0D5h,0DBh,0DCh,0D4h,0DFh
db
0C7h,0CDh,0CEh,0C3h,0C0h,0C6h,0C9h,0CAh,0C1h,0C2h,0C8h,0C5h,0CBh,0CCh,0C4h,0CFh
db
077h,07Dh,07Eh,073h,070h,076h,079h,07Ah,071h,072h,078h,075h,07Bh,07Ch,074h,07Fh
db
0B7h,0BDh,0BEh,0B3h,0B0h,0B6h,0B9h,0BAh,0B1h,0B2h,0B8h,0B5h,0BBh,0BCh,0B4h,0BFh
db
047h,04Dh,04Eh,043h,040h,046h,049h,04Ah,041h,042h,048h,045h,04Bh,04Ch,044h,04Fh
db
027h,02Dh,02Eh,023h,020h,026h,029h,02Ah,021h,022h,028h,025h,02Bh,02Ch,024h,02Fh
db
087h,08Dh,08Eh,083h,080h,086h,089h,08Ah,081h,082h,088h,085h,08Bh,08Ch,084h,08Fh
ConstTable4 db
0EFh,0E1h,0E8h,0EEh,0E6h,0EBh,0E3h,0E4h,0E9h,0E7h,0E2h,0EDh,0ECh,0E0h,0E5h,0EAh
db
04Fh,041h,048h,04Eh,046h,04Bh,043h,044h,049h,047h,042h,04Dh,04Ch,040h,045h,04Ah
db
0DFh,0D1h,0D8h,0DEh,0D6h,0DBh,0D3h,0D4h,0D9h,0D7h,0D2h,0DDh,0DCh,0D0h,0D5h,0DAh
db
01Fh,011h,018h,01Eh,016h,01Bh,013h,014h,019h,017h,012h,01Dh,01Ch,010h,015h,01Ah
db
02Fh,021h,028h,02Eh,026h,02Bh,023h,024h,029h,027h,022h,02Dh,02Ch,020h,025h,02Ah
db
0FFh,0F1h,0F8h,0FEh,0F6h,0FBh,0F3h,0F4h,0F9h,0F7h,0F2h,0FDh,0FCh,0F0h,0F5h,0FAh
db
0BFh,0B1h,0B8h,0BEh,0B6h,0BBh,0B3h,0B4h,0B9h,0B7h,0B2h,0BDh,0BCh,0B0h,0B5h,0BAh
db
08Fh,081h,088h,08Eh,086h,08Bh,083h,084h,089h,087h,082h,08Dh,08Ch,080h,085h,08Ah
db
03Fh,031h,038h,03Eh,036h,03Bh,033h,034h,039h,037h,032h,03Dh,03Ch,030h,035h,03Ah
db
0AFh,0A1h,0A8h,0AEh,0A6h,0ABh,0A3h,0A4h,0A9h,0A7h,0A2h,0ADh,0ACh,0A0h,0A5h,0AAh
db
06Fh,061h,068h,06Eh,066h,06Bh,063h,064h,069h,067h,062h,06Dh,06Ch,060h,065h,06Ah
db
0CFh,0C1h,0C8h,0CEh,0C6h,0CBh,0C3h,0C4h,0C9h,0C7h,0C2h,0CDh,0CCh,0C0h,0C5h,0CAh
db
05Fh,051h,058h,05Eh,056h,05Bh,053h,054h,059h,057h,052h,05Dh,05Ch,050h,055h,05Ah
db
09Fh,091h,098h,09Eh,096h,09Bh,093h,094h,099h,097h,092h,09Dh,09Ch,090h,095h,09Ah
db
00Fh,001h,008h,00Eh,006h,00Bh,003h,004h,009h,007h,002h,00Dh,00Ch,000h,005h,00Ah
db
07Fh,071h,078h,07Eh,076h,07Bh,073h,074h,079h,077h,072h,07Dh,07Ch,070h,075h,07Ah
DecryptedHead db "User Key: Cracked By The+Q -FULL"
db 20h*3 dup (0)
EncryptedHead db 20h dup (0)
A DD 0
B DD 0
C DD 0
i DD 0
FileName DB "user.key",0
hFile DD 0
hMapFile DD 0
pMapFile DD 0
.CODE
;---陳陳陳塚様様様様様様様様様様様様様様様様様様様様様様様様様様様幼陳陳陳----
CreateKeyFile PROC
USES ebx,ecx,edx,esi,edi,ebp
Call CreateFile,OFFSET FileName,GENERIC_WRITE+GENERIC_READ,0,NULL, \
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
Mov hFile,eax
.IF eax!=INVALID_HANDLE_VALUE
Call CreateFileMappingA,hFile,NULL,PAGE_READWRITE,0,0C0h,NULL
.IF eax!=0
Mov hMapFile,eax
Call MapViewOfFile, hMapFile,FILE_MAP_ALL_ACCESS,0,0,0
Mov pMapFile,eax
Call EncryptHead
Call GetDlgItemTextA, mainhwnd, Edit_Name, OFFSET FName, 30
Mov edi, pMapFile
Add edi,40h
Call lstrcpyA,edi, OFFSET FName
Call GetDlgItemTextA, mainhwnd, Edit_Email, OFFSET FName, 30
Mov edi, pMapFile
Add edi,80h
Call lstrcpyA,edi, OFFSET FName
Call GetDlgItemTextA, mainhwnd, Edit_Addr, OFFSET FName, 30
Mov edi, pMapFile
Add edi,60h
Call lstrcpyA,edi, OFFSET FName
Call UnmapViewOfFile, pMapFile
Call CloseHandle, hMapFile
.ENDIF
Call CloseHandle, hFile
.ENDIF
RET
CreateKeyFile ENDP
;---陳陳陳塚様様様様様様様様様様様様様様様様様様様様様様様様様様様幼陳陳陳----
EncryptHead Proc
Mov edi, (OFFSET DecryptedHead+20h) ; Build table
Mov ebx,3
@BuildTable1:
Mov esi, (OFFSET DecryptedHead+1Ch)
Mov ecx, 8
@BuildTable2:
Std
Lodsd
Cld
Stosd
Loop @BuildTable2
Dec ebx
Jnz @BuildTable1
Mov esi, OFFSET DecryptedHead ; Save decrypted head to file
Mov edi, pMapFile
Mov ecx, 8
Repnz Movsd
Mov edi, OFFSET EncryptedHead ; Encrypt head
Mov ebx, OFFSET ConstTable1
Xor ecx,ecx
@Encrypt1:
Push ecx
Mov i, 7Ch
Mov esi, OFFSET DecryptedHead
Shl ecx,3
Add esi,ecx
Mov eax, dword ptr [esi] ; Text to encrypt
Mov A, eax
Mov eax, dword ptr [esi+4]
Mov C, eax
; B = [Translate(A+Head[i]) Rol 3] Xor C;
; if (i--==0) break;
; C = A;
; A = B;
@Encrypt2:
Mov esi, OFFSET DecryptedHead
Add esi, i
Mov eax, A
Mov edx, C
Add eax, dword ptr [esi]
Xlat
Add ebx, 100h
Ror eax, 8
Xlat
Add ebx, 100h
Ror eax, 8
Xlat
Add ebx, 100h
Ror eax, 8
Xlat
Sub ebx, 300h
Rol eax, 3
Xor eax, edx
Mov B, eax
Sub i, 4
Cmp i, -4
Jz @Encrypt3
Push A
Pop C
Push B
Pop A
Jmp @Encrypt2
@Encrypt3:
Mov eax, A
Stosd
Mov eax, B
Stosd
Pop ecx
Inc ecx
Cmp ecx,4
Jnz @Encrypt1
Mov esi, OFFSET EncryptedHead ; Save encrypted head to file
Mov edi, pMapFile
Add edi, 20h
Mov ecx, 8
Repnz Movsd
RET
EncryptHead Endp
;---陳陳陳塚様様様様様様様様様様様様様様様様様様様様様様様様様様様幼陳陳陳----
***/***
I looked in the ida's disassembly for a lot of memory flags, nothing more.
Now we really have to understand what this program does, trying to think like it. Maybe there is a flag attached to the proxies, they crypted the proxy file aproxy.cdb, they must have a serious reason. I will repeat it again and again, ida is the *best* tool that you can use, using the mfc signatures, look what's after this check :
.text:0040CD5D loc_0_40CD5D: ; CODE XREF: sub_0_40CCE0+76j .text:0040CD5D push edi .text:0040CD5E lea edi, [eax-1] .text:0040CD61 mov eax, [esi+0F0h] .text:0040CD67 push 2 .text:0040CD69 push edi .text:0040CD6A push 100Ch .text:0040CD6F push eax .text:0040CD70 call ebx .text:0040CD72 lea ebx, [esi+0D0h] .text:0040CD78 push edi .text:0040CD79 mov ecx, ebx .text:0040CD7B call j_?GetItemData@CListCtrl@@QBEKH@Z ; CListCtrl::GetItemData(int) .text:0040CD80 or eax, 1000000h .text:0040CD85 mov ecx, ebx .text:0040CD87 push eax .text:0040CD88 push 0 .text:0040CD8A push 0 .text:0040CD8C push 0 .text:0040CD8E push 0 .text:0040CD90 push 4 .text:0040CD92 push 0 .text:0040CD94 push edi .text:0040CD95 call j_?SetItem@CListCtrl@@QAEHHHIPBDHIIJ@Z ; CListCtrl::SetItem(int,int,uint,char const *,int,uint,uint,long) .text:0040CD9A cmp dword_0_419748, 5 .text:0040CDA1 jnz short loc_0_40CDD0 .text:0040CDA3 push offset unk_0_4183EC .text:0040CDA8 push 13h .text:0040CDAA push edi .text:0040CDAB mov ecx, ebx .text:0040CDAD call j_MFC42_6907 .text:0040CDB2 push offset unk_0_4183EC .text:0040CDB7 push 15h .text:0040CDB9 push edi .text:0040CDBA mov ecx, ebx .text:0040CDBC call j_MFC42_6907 .text:0040CDC1 push offset unk_0_4183EC .text:0040CDC6 push 14h .text:0040CDC8 push edi .text:0040CDC9 mov ecx, ebx .text:0040CDCB call j_MFC42_6907
At line 40cd7b, you have a clistctrl method that is used, GetItemData(n), according to m$ doc, retrieves a app dedicated value for the item number n, or the proxy number n is the proxy list. Just do a bpx at this line,you will see that the edi val pushed before is exactly the same number in order that the first proxy you selected.
The value is then stored in eax and a logical and with 01000000 is done on it. What for ? Just impeach that and with softice, and the proxy is not checked.
All the proxies in that list are flagged with a non x1xxxxxx value, this & 01000000 just enables them to be checked. So there is a check for this value inside a4proxy, to stop the proxy check when the first is checked. In the registered version, this routine must enable all the proxies you selected.
Searching in ida for 01000000h, you find this :
.text:0040C0B0 loc_0_40C0B0: ; CODE XREF: sub_0_40C040+210j .text:0040C0B0 push edi .text:0040C0B1 mov ecx, ebx .text:0040C0B3 call j_?GetItemData@CListCtrl@@QBEKH@Z ; CListCtrl::GetItemData(int) .text:0040C0B8 naughty -> test eax, 1000000h .text:0040C0BD mov [esp+38h+var_1C], eax .text:0040C0C1 jz short loc_0_40C106 .text:0040C0C3 mov ecx, offset unk_0_418D80 .text:0040C0C8 xor esi, esi .text:0040C0CA mov [esp+38h+var_24], ecx .text:0040C0CE .text:0040C0CE loc_0_40C0CE: ; CODE XREF: sub_0_40C040+B7j .text:0040C0CE cmp dword ptr [ecx+4], 0FFFFFFFFh .text:0040C0D2 jnz short loc_0_40C0E9 .text:0040C0D4 push 0 .text:0040C0D6 push 33h .text:0040C0D8 push 1 .text:0040C0DA push 0 .text:0040C0DC call j_?Create@CAsyncSocket@@QAEHIHJPBD@Z ; CAsyncSocket::Create(uint,int,long,char const *) .text:0040C0E1 test eax, eax .text:0040C0E3 jnz short loc_0_40C13A .text:0040C0E5 mov ecx, [esp+48h+var_34] When a4proxy arrives here, it checks for the first proxy selected that passes the 40c0b8 test, it's param was updated above. When the second proxy arrives, it's param was not x1xxxxxx like, so it goes out at line 40c0c1. Just nop the 40c0c1 line, and all the proxies after the first you selected will be checked.
Sure this is not a definite crack, the unregistered feature still appears on the about window, the crack is enough to use this app , if someone manage to find the global reg check, just send me the ideas, they are welcomed.
+Tsehp April 2000
The global protection resides inside the proxy list they send you when you buy it. So you have to wait for them to send you the updates, or manually build a text listing everytime. Very stupid because this kind of protection removes the auto update they could have made. Maybe in the next version. ;-) +Tsehp