Anonymity 4 Proxy 2.0

Interesting protection for a useful app.

Not Assigned
April 2000
by +Tsehp
Courtesy of Fravia's page of reverse engineering
slightly edited
by +Tsehp
There is a crack, a crack in everything That's how the light gets in
( )Beginner (x)Intermediate ( )Advanced ( )Expert

Anonymity matters, those days, the web is becoming more and more filled by commercial crooks, they collect
more and more info about you, they use cgi apps to collect your browser's environment variables, they record
your ip, feed you with cookies and advertisements.
Lets definitly stop all this, at your pc level, imagine an app that will impeach every browser to send the info you
don't want to. Now they can program everything they want, this great program will stop everything and cover your
cracker's ass. It's not expensive but the protection deserves a look because it's original.

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 
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.
Tools required
Ida pro 4.03
Softice 4.05

Target's URL/FTP

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 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
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

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

CreateKeyFile PROC
USES ebx,ecx,edx,esi,edi,ebp
Mov hFile,eax
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

Call CloseHandle, hFile
CreateKeyFile ENDP
EncryptHead Proc
Mov edi, (OFFSET DecryptedHead+20h) ; Build table
Mov ebx,3
Mov esi, (OFFSET DecryptedHead+1Ch)
Mov ecx, 8
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
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;
Mov esi, OFFSET DecryptedHead
Add esi, i
Mov eax, A
Mov edx, C
Add eax, dword ptr [esi]
Add ebx, 100h
Ror eax, 8
Add ebx, 100h
Ror eax, 8
Add ebx, 100h
Ror eax, 8
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

Mov eax, A
Mov eax, B

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
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 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
					+Tsehp April 2000

Final Notes
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. ;-) 


Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back.

You are deep inside Fravia's page of reverse engineering, choose your way out:

redhomepage redlinks redsearch_forms red+ORC redhow to protect redacademy database
redreality cracking redhow to search redjavascript wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_Fravia
redIs reverse engineering legal?