{Tested versions: 5.51}

unit WTCPwd;

interface

uses
  SysUtils;

function WTCDecrypt(const Password: String): String;

implementation


const
    var_118   =  -$118;
    var_14    =  -$14;
    var_10    =  -$10;
    var_C     =  -$0C;
    var_A     =  -$0A;
    var_9     =  -$09;
    var_8     =  -$08;
    var_4     =  -$04;
    var_1     =  -$01;


const
   PTable : array [0..255] of LongWord =
   ($00000000, $77073096, $EE0E612C, $990951BA,
    $076DC419, $706AF48F, $E963A535, $9E6495A3,
    $0EDB8832, $79DCB8A4, $E0D5E91E, $97D2D988,
    $09B64C2B, $7EB17CBD, $E7B82D07, $90BF1D91,
    $1DB71064, $6AB020F2, $F3B97148, $84BE41DE,
    $1ADAD47D, $6DDDE4EB, $F4D4B551, $83D385C7,
    $136C9856, $646BA8C0, $FD62F97A, $8A65C9EC,
    $14015C4F, $63066CD9, $FA0F3D63, $8D080DF5,
    $3B6E20C8, $4C69105E, $D56041E4, $A2677172,
    $3C03E4D1, $4B04D447, $D20D85FD, $A50AB56B,
    $35B5A8FA, $42B2986C, $DBBBC9D6, $ACBCF940,
    $32D86CE3, $45DF5C75, $DCD60DCF, $ABD13D59,
    $26D930AC, $51DE003A, $C8D75180, $BFD06116,
    $21B4F4B5, $56B3C423, $CFBA9599, $B8BDA50F,
    $2802B89E, $5F058808, $C60CD9B2, $B10BE924,
    $2F6F7C87, $58684C11, $C1611DAB, $B6662D3D,
    $76DC4190, $01DB7106, $98D220BC, $EFD5102A,
    $71B18589, $06B6B51F, $9FBFE4A5, $E8B8D433,
    $7807C9A2, $0F00F934, $9609A88E, $E10E9818,
    $7F6A0DBB, $086D3D2D, $91646C97, $E6635C01,
    $6B6B51F4, $1C6C6162, $856530D8, $F262004E,
    $6C0695ED, $1B01A57B, $8208F4C1, $F50FC457,
    $65B0D9C6, $12B7E950, $8BBEB8EA, $FCB9887C,
    $62DD1DDF, $15DA2D49, $8CD37CF3, $FBD44C65,
    $4DB26158, $3AB551CE, $A3BC0074, $D4BB30E2,
    $4ADFA541, $3DD895D7, $A4D1C46D, $D3D6F4FB,
    $4369E96A, $346ED9FC, $AD678846, $DA60B8D0,
    $44042D73, $33031DE5, $AA0A4C5F, $DD0D7CC9,
    $5005713C, $270241AA, $BE0B1010, $C90C2086,
    $5768B525, $206F85B3, $B966D409, $CE61E49F,
    $5EDEF90E, $29D9C998, $B0D09822, $C7D7A8B4,
    $59B33D17, $2EB40D81, $B7BD5C3B, $C0BA6CAD,
    $EDB88320, $9ABFB3B6, $03B6E20C, $74B1D29A,
    $EAD54739, $9DD277AF, $04DB2615, $73DC1683,
    $E3630B12, $94643B84, $0D6D6A3E, $7A6A5AA8,
    $E40ECF0B, $9309FF9D, $0A00AE27, $7D079EB1,
    $F00F9344, $8708A3D2, $1E01F268, $6906C2FE,
    $F762575D, $806567CB, $196C3671, $6E6B06E7,
    $FED41B76, $89D32BE0, $10DA7A5A, $67DD4ACC,
    $F9B9DF6F, $8EBEEFF9, $17B7BE43, $60B08ED5,
    $D6D6A3E8, $A1D1937E, $38D8C2C4, $4FDFF252,
    $D1BB67F1, $A6BC5767, $3FB506DD, $48B2364B,
    $D80D2BDA, $AF0A1B4C, $36034AF6, $41047A60,
    $DF60EFC3, $A867DF55, $316E8EEF, $4669BE79,
    $CB61B38C, $BC66831A, $256FD2A0, $5268E236,
    $CC0C7795, $BB0B4703, $220216B9, $5505262F,
    $C5BA3BBE, $B2BD0B28, $2BB45A92, $5CB36A04,
    $C2D7FFA7, $B5D0CF31, $2CD99E8B, $5BDEAE1D,
    $9B64C2B0, $EC63F226, $756AA39C, $026D930A,
    $9C0906A9, $EB0E363F, $72076785, $05005713,
    $95BF4A82, $E2B87A14, $7BB12BAE, $0CB61B38,
    $92D28E9B, $E5D5BE0D, $7CDCEFB7, $0BDBDF21,
    $86D3D2D4, $F1D4E242, $68DDB3F8, $1FDA836E,
    $81BE16CD, $F6B9265B, $6FB077E1, $18B74777,
    $88085AE6, $FF0F6A70, $66063BCA, $11010B5C,
    $8F659EFF, $F862AE69, $616BFFD3, $166CCF45,
    $A00AE278, $D70DD2EE, $4E048354, $3903B3C2,
    $A7672661, $D06016F7, $4969474D, $3E6E77DB,
    $AED16A4A, $D9D65ADC, $40DF0B66, $37D83BF0,
    $A9BCAE53, $DEBB9EC5, $47B2CF7F, $30B5FFE9,
    $BDBDF21C, $CABAC28A, $53B39330, $24B4A3A6,
    $BAD03605, $CDD70693, $54DE5729, $23D967BF,
    $B3667A2E, $C4614AB8, $5D681B02, $2A6F2B94,
    $B40BBE37, $C30C8EA1, $5A05DF1B, $2D02EF8D);



function Hex2Dec(St: String): Byte;   // 2-chars only!
var
  Tmp: String;
begin
  SetLength(Tmp, 2);
  Tmp[1] := St[1];
  Tmp[2] := St[2];
  Result := StrToInt('$' + Tmp);
end;

var
  dword_53602C: Cardinal;
  psw, Tmp: PChar;

procedure MainDecrypt; assembler;
asm
                 mov     eax, psw

                 push    ebp
                 mov     ebp, esp
                 add     esp, 0FFFFFEE8h
                 push    ebx
                 push    esi
                 push    edi
                 mov     esi, eax
                 cmp     byte ptr [esi], 0     // Проверка на пустую строку
                 jz      @@loc_4781E4          // Выход если первый байт 0x00 (пустая строка)
                 lea     eax, [ebp+var_118]
                 mov     edx, esi              // ?   /
                 call    @@sub_406BB0          // ?  /
                 mov     eax, esi              // ? < Какая-то проверка корректности шифра?
                 call    @@sub_406B48          // ?  \
                 shr     eax, 1                // ?   \
                 dec     eax
                 mov     [ebp+var_8], eax
                 cmp     dword ptr [ebp+var_8], 4
                 jge     @@loc_47806B        // Продолжаем
                 mov     byte ptr [esi], 0   // Запись 0x00 после jmp в TmpStr
                 jmp     @@loc_4781E4        // Выход
 @@loc_47806B:
                 lea     eax, [ebp+var_118]  // ?   /
                 mov     [ebp+var_14], eax   // ?  /
                 mov     edi, [ebp+var_8]    // ? <  Похоже, это Length(Ecnrypted)
                 test    edi, edi            // ?  \
                 jl      @@loc_478091        // ?   \
                 inc     edi                 // Увиличиваем счетчик длины строки
                 xor     ebx, ebx            // Пишем в ebx 0, чтобы [ebp+ebx] указывал на начале шифровки
 @@loc_47807E:                               // На входе в edi длина шифровки, ebx = 0, ebp указ. на шифровку
                 mov     eax, [ebp+var_14]   // Читаем
                 call    Hex2Dec             // Преобразуем в 10-ричную систему байт из eax
                 mov     [esi+ebx], al       // Вернулся байт в eax (al), запишем его
                 add     dword ptr [ebp+var_14], 2 // Увеличим указатель (чтение) на 2 байта, т.е 2 знака hex
                 inc     ebx                 // Увеличим байтовый счетчик (выход)
                 dec     edi                 // Уменьшаем счетчик (длины строки)
                 jnz     @@loc_47807E        // Если edi <> 0 (не вся строка шифра пройдена) то циклимся вверх
 @@loc_478091:
                 mov     eax, [ebp+var_8]
                 mov     al, [esi+eax-3]
                 mov     [ebp+var_C], al
                 mov     eax, [ebp+var_8]
                 mov     al, [esi+eax-2]
                 mov     [ebp-0Bh], al
                 mov     eax, [ebp+var_8]
                 mov     al, [esi+eax-1]
                 mov     [ebp+var_A], al
                 mov     eax, [ebp+var_8]
                 mov     al, [esi+eax]
                 mov     [ebp+var_9], al
                 sub     dword ptr [ebp+var_8], 4
                 mov     eax, [ebp+var_8]
                 mov     byte ptr [esi+eax+1], 0
                 mov     dword_53602C, 0CF671h
                 mov     edi, [ebp+var_8]
                 jl      @@loc_47810D
                 inc     edi
                 xor     ebx, ebx
 @@loc_4780D8:
                 xor     eax, eax
                 mov     al, [esi+ebx]
                 mov     [ebp-04h], ax
                 mov     eax, 8
                 call    @@sub_402A9C
                 mov     [ebp+var_1], al
                 push    ax
                 push    cx
                 mov     cl, [ebp+var_1]
                 mov     ax, [ebp+var_4]
                 rol     al, cl
                 mov     [ebp+var_4], ax
                 pop     cx
                 pop     ax
                 mov     al, byte ptr [ebp+var_4]
                 mov     [esi+ebx], al
                 inc     ebx
                 dec     edi
                 jnz     @@loc_4780D8
 @@loc_47810D:
                 mov     dword_53602C, 3039h
                 mov     ebx, 100h
 @@loc_47811C:
                 mov     edi, [ebp+var_8]
                 inc     edi
                 mov     eax, edi
                 call    @@sub_402A9C
                 lea     eax, [esi+eax]
                 push    eax
                 mov     eax, edi
                 call    @@sub_402A9C
                 lea     eax, [esi+eax]
                 pop     edx
                 call    @@sub_478020
                 dec     ebx
                 jnz     @@loc_47811C
                 mov     dword_53602C, 0A564h
                 mov     edi, [ebp+var_8]
                 test    edi, edi
                 jl      @@loc_478173
                 inc     edi
                 xor     ebx, ebx
 @@loc_478152:
                 xor     eax, eax
                 mov     al, [esi+ebx]
                 mov     [ebp+var_4], ax
                 mov     eax, 100h
                 call    @@sub_402A9C
                 xor     [ebp+var_4], ax
                 mov     al, byte ptr [ebp+var_4]
                 mov     [esi+ebx], al
                 inc     ebx
                 dec     edi
                 jnz     @@loc_478152
 @@loc_478173:
                 mov     dword_53602C, 0D431h
                 mov     edi, [ebp+var_8]
                 test    edi, edi
                 jl      @@loc_4781C4
                 inc     edi
                 xor     ebx, ebx
 @@loc_478187:
                 xor     eax, eax
                 mov     al, [esi+ebx]
                 mov     [ebp+var_4], ax
                 mov     eax, 100h
                 call    @@sub_402A9C
                 movzx   edx, word ptr [ebp+var_4]
                 add     edx, 100h
                 sub     edx, eax
                 and     edx, 800000FFh
                 jns     @@loc_4781B6
                 dec     edx
                 or      edx, 0FFFFFF00h
                 inc     edx
 @@loc_4781B6:
                 mov     [ebp+var_4], dx
                 mov     al, byte ptr [ebp+var_4]
                 mov     [esi+ebx], al
                 inc     ebx
                 dec     edi
                 jnz     @@loc_478187
 @@loc_4781C4:
                 mov     dword ptr [ebp+var_10], 0FFFFFFFFh
                 lea     ecx, [ebp+var_10]
                 mov     edx, [ebp+var_8]
                 inc     edx
                 mov     eax, esi
                 call    @@sub_530E28
                 mov     eax, dword ptr [ebp+var_C]
                 cmp     eax, [ebp+var_10]
                 jz      @@loc_4781E4
                 mov     byte ptr [esi], 0
 @@loc_4781E4:
                 pop     edi
                 mov     [Tmp], esi     // Запись в TmpStr из esi
                 pop     esi
                 pop     ebx
                 mov     esp, ebp
                 pop     ebp

                 jmp     @@EndDecrypt      // Выход (финальный)

 @@sub_406BB0:   push    edi
                 push    esi
                 mov     esi, eax
                 mov     edi, edx
                 mov     ecx, 0FFFFFFFFh
                 xor     al, al
                 repne scasb
                 not     ecx
                 mov     edi, esi
                 mov     esi, edx
                 mov     edx, ecx
                 mov     eax, edi
                 shr     ecx, 2
                 repe movsd
                 mov     ecx, edx
                 and     ecx, 3
                 repe movsb
                 pop     esi
                 pop     edi
                 ret

 @@sub_406B48:   mov     edx, edi
                 mov     edi, eax
                 mov     ecx, 0FFFFFFFFh
                 xor     al, al
                 repne scasb
                 mov     eax, 0FFFFFFFEh
                 sub     eax, ecx
                 mov     edi, edx
                 ret

 @@sub_402A9C:   imul    edx, dword_53602C, 8088405h
                 inc     edx
                 mov     dword_53602C, edx
                 mul     edx
                 mov     eax, edx
                 ret

 @@sub_478020:   push    ebx
                 mov     cl, [eax]
                 mov     bl, [edx]
                 mov     [eax], bl
                 mov     [edx], cl
                 pop     ebx
                 ret

 @@sub_530E28:   push    ebp
                 mov     ebp, esp
                 add     esp, 0FFFFFFF4h
                 mov     [ebp+var_8], ecx
                 mov     [ebp+var_C], edx
                 mov     [ebp+var_4], eax
                 push    edi
                 push    esi
                 push    ebx
                 mov     edi, [ebp+var_4]
                 mov     eax, [ebp+var_8]
                 mov     eax, [eax]
                 lea     esi, PTable
                 mov     ecx, [ebp+var_C]
                 or      ecx, ecx
                 jz      @@loc_530E62

 @@loc_530E4F:
                 xor     ebx, ebx
                 mov     bl, al
                 shr     eax, 8
                 xor     bl, [edi]
                 inc     edi
                 shl     ebx, 2
                 xor     eax, [esi+ebx]
                 dec     ecx
                 jnz     @@loc_530E4F

 @@loc_530E62:
                 mov     ebx, [ebp+var_8]
                 mov     [ebx], eax
                 pop     ebx
                 pop     esi
                 pop     edi
                 mov     esp, ebp
                 pop     ebp
                 ret
 @@EndDecrypt:
end;

function WTCDecrypt(const Password: String): String;
var
  a: PChar;
begin
  Result := '';
  a := nil;
  try
    psw := PChar(Password);
    Tmp := StrAlloc(1024);
    a := Tmp;
    MainDecrypt;
    Result := String(Tmp);
  finally
    if a <> nil then
      StrDispose(a);
  end;
end;


end.
