Decrypted ECM CW Irdeto2 V1.0 by kasita botonnou
Decrypted ECM CW Irdeto2 V1.0 by kasita botonnou
the soft asks opkey
where to find
{*************************************** ****************
**************************************** ****************
**************************************** ****************
* Softcam plugin to VDR (C++) to Delphi implementation *
* written by Ekrem KOÇAK *
**************************************** ****************
**************************************** ****************
**************************************** ***************}
unit Viaccess3;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,crypto,AES,RC6,Helper;
Type
TViaccess3 =class(TDes)
private
//cAES Aes;
//cViac1 Viac1;
//cUtils Utils;
T1Key:array[0..256-1] of byte;
KeyDes3:array[0..16-1] of byte;
KeyDes1:array[0..8-1] of byte;
XorKey:array[0..8-1] of byte;
XPos:array[0..8-1] of byte;
IV:array[0..8-1] of byte;
AESKey:array[0..16-1] of byte;
function RequestKeys():Boolean;
procedure Core( data:PByteArray; Off:byte);
procedure Fct1( data:PByteArray);
procedure Fct2( data:PByteArray);
procedure ProcessDw( data:PByteArray);
Function AESDecrypt(Key:PByteArray ;InBlock:PByteArray):string;
public
CurrentIdent:Integer;
DesKeyIdx:Integer;
aesKeyIdx:Integer;
AesAfterVia3Core:Boolean;
needsAES:Boolean;
constructor Create();
destructor Destroy; override;
function Via3Decrypt( pNanoEA:PByteArray;dw:PByteArray):Boolea n;
end;
implementation
Uses UntMain;
constructor TViaccess3.Create();
begin
inherited Create(nil,0,nil,0);
end;
destructor TViaccess3.Destroy;
begin
inherited Destroy;
end;
Function TViaccess3.AESDecrypt(Key:PByteArray ;InBlock:PByteArray):string;
var
TempBuf: TAESBuffer;
Buffer: TAESBuffer;
ExpAndedKey: TAESExpAndedKey128;
Key128: TAESKey128;
Begin
move(Key[0], Key128[0], 16);
ExpAndAESKeyForDecryption(Key128, ExpAndedKey);
move(InBlock[0], Buffer[0], 16);
DecryptAES(Buffer, ExpAndedKey, TempBuf);
move(TempBuf[0], InBlock[0], 16);
End;
function HasValidCRC(dw:PByteArray):boolean;
begin
if (((dw[0]+dw[1]+dw[2]) and $FF) <> dw[3]) then begin result:= false; exit; end;
if (((dw[4]+dw[5]+dw[6]) and $FF) <> dw[7]) then begin result:= false; exit; end;
if (((dw[8]+dw[9]+dw[10]) and $FF) <> dw[11]) then begin result:= false; exit; end;
if (((dw[12]+dw[13]+dw[14]) and $FF) <> dw[15]) then begin result:= false; exit; end;
result:= true;
end;
function TViaccess3.RequestKeys():Boolean;
begin
_memcpy(@T1Key[0],@T1[0],256);
_memcpy(@KeyDes3[0],@OP_KEY[0],16);
_memcpy(@KeyDes1[0],@D1[0],8);
_memcpy(@XorKey[0],@X1[0],8);
_memcpy(@XPos[0],@P1[0],8);
_memcpy(@IV[0],@C1[0],8);
Result:=true;
end;
procedure TViaccess3.Core( data:PByteArray; Off:byte);
var
i:Integer;
R2, R3, R4, R6, R7:Integer;
begin
// if (ShowLog) SendMSG(0,"Core on Ident: X", CurrentIdent);
frmMain.Messages(0,'Core->init data:'@data[0],8);
// SendHexDump("Core->init data:",0,data,8);
case (CurrentIdent) of
$032820:
begin
for i:=0 to 4-1 do
data[i]:=data[i] xor XorKey[(Off+i) and $07];
R2 := (data[0] xor $BD)+data[0];
R3 := (data[3]xor $EB)+data[3];
R2 := (R2-R3)xor data[2];
R3 := (($39*data[1])shl 2);
data[4] := (R2 or R3)+data[2];
R3 := ((((data[0]+6) xor data[0]) or (data[2] shl 1))xor $65)+data[0];
R2 := (data[1]xor $ED)+data[1];
R7 := ((data[3]+$29) xor data[3])*R2;
data[5] := R7+R3;
R2 := ((data[2]xor $33)+data[2]) and $0A;
R3 := (data[0]+ $AD) xor data[0];
R3 := R3+R2;
R2 := data[3]*data[3];
R7 := (R2 or 1) + data[1];
data[6] := (R3 or R7)+data[1];
R3 := data[1] and $07;
R2 := (R3-data[2]) and (data[0] or R2 or $01);
data[7] := R2+data[3];
for i:=0 to 4-1 do
data[i+4] := T1Key[data[i+4]];
end;
$030B00:
begin
for i:=0 to 4-1 do
data[i]:=data[i] xor XorKey[(Off+i) and $07];
R6 := (data[3] + $6E)xor data[3];
R6 := (R6*(data[2] shl 1)) + $17;
R3 := (data[1] + $77) xor data[1];
R4 := (data[0] + $D7) xor data[0];
data[4] := ((R4 and R3) or R6) + data[0];
R4 := ((data[3] + $71) xor data[3]) xor $90;
R6 := (data[1] + $1B) xor data[1];
R4 := (R4*R6) xor data[0];
data[5] := (R4 xor (data[2] shl 1)) + data[1];
R3 := (data[3] * data[3])or $01;
R4 := (((data[2] xor $35) + data[2]) or R3) + data[2];
R6 := data[1] xor (data[0] + $4A);
data[6] := R6 + R4;
R3 := (data[0] * (data[2] shl 1)) or data[1];
R4 := $FE - data[3];
R3 := R4 xor R3;
data[7] := R3 + data[3];
for i:=0 to 4-1 do
data[4+i] := T1Key[data[4+i]];
end;
end;
frmMain.Messages(0,'Core->final data:'@data[0],8);
// SendHexDump("Core->final data:",0,data,8);
end;
procedure TViaccess3.Fct1( data:PByteArray);
var
t:byte;
begin
// if (ShowLog) SendMSG(0,"Fct1 on Ident: X", CurrentIdent);
// unsigned char t;
Core(@data[0], 0);
case CurrentIdent of
$032820:
begin
t := data[4];
data[4] := data[7];
data[7] := t;
end;
$030B00:
begin
t := data[5];
data[5] := data[7];
data[7] := t;
end;
end;
end;
procedure TViaccess3.Fct2( data:PByteArray);
var
t:byte;
begin
// if (ShowLog) SendMSG(0,"Fct2 on Ident: X", CurrentIdent);
// unsigned char t;
Core(@data[0], 4);
case CurrentIdent of
$032820:
begin
t := data[4];
data[4] := data[7];
data[7] := data[5];
data[5] := data[6];
data[6] := t;
end;
$030B00:
begin
t := data[6];
data[6] := data[7];
data[7] := t;
end;
end;
end;
procedure TViaccess3.ProcessDw( data:PByteArray);
var
i:Integer;
tmp:array[0..8-1] of byte;
tmpKey:array[0..16-1] of byte;
begin
frmMain.Messages(0,'ProcessDw->inputCW:'@data[0],8);
// SendHexDump("ProcessDw->inputCW:",0,data,8);
for i:=0 to 4-1 do
tmp[i] := data[i+4];
Fct1(@tmp[0]);
frmMain.Messages(0,'Fct1:'@tmp[0],8);
// SendHexDump("Fct1:",0,tmp,8);
for i:=0 to 4-1 do
tmp[i] := data[i] xor tmp[i+4];
Fct2(@tmp[0]);
frmMain.Messages(0,'Fct2:'@tmp[0],8);
// SendHexDump("Fct2:",0,tmp,8);
for i:=0 to 4-1 do
tmp[i]:=tmp[i] xor XorKey[i+4];
for i:=0 to 4-1 do
begin
data[i] := data[i+4] xor tmp[i+4];
data[i+4] := tmp[i];
end;
frmMain.Messages(0,'After data mixing:'@data[0],8);
//SendHexDump("CW->After data mixing:",0,data,8);
_memcpy(@tmpKey[0],@KeyDes3[0],16);
doPC1(@tmpKey[0]);
doPC1(@tmpKey[8]);
Des(@data[0], @tmpKey[0], DES_ECS2_DECRYPT);
Des(@data[0], @tmpKey[8], DES_ECS2_CRYPT);
Des(@data[0], @tmpKey[0], DES_ECS2_DECRYPT);
frmMain.Messages(0,'After 3Des:'@data[0],8);
// SendHexDump("CW->After 3Des:",0,data,8);
for i:=0 to 4-1 do
tmp[i] := data[i+4];
Fct2(@tmp[0]);
frmMain.Messages(0,'Fct2:'@tmp[0],8);
//SendHexDump("Fct2:",0,tmp,8);
for i:=0 to 4-1 do
tmp[i] := data[i] xor tmp[i+4];
Fct1(@tmp[0]);
frmMain.Messages(0,'Fct1:'@tmp[0],8);
// SendHexDump("Fct1:",0,tmp,8);
for i:=0 to 4-1 do
tmp[i]:=tmp[i] xor XorKey[i];
for i:=0 to 4-1 do
begin
data[i] := data[i+4] xor tmp[i+4];
data[i+4] := tmp[i];
end;
frmMain.Messages(0,'ProcessDw->outputDW after data mixing:'@data[0],8);
/// SendHexDump("ProcessDw->outputDW after data mixing:",0,data,8);
end;
function TViaccess3.Via3Decrypt( pNanoEA:PByteArray;dw:PByteArray):Boolea n;
var
tmpData:array[0..8-1] of byte;
pXorVector:PByteArray;
i,ii:Integer;
begin
if (CurrentIdent = 0)then
begin
// if (ShowLog) SendMSG(0,"Bad viac ecm...");
result:= false;
exit;
end;
if ( not RequestKeys()) then begin
// if (ShowLog) SendMSG(0,"Bad viac ecm...");
result:= false;
exit;
end;
frmMain.Messages(0,'CWs:'@pNanoEA[0],16);
// SendHexDump("CWs: ",0,pNanoEA,16);
if (needsAES) and ( not AesAfterVia3Core) then
begin
AESDecrypt(@AESKey[0],@pNanoEA[0]);
// Aes.SetKey(AESKey);
// Aes.Decrypt(pNanoEA,16);
frmMain.Messages(0,'CW after AES:'@pNanoEA[0],16);
// SendHexDump("CW after AES: ",0,pNanoEA,16);
end;
for i:=0 to 2-1 do
begin
_memcpy(@tmpData[0], @pNanoEA[i*8], 8);
ProcessDw(@tmpData[0]);
if (i<>0) then
pXorVector := pNanoEA
else
pXorVector := @IV[0];
for ii:=0 to 8-1 do
dw[i*8+ii] := tmpData[ii] xor pXorVector[ii];
end;
frmMain.Messages(0,'Final DW after xor:'@dw[0],16);
// SendHexDump("Final DW after xor: ",0,dw,16);
if (needsAES and AesAfterVia3Core) then
begin
AESDecrypt(@AESKey[0],@dw[0]);
// Aes.SetKey(AESKey);
// Aes.Decrypt(dw,16);
frmMain.Messages(0,'Main DW after AES:'@dw[0],16);
// SendHexDump("Main DW after AES: ",0,dw,16);
end;
if (CurrentIdent = $030B00) then
begin
//hmm.. we can check it's dcw crc this time...
if ( not HasValidCRC(dw)) then
begin
// if (ShowLog) SendMSG(1,"Wrong crc.");
result:= false;
exit;
end;
end;
result:= true;
end;
end.
unit Irtedo2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,Helper,Des;
const
DES_ENCRYPT = 1 ;
DES_DECRYPT = 0 ;
//DES_LONG = Cardinal;
TYPE_I1 = 0;
TYPE_OP = 1 ;
TYPE_IV = 2 ;
TYPE_SEED =3 ;
TYPE_PMK = 4 ;
Type
TIrtedo2 = class
private
ks1: DES_key_schedule; // OpenSSL DES_key_schedule <>
ks2: DES_key_schedule; // OpenSSL DES_key_schedule <>
procedure ScheduleKey(const Key:PByteArray);
procedure DES3(data:PByteArray;mode :Integer);
procedure PrepareSeed(seed:PByteArray; const key:PByteArray);
procedure NanoDecrypt(data:PByteArray; i:Integer; len:Integer; const key:PByteArray;const iv:PByteArray);
public
constructor Create();
destructor Destroy; override;
procedure Encrypt(data:PByteArray; const seed:PByteArray; const key:PByteArray; len:Integer);
procedure Decrypt(data:PByteArray; const seed:PByteArray; const key:PByteArray; len:Integer);
function CalculateHash(const key:PByteArray; const iv:PByteArray; const data:PByteArray; len:Integer):Boolean;
function ProcessECM(data:PByteArray):Boolean;
End;
implementation
Uses UntMain,Unit2;
procedure XXOR( d: PByteArray; l:integer;const v1:PByteArray; const v2:PByteArray);
var
i:Byte;
begin
if (l=16) or (l=8) or (l=4) then
begin
for i:=0 to l-1 do
d[i] := v1[i] xor v2[i];
end
else
for i:= l - 1 downto 0 do
d[i] := v1[i] xor v2[i];
end;
constructor TIrtedo2.Create();
Begin
inherited Create();
FillChar(ks1,32,0);
FillChar(ks2,32,0);
End;
destructor TIrtedo2.Destroy;
Begin
inherited Destroy;
End;
procedure TIrtedo2.ScheduleKey(const Key:PByteArray);
begin
DES_key_sched((@key[0]), @ks1[0]);
DES_key_sched((@key[8]), @ks2[0]);
end;
procedure TIrtedo2.DES3(data:PByteArray;mode :Integer);
var
m1,m2:Integer;
begin
if(mode>0)then begin m1:=DES_DECRYPT; m2:=DES_ENCRYPT; end
else begin m1:=DES_ENCRYPT; m2:=DES_DECRYPT; end;
DES_ecb_encrypt(@data[0],@data[0],@ks1[0],m1);
DES_ecb_encrypt(@data[0],@data[0],@ks2[0],m2);
DES_ecb_encrypt(@data[0],@data[0],@ks1[0],m1);
end;
procedure TIrtedo2.Encrypt(data:PByteArray; const seed:PByteArray; const key:PByteArray; len:Integer);
var
i:integer;
tmp: PByteArray;
begin
ScheduleKey(@key[0]);
len:=len and (not 7);
tmp:=seed;
i:=0;
while (i<len-1) do begin
xxor(@data[i],8,@data[i],tmp);
tmp:=@data[i];
DES3(@data[i],0);
inc(i,8);
end;
end;
procedure TIrtedo2.Decrypt(data:PByteArray; const seed:PByteArray; const key:PByteArray; len:Integer);
var
i:Integer;
buf:array[0..2-1,0..8-1] of byte;
n,z:Integer;
begin
ScheduleKey(@key[0]);
z:=0;
len:=len and (not 7);
n:=0;
_memcpy(@buf[n],seed,8);
i:=0;
while i<len-1 do begin
_memcpy(@buf[1-n],@data[z],8);
DES3(@data[z],1);
xxor(@data[z],8,@data[z],@buf[n]);
inc(i,8);
inc(z,8);
n:=n xor 1;
end;
end;
function TIrtedo2.CalculateHash(const key:PByteArray; const iv:PByteArray; const data:PByteArray; len:Integer):Boolean;
var
cbuff:array[0..8-1] of byte;
y,l:Integer;
begin
ScheduleKey(@key[0]);
_memset(@cbuff[0],0,8);
len:=len-8;
y:=0;
while y<len-1 do begin
if(y<len-8) then begin
xxor(@cbuff[0],8,@cbuff[0],@data[y]);
end
else begin
l:=len-y;
xxor(@cbuff[0],l,@cbuff[0],@data[y]);
xxor(@cbuff[l],8-l,@cbuff[l],@iv[8]);
end;
DES3(@cbuff[0],0);
inc(y,8);
end;
result:= _memcmp(@cbuff[0],@data[len],8)=0;
end;
procedure TIrtedo2.PrepareSeed(seed:PByteArray; const key:PByteArray);
var
blank:array[0..16-1] of byte;
begin
_memset(@blank[0],0,16);
Encrypt(@seed[0],@blank[0],@key[0],16);
end;
function NANOLEN(_a:Integer) :Integer;
begin
if (_a)>0 then result:=((_a)and $3F)+2 else result:= 1;
end;
procedure TIrtedo2.NanoDecrypt(data:PByteArray; i:Integer; len:Integer; const key:PByteArray;const iv:PByteArray);
var
l:Integer;
begin
while(i<len-1) do begin
l:=NANOLEN(data[i+1]);
case data[i] of
$10: ;
$50:begin if(l=$13) and (i<=len-l) then Decrypt(@data[i+3],@iv[0],@key[0],16); break; end;
$78:begin if(l=$14) and (i<=len-l) then Decrypt(@data[i+4],@iv[0],@key[0],16); break; end;
end;
i:=i+l;
end;
end;
function PROV(keynr:Integer):Integer;
begin
result:= (((keynr)shr 16)and $FF);
end;
function TYPE_(keynr:Integer):Integer;
begin
result:= (((keynr)shr 8)and $FF) ;
end;
function ID(keynr:Integer) :Integer;
begin
result:= (((keynr) )and $FF);
end;
function KEYSET(prov:Integer;typ:Integer;id:Integ er):Integer;
begin
result:= ((((prov)and $FF)shl 16)or(((typ)and $FF)shl 8)or ((id)and $FF));
end;
function SCT_LEN(sct:pbytearray):Integer;
begin
result:= (3+((sct[1]and $0f) shl 8)+sct[2]);
end;
function FindKey(Mode:String;ProviderID:integer;K eyIndex:string;var Key :String; var KeyLen:Integer):Boolean;
var
SoftCamFile: TextFile;
S: String;
StringList: TStrings;
begin
result:=False;
Key:='0000000000000000';
KeyLen:=0;
AssignFile(SoftCamFile,'SoftCam.key' );
Reset(SoftCamFile);
try
while not Eof(SoftCamFile) do
begin
Readln(SoftCamFile, S);
if Pos(trim(Mode), S) = 1 then
begin
StringList := TStringList.Create;
try
ExtractStrings([' ',';'],[' '],pchar(S),StringList); // (trim(StringList[0])=trim(Mode)) and
if (trim(StringList[0])=trim(Mode)) and(HexToInt(trim(StringList[1]))=(ProviderID)) and (trim(StringList[2])=trim(KeyIndex)) then
begin
Key:=trim(StringList[3]);
KeyLen:=Length(trim(Key))div 2;
result:=True;
Break;
end;
finally
StringList.free;
end;
end;
end;
finally
CloseFile(SoftCamFile);
end;
end;
function TIrtedo2.ProcessECM(data:PByteArray):Boo lean;
var
len:Integer;
chid,prov:Integer;
keyNr:Integer;
i,l:Integer;
cw:array[0..16-1] of byte;
caid:integer;
Softkey:string;
SoftKeyLen:integer;
OP_KEY_06:array[0..16-1] of byte;
ECM_SEED :array[0..16-1] of byte;
ECM_IV :array[0..16-1] of byte;
ECM_SEED_Prepare:array[0..16-1] of byte;
begin
frmMain.Messages(0,'System Irtedo-2');
len:=data[11];
caid:=$062200;
if(len<>$28) or (SCT_LEN(data)<len+12) then begin
showmessage('bad ECM length');
result:= false;
exit;
end;
chid:= (data[7]) ;
prov:=data[8];
keyNr:=(data[9]);
frmMain.StatusBar2.Panels[0].Text:=Format('%s', ['IRTEDO2']);
frmMain.Edit3.Text:=IntToHex(prov,2);
frmMain.Edit4.Text:=IntToHex(keyNr,2);
{
if FindKey('I',caid,IntToHex(keyNr,2),Softk ey,SoftKeyLen) then begin
for i := 1 to SoftKeyLen do OP_KEY_06[i-1] := strtoint('$'+copy(Softkey,(2*i)-1,2));
frmMain.StatusBar2.Panels[1].Text:= HexStrSpaced(@OP_KEY_06[0],16);
end;
if FindKey('I',caid,'M1',Softkey,SoftKeyLen ) then begin
for i := 1 to SoftKeyLen do ECM_SEED[i-1] := strtoint('$'+copy(Softkey,(2*i)-1,2));
// form1.Edit2.Text:= HexStrSpaced(@ECM_SEED[0],16);
end;
if FindKey('I',caid,'M2',Softkey,SoftKeyLen ) then begin
for i := 1 to SoftKeyLen do ECM_IV[i-1] := strtoint('$'+copy(Softkey,(2*i)-1,2));
// form1.Edit4.Text:= HexStrSpaced(@ECM_IV[0],16);
end;
}
NanotoBytearray(frmMain.Edit11.Text,OP_K EY_06);
NanotoBytearray(frmMain.Edit12.Text,ECM_ SEED);
NanotoBytearray(frmMain.Edit13.Text,ECM_ IV);
PrepareSeed(@ECM_SEED[0],@OP_KEY_06[0]);
// form1.Edit3.Text:= HexStrSpaced(@ECM_SEED[0],16);
Decrypt(@data[12+0],@ECM_IV[0],@ECM_SEED[0],len);
// form1.Edit9.Text:= HexStrSpaced(@data[24],16);
i:=(data[12+0] and 7)+1;
NanoDecrypt(@data[12+0],i,len-8,@OP_KEY_06[0],@ECM_IV[0]);
// form1.Memo2.Text:= HexStrSpaced(@data[0],52-8);
// form1.Edit10.Text:= HexStrSpaced(@data[24],16);
// form1.Edit11.Text:= HexStrSpaced(@data[44],8);
if (CalculateHash(@ECM_SEED[0],@ECM_IV[0],@data[12-6],len+6)) then begin
//HEXDUMP(L_SYS_RAWECM,data-12,len+12,"Irtedo2 RAWECM");
while(i<len-8) do begin
if data[12+i+1] >0 then
l:= (data[12+i+1]and $3F)+2 else l:= 1;
case (data[12+i]) of
$78:begin
_memcpy(@cw[0],@data[12+i+4],16);
frmMain.Edit5.Text:=HexStr(@cw[0],8);
frmMain.Edit15.Text:=HexStr(@cw[8],8);
// form1.Edit12.Text:= HexStrSpaced(@cw[0],16);
//ks.OK(pk);
result:= true;
exit;
end;
end;
i:=i+l;
end;
end
else begin
showmessage('hash failed');
end;
result:= false;
end;
end.
unit Viaccess26;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,crypto,AES,RC6,Helper;
const
OP_KEY:array[0..16-1] of byte = ($94 ,$FB ,$D7 ,$05 ,$B7 ,$19 ,$A4 ,$86 ,$10 ,$1E ,$19 ,$A6 ,$00 ,$5A ,$25 ,$15);
T1:array[0..256-1] of byte = ($CB
,$90 ,$B6 ,$F5 ,$44 ,$B4 ,$3A ,$32 ,$66
,$48 ,$1D ,$B5 ,$AC ,$A1 ,$12 ,$9F ,$B9
,$F7 ,$0E ,$34 ,$EF ,$E1 ,$68 ,$D3 ,$83
,$2D ,$41 ,$CF ,$BC ,$0A ,$55 ,$BD ,$A3
,$99 ,$C3 ,$D2 ,$85 ,$C4 ,$E8 ,$74 ,$C5
,$51 ,$82 ,$58 ,$70 ,$19 ,$9E ,$3B ,$39
,$AD ,$07 ,$9A ,$13 ,$C7 ,$D0 ,$AF ,$92
,$30 ,$06 ,$2F ,$C8 ,$5B ,$42 ,$C1 ,$94
,$1A ,$3E ,$86 ,$04 ,$A0 ,$B2 ,$9D ,$09
,$F8 ,$8E ,$84 ,$ED ,$6E ,$87 ,$FC ,$7B
,$29 ,$59 ,$77 ,$9C ,$1E ,$DC ,$F3 ,$2B
,$52 ,$F9 ,$3D ,$F4 ,$A9 ,$D8 ,$DB ,$7D
,$CC ,$78 ,$DE ,$A2 ,$A5 ,$08 ,$CD ,$16
,$71 ,$80 ,$B8 ,$7F ,$FD ,$4D ,$F6 ,$2C
,$69 ,$DF ,$F1 ,$27 ,$8B ,$FB ,$53 ,$62
,$9B ,$E5 ,$50 ,$96 ,$60 ,$B0 ,$6C ,$6A
,$EE ,$2A ,$18 ,$4B ,$24 ,$43 ,$4E ,$E6
,$AE ,$F2 ,$75 ,$E2 ,$D7 ,$4A ,$EA ,$01
,$EC ,$38 ,$FA ,$40 ,$EB ,$7C ,$E0 ,$A6
,$21 ,$33 ,$79 ,$54 ,$47 ,$2E ,$0F ,$45
,$0D ,$64 ,$20 ,$D4 ,$65 ,$98 ,$BA ,$D6
,$5D ,$BB ,$B7 ,$0C ,$31 ,$89 ,$37 ,$7E
,$D1 ,$46 ,$C6 ,$05 ,$0B ,$02 ,$AB ,$6B
,$10 ,$A7 ,$AA ,$1C ,$1F ,$E3 ,$F0 ,$FE
,$3F ,$E4 ,$22 ,$25 ,$28 ,$B3 ,$35 ,$3C
,$CE ,$E9 ,$00 ,$61 ,$67 ,$C9 ,$1B ,$36
,$B1 ,$23 ,$17 ,$A4 ,$DD ,$A8 ,$8D ,$5E
,$FF ,$E7 ,$5F ,$56 ,$D5 ,$63 ,$72 ,$97
,$15 ,$8C ,$BE ,$C2 ,$7A ,$88 ,$DA ,$26
,$CA ,$8F ,$95 ,$91 ,$4C ,$81 ,$14 ,$BF
,$73 ,$8A ,$57 ,$5C ,$03 ,$6F ,$11 ,$49
,$5A ,$93 ,$76 ,$4F ,$6D ,$C0 ,$D9);
//D1
D1:array[0..8-1] of byte = ($13 ,$CE ,$62 ,$7A ,$F7 ,$1A ,$53 ,$1A);
//X1
X1:array[0..8-1] of byte = ($D3 ,$BE ,$5F ,$43 ,$29 ,$DA ,$FF ,$C9);
//P1
P1:array[0..8-1] of byte = ($06 ,$04 ,$00 ,$01 ,$03 ,$07 ,$02 ,$05);
//C1
C1:array[0..8-1] of byte = ($B6 ,$67 ,$8B ,$8C ,$82 ,$A2 ,$6B ,$4E);
Type
TViaccess2 =class(TDes)
private
T1Key:array[0..256-1] of byte;
KeyDes3:array[0..16-1] of byte;
KeyDes1:array[0..8-1] of byte;
XorKey:array[0..8-1] of byte;
XPos:array[0..8-1] of byte;
IV:array[0..8-1] of byte;
procedure ProcessDw(indata:PByteArray);
function RequestKeys():Boolean;
public
CurrentIdent:Integer;
DesKeyIdx:Integer;
constructor Create();
destructor Destroy; override;
function Via26Decrypt( pNanoEA:PByteArray;dw:PByteArray):Boolea n;
end;
implementation
Uses UntMain;
procedure XXOR( d: PByteArray; const v1:PByteArray;l:integer);
var
i,z:Integer;
begin
for i:=0 to l-1 do
d[i] := d[i] xor v1[i];
end;
constructor TViaccess2.Create();
begin
inherited Create(nil,0,nil,0);
end;
destructor TViaccess2.Destroy;
begin
inherited Destroy;
end;
function TViaccess2.RequestKeys():Boolean;
begin
_memcpy(@T1Key[0],@T1[0],256);
_memcpy(@KeyDes3[0],@OP_KEY[0],16);
_memcpy(@KeyDes1[0],@D1[0],8);
_memcpy(@XorKey[0],@X1[0],8);
_memcpy(@XPos[0],@P1[0],8);
_memcpy(@IV[0],@C1[0],8);
Result:=true;
end;
procedure TViaccess2.ProcessDw(indata:PByteArray);
var
pv1,pv2:byte;
i:Integer;
Tmp:array[0..8-1] of byte;
tmpKey:array[0..16-1] of byte;
begin
frmMain.Messages(0,'processDw->inputCW:'@indata[0],8);
//SendHexDump("processDw->inputCW:",0,indata,8);
for i:=0 to 8-1 do
begin
pv1 := indata[i];
Tmp[i] := T1Key[pv1];
end;
for i:=0 to 8-1 do
begin
pv1 := XPos[i];
pv2 := Tmp[pv1];
indata[i]:=pv2;
end;
frmMain.Messages(0,'CW->After data mixing:: '@indata[0],8);
// SendHexDump("CW->After data mixing:",0,indata,8);
_memcpy(@tmpKey[0], @KeyDes1[0],8);
doPC1(@tmpKey[0]) ;
frmMain.Messages(0,'st Permute: '@tmpKey[0],8);
// SendHexDump("1st Permute:",0,tmpKey,8);
frmMain.Messages(0,'indata before 1st Des:',@indata[0],8);
// SendHexDump("indata before 1st Des:",0,indata,8);
Des(@indata[0],@tmpKey[0], DES_ECS2_CRYPT);
frmMain.Messages(0,'indata after 1st Des '@indata[0],8);
// SendHexDump("indata after 1st Des:",0,indata,8);
XXor(@indata[0], @XorKey[0], 8);
frmMain.Messages(0,'CW->After xxor:',@indata[0],8);
//SendHexDump("CW->After xxor:",0,indata,8);
_memcpy(@tmpKey[0],@KeyDes3[0],16);
doPC1(@tmpKey[0]);
doPC1(@tmpKey[8]);
Des(@indata[0],@tmpKey[0],DES_ECS2_DECRYPT);
Des(@indata[0],@tmpKey[8], DES_ECS2_CRYPT );
Des(@indata[0],@tmpKey[0],DES_ECS2_DECRYPT );
frmMain.Messages(0,'CW->After 3Des:',@indata[0],8);
// SendHexDump("CW->After 3Des:",0,indata,8);
XXor(@indata[0], @XorKey[0], 8);
frmMain.Messages(0,'CW->After xxor:',@indata[0],8);
// SendHexDump("CW->After xxor:",0,indata,8);
_memcpy(@tmpKey[0], @KeyDes1[0],8);
doPC1(@tmpKey[0]);
Des(@indata[0],@tmpKey[0], DES_ECS2_DECRYPT);
frmMain.Messages(0,'CW->After final Des:',@indata[0],8);
//SendHexDump("CW->After final Des:",0,indata,8);
for i:=0 to 8-1 do
begin
pv1 := indata[i];
pv2 := XPos[i];
Tmp[pv2] := pv1;
end;
for i:=0 to 8-1 do
begin
pv1 := Tmp[i];
pv2 := T1Key[pv1];
indata[i] := pv2;
end;
frmMain.Messages(0,'processDw->outputDW after data mixing:',@indata[0],8);
//SendHexDump("processDw->outputDW after data mixing:",0,indata,8);
// return;
end;
function TViaccess2.Via26Decrypt( pNanoEA:PByteArray;dw:PByteArray):Boolea n;
var
tmpData:array[0..8-1] of byte;
pXorVector:PByteArray;
i:Integer;
ii:Integer;
begin
if (CurrentIdent = 0) then
begin
// if (ShowLog) SendMSG(0,"bad viac ecm...");
result:= false;
exit;
end;
if ( not RequestKeys( )) then
begin
result:= false;
exit;
end;
for i:=0 to 2-1 do
begin
_memcpy(@tmpData[0], @pNanoEA[i*8], 8);
ProcessDw(@tmpData[0]) ;
if (i<>0) then
pXorVector := pNanoEA
else
pXorVector := @IV[0];
for ii:=0 to 8-1 do
dw[i*8+ii] := tmpData[ii] xor pXorVector[ii];
end;
frmMain.Messages(0,'Final DW after xor: '@dw[0],16);
//SendHexDump("Final DW after xor: ",0,dw,16);
result:= true; //there is no hash algo for this version...
end;
end.
{*************************************** ****************
**************************************** ****************
**************************************** ****************
* Softcam plugin to VDR (C++) to Delphi implementation *
* written by Ekrem KOÇAK *
**************************************** ****************
**************************************** ****************
**************************************** ***************}
unit Viaccess1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,crypto,AES,RC6,Helper;
Const
TPS_T1:Array[0..64-1] of Byte =(
$4F,$B4,$FC,$9B,$4A,$7F,$44,$FB,$05,$FF, $BD,$BB,$16,$2D,$6C,$C8,
$D8,$96,$F9,$FE,$3F,$FF,$36,$24,$B6,$BF, $49,$C9,$2D,$36,$5E,$D0,
$1F,$09,$7E,$A9,$7F,$FF,$64,$B6,$5B,$7E, $F8,$FC,$6E,$3F,$7F,$BF,
$DD,$36,$12,$E9,$05,$FE,$B4,$6C,$6F,$FE, $7E,$C8,$25,$90,$6D,$90
);
TPS_T2:Array[0..64-1] of Byte =(
$7E,$6D,$7E,$12,$76,$FD,$2F,$FE,$6D,$FE, $DA,$3F,$DA,$6D,$BD,$97,
$D0,$6D,$D8,$9F,$69,$FD,$B6,$37,$FE,$7F, $36,$92,$BD,$52,$16,$DF,
$FC,$96,$FF,$92,$FD,$6D,$7F,$B5,$FB,$4C, $B6,$B7,$7E,$D9,$FE,$9B,
$FD,$F4,$6D,$9B,$B9,$36,$BF,$7F,$D2,$2D, $DF,$B7,$D9,$FE,$69,$BF
);
Type
TViaccess1 = class(TDes)
Private
V2mode:Boolean;
V2key:Array[0..7] of Byte;
Function HashNanos(Data:PByteArray;Len:Integer):I nteger;
procedure Via2Mod(Key2:PByteArray;Data:PByteArray) ;
Protected
hbuff:Array[0..7] of Byte;
hkey:Array[0..7] of Byte;
pH:integer;
Procedure SetHashKey(const Key:PByteArray);
Procedure HashByte(c: Byte);
Procedure HashClear;
Procedure Hash;
Procedure Decode(Data:PByteArray; Key:PByteArray);
Function _Mod(R:Integer;Key7:integer):Integer;
public
CurrentIdent:Integer;
DesKeyIdx:Integer;
constructor Create();
destructor Destroy; override;
Procedure SetV2Mode(const Key2:PByteArray);
Function Decrypt(work_key:PByteArray;Data:PByteAr ray;len:Integer;des_Data1:PByteArray;des _Data2:PByteArray) :boolean;
Function TpsDecrypt(Data:PByteArray; len:Integer;Key:PByteArray):Integer;
Function AESDecrypt( Key: PByteArray ; InBlock:PByteArray) : string;
Procedure RC6decrypt(Key: PByteArray ; InBlock:PByteArray);
function Via1Decrypt(source:PByteArray;dw:PByteAr ray):Boolean;
end;
implementation
Uses UntMain,Unit2;
function TViaccess1.Via1Decrypt(source:PByteArray ;dw:PByteArray):Boolean;
begin
Decrypt(@VIA1_KEY[0],@source[9],source[2]-6,@dw[0],@dw[8]);
end;
constructor TViaccess1.Create();
var
i:Integer;
Begin
inherited Create(nil,0,nil,0);
v2mode:=false;
End;
destructor TViaccess1.Destroy;
Begin
inherited Destroy;
End;
Function TViaccess1._Mod(R:Integer;Key7:Integer): Integer;
var
Key5,al:Integer;
Begin
If(Key7<>0)Then
Begin
Key5:=(R shr 24)and $ff;
al:=Key7*Key5 + Key7 + Key5;
al:=(al And $ff)-((al shr 8)And $ff);
If(al And $100)= $100 Then inc( al,1);
R:=(R And $00ffffff) + (al shl 24);
End;
result:= R;
End;
Procedure TViaccess1.Via2Mod( Key2:PByteArray;Data:PByteArray);
var
kb, db,a0,pos:Integer;
Begin
for db:=7 downto 0 do Begin
for kb:=7 downto Succ(3) do Begin
a0:=kb xor db;
pos:=7;
If (a0 And 4)>0 Then Begin a0:=a0 xor 7; pos:=pos xor 7; End;
a0:=(a0 xor (kb And 3)) + (kb And 3);
If (a0 And 4)= 0 Then Data[db]:=Data[db] xor ((Key2[kb] xor ((Data[kb xor pos]* Key2[kb xor 4])And $FF ) ));
End;
End;
for db:=0 to Pred(8) do Begin
For kb:=0 to Pred(4) do Begin
a0:=kb xor db;
pos:=7;
If(a0 And 4)>0 Then Begin a0:=a0 xor 7; pos:=pos xor 7; End;
a0:=(a0 xor(kb And 3)) + (kb And 3);
If (a0 And 4) =0 Then Data[db]:=Data[db] xor ((Key2[kb] xor ((Data[kb xor pos]*Key2[kb xor 4]) And $FF)));
End;
End;
End;
Procedure TViaccess1.Decode(Data:PByteArray; Key:PByteArray);
Begin
If(v2mode)Then Via2Mod(@v2Key[0],@Data[0]);
Des(@Data[0],@Key[0],VIA_DES);
If(v2mode)Then Via2Mod(@v2Key[0],@Data[0]);
End;
Procedure TViaccess1.SetV2Mode(const Key2:PByteArray);
Begin
If(Key2[0]<>0) Then
Begin
_memcpy(@v2Key[0],@Key2[0],sizeof(v2Key));
v2mode:=true;
End
Else v2mode:=false;
End;
Procedure TViaccess1.SetHashKey(const Key:PByteArray);
Begin
_memcpy(@hKey[0],@Key[0],sizeof(hKey));
End;
Procedure TViaccess1.HashClear;
Begin
_memset(PByteArray(@hbuff), 0, SizeOf(hbuff));
pH:=0;
End;
Procedure TViaccess1.Hash;
Begin
If(v2mode)Then Via2Mod(@v2Key[0],@hbuff[0]);
Des(@hbuff[0],@hKey[0],VIA_DES_HASH);
If(v2mode)Then Via2Mod(@v2Key[0],@hbuff[0]);
End;
Procedure TViaccess1.HashByte(c: Byte);
Begin
hbuff[pH]:=hbuff[pH] xor c;
pH:=pH+1;
If(pH=8)Then
Begin
pH:=0;
Hash();
End;
End;
Function TViaccess1.HashNanos(Data:PByteArray;len :Integer):Integer;
var
i,j,m:Integer;
Begin
i:=0;
pH:=0;
If(Data[0]=$9f) Then Begin
HashByte(Data[i]);
i:=i+1 ;
HashByte(Data[i]);
i:=i+1 ;
For j:=0 to Pred(Data[1]) do Begin i:=i+1 ; HashByte(Data[i]); End;
while not(pH=0) do HashByte(0);
End;
while i<len do Begin
HashByte(Data[i]);
inc(i);
End;
result:= i;
exit;
End;
Function TViaccess1.Decrypt(work_Key:PByteArray;D ata:PByteArray;len:Integer;des_Data1:PBy teArray;des_Data2:PByteArray) :boolean;
var
pos:Integer;
encStart:Integer;
signatur:Array[0..7]of Byte;
prepared_Key:Array[0..7]of Byte;
k,tmp:Byte;
i,j:Integer;
Begin
pos:=0;
encStart:=0;
pH :=0;
while(pos<len) do Begin
case (Data[pos]) of
$EA: Begin
encStart := pos + 2;
_memcpy(PByteArray(@des_Data1[0]),@Data[pos+2],8);
_memcpy(PByteArray(@des_Data2[0]),@Data[pos+2+8],8);
End;
$F0:Begin // signature
_memcpy(@signatur[0],@Data[pos+2],8);
End;
End;
pos :=pos + Data[pos+1]+2;
End;
HashClear();
SetHashKey(work_Key);
If (work_Key[7]=0)Then Begin
HashNanos(Data,encStart+16);
_memcpy(@prepared_Key[0],@work_Key[0],8);
End
Else
Begin
prepared_Key[0]:=work_Key[2];
prepared_Key[1]:=work_Key[3];
prepared_Key[2]:=work_Key[4];
prepared_Key[3]:=work_Key[5];
prepared_Key[4]:=work_Key[6];
prepared_Key[5]:=work_Key[0];
prepared_Key[6]:=work_Key[1];
prepared_Key[7]:=work_Key[7];
If(work_Key[7] And $01) = 1 Then
Begin
HashNanos(Data,encStart);
If (work_Key[7] > $0F) Then k :=$5A Else k := $A5;
For i:=0 to 7 do Begin
tmp:=des_Data1[i];
des_Data1[i]:=des_Data1[i] xor (hbuff[pH] And tmp);
HashByte(tmp);
End;
For i:=0 to 7 do Begin
tmp:=des_Data2[i];
des_Data2[i]:=des_Data2[i] xor (hbuff[pH] And tmp);
HashByte(tmp);
End;
End
Else Begin
HashNanos(Data,encStart+16);
End;
End;
Decode(@des_Data1[0],@prepared_Key[0]);
Decode(@des_Data2[0],@prepared_Key[0]);
Hash();
Begin
result:= (_memcmp(@signatur,@hbuff,8)=0);
End;
End;
Procedure TViaccess1.RC6decrypt(Key: PByteArray; InBlock:PByteArray);
var
Data: TRC6Data;
outBlock: Array[0..15] of Byte;
Begin
fillchar(outBlock, 16, 0);
RC6Init(Data, @Key, Sizeof(Key), nil);
RC6DecryptCBC(Data, @InBlock, @outBlock);
move(outBlock[0], InBlock[0], 16);
RC6Burn(Data);
End;
Function TViaccess1.AESDecrypt(Key:PByteArray ;InBlock:PByteArray):string;
var
TempBuf: TAESBuffer;
Buffer: TAESBuffer;
ExpAndedKey: TAESExpAndedKey128;
Key128: TAESKey128;
Begin
move(Key[0], Key128[0], 16);
ExpAndAESKeyForDecryption(Key128, ExpAndedKey);
move(InBlock[0], Buffer[0], 16);
DecryptAES(Buffer, ExpAndedKey, TempBuf);
move(TempBuf[0], InBlock[0], 16);
End;
Function TViaccess1.TpsDecrypt(Data:PByteArray; len:Integer;Key:PByteArray):Integer;
var
offset:cardinal;
i:Integer;
table:Array[0..64-1] of Byte;
Begin
If (Data[0]<>$D2) or (Data[1]<>$01) or (Data[2]<>$01) Then Begin result:=0;exit;End;
offset:=3;
len:=len-3;
If(Data[offset]=$40) Then
Begin // TPS crypt v2 (AES)
Data[offset]:=$90;
i:=0;
while i<len do Begin
If(Data[offset+i]=$EA) Then
Begin
// RC6decrypt(@Key[0],@Data[offset+i+2]);
AESDecrypt(@Key[0],@Data[offset+i+2]);
break;
End;
inc(i,Data[offset+i+1]+2);
End;
End
Else Begin // TPS crypt v1 (XOR)
If Data[offset]=$DF Then
_memcpy(@table[0],@TPS_T1[0],64)
Else
_memcpy(@table[0],@TPS_T2[0],64);
For i:=len-1 downto 0 do Data[offset+i]:=Data[offset+i] xor table[i And 63];
End;
result:= 3;
End;
End.