📄 viaccess.c
字号:
bool cViaccess::Decrypt(const unsigned char *work_key, const unsigned char *data, int len, unsigned char *des_data1, unsigned char *des_data2){ int pos=0, encStart=0; unsigned char signatur[8]; while(pos<len) { switch(data[pos]) { case 0xea: // encrypted bytes encStart = pos + 2; memcpy(des_data1,&data[pos+2],8); memcpy(des_data2,&data[pos+2+8],8); break; case 0xf0: // signature memcpy(signatur,&data[pos+2],8); break; } pos += data[pos+1]+2; } HashClear(); SetHashKey(work_key); // key preparation unsigned char prepared_key[8]; if(work_key[7]==0) { // 8th key-byte = 0 then like Eurocrypt-M but with viaccess mods HashNanos(data,encStart+16); memcpy(prepared_key,work_key,sizeof(prepared_key)); } else { // key8 not zero // rotate the key 2x left 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]; // test if key8 odd if(work_key[7]&1) { HashNanos(data,encStart); // test if low nibble zero unsigned char k = ((work_key[7] & 0xf0) == 0) ? 0x5a : 0xa5; for(int i=0; i<8; i++) { unsigned char tmp=des_data1[i]; des_data1[i]=(k & hbuff[pH]) ^ tmp; HashByte(tmp); } for(int i=0; i<8; i++) { unsigned char tmp=des_data2[i]; des_data2[i]=(k & hbuff[pH]) ^ tmp; HashByte(tmp); } } else { HashNanos(data,encStart+16); } } Decode(des_data1,prepared_key); Decode(des_data2,prepared_key); Hash(); return (memcmp(signatur,hbuff,8)==0);}// -- cSystemViaccess ----------------------------------------------------------#define MAX_NEW_KEYS 5class cSystemViaccess : public cSystem, private cViaccess {private: cTPS tps;public: cSystemViaccess(void); virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data); virtual void ProcessEMM(int pid, int caid, unsigned char *data); virtual void ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned short sysId, const unsigned char *data, int len); };cSystemViaccess::cSystemViaccess(void):cSystem(SYSTEM_NAME,SYSTEM_PRI){ hasLogger=true;}void cSystemViaccess::ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned short sysId, const unsigned char *data, int len){ const int pid=WORD(data,2,0x1FFF); if(pid>=0xAA && pid<=0xCF) { PRINTF(L_CORE_ECMPROC,"viaccess: dropped \"fake\" ecm pid 0x%04x",pid); return; } cSystem::ParseCADescriptor(ecms,sysId,data,len);}bool cSystemViaccess::ProcessECM(const cEcmInfo *ecm, unsigned char *data){ unsigned char *nanos=(unsigned char *)cParseViaccess::NanoStart(data); int len=SCT_LEN(data)-(nanos-data); bool mayHaveTps=false; if(ecm->provId==0x007c00) { // TPS maxEcmTry=4; mayHaveTps=true; int num=tps.Decrypt(CardNum(),ecm->source,ecm->transponder,nanos,len); if(num<0) return false; nanos+=num; len-=num; } if(cParseViaccess::CheckNano90FromNano(nanos)) { int keynr=cParseViaccess::KeyNrFromNano(nanos); cKeySnoop ks(this,'V',ecm->provId,keynr); cPlainKey *pk=0; while((pk=keys.FindKey('V',ecm->provId,keynr,-1,pk))) { unsigned char key[16]; if(pk->Size()<=(int)sizeof(key)) { pk->Get(key); SetV2Mode(pk->Size()==VIA2_KEYLEN ? &key[VIA1_KEYLEN] : 0); if(cViaccess::Decrypt(key,&nanos[5],len-5,&cw[0],&cw[8])) { if(mayHaveTps) tps.PostProc(cw); ks.OK(pk); return true; } } } } return false;}void cSystemViaccess::ProcessEMM(int pid, int caid, unsigned char *data){ for(cViaccessCardInfo *mkey=Vcards.First(); mkey; mkey=Vcards.Next(mkey)) { int updtype; cAssembleData ad(data); if(mkey->cCardViaccess::MatchEMM(data)) { updtype=3; HashClear(); memcpy(hbuff+3,mkey->ua,sizeof(mkey->ua)); } else if(mkey->cProviderViaccess::MatchEMM(data)) { if(mkey->cProviderViaccess::Assemble(&ad)<0) continue; updtype=2; HashClear(); memcpy(hbuff+5,mkey->sa,sizeof(mkey->sa)-1); } else continue; const unsigned char *buff; if((buff=ad.Assembled())) { const unsigned char *scan=cParseViaccess::NanoStart(buff); unsigned int scanlen=SCT_LEN(buff)-(scan-buff); if(scanlen>=5 && mkey->cProviderViaccess::MatchID(buff) && cParseViaccess::KeyNrFromNano(scan)==mkey->keyno) { scan+=5; scanlen-=5; SetHashKey(mkey->key); Hash(); unsigned int n; if(scan[0]==0x9e && scanlen>=(n=scan[1]+2)) { for(unsigned int i=0; i<n; i++) HashByte(scan[i]); Hash(); pH=0; scan+=n; scanlen-=5; } if(scanlen>0) { unsigned char newKey[MAX_NEW_KEYS][8]; int numKeys=0, updPrv[MAX_NEW_KEYS]={}, updKey[MAX_NEW_KEYS]={}; for(unsigned int cnt=0; cnt<scanlen && numKeys<MAX_NEW_KEYS;) { const unsigned int parm=scan[cnt++]; unsigned int plen=scan[cnt++]; switch(parm) { case 0x90: case 0x9E: cnt+=plen; break; case 0xA1: // keyupdate updPrv[numKeys]=(scan[cnt]<<16)+(scan[cnt+1]<<8)+(scan[cnt+2]&0xF0); updKey[numKeys]=scan[cnt+2]&0x0F; // fall through default: HashByte(parm); HashByte(plen); while(plen--) HashByte(scan[cnt++]); break; case 0xEF: // crypted key(s) HashByte(parm); HashByte(plen); if(plen==sizeof(newKey[0])) { const unsigned char k7=mkey->key[7]; for(unsigned int kc=0 ; kc<sizeof(newKey[0]) ; kc++) { const unsigned char b=scan[cnt++]; if(k7&1) newKey[numKeys][kc]=b^(hbuff[pH]&(k7<0x10 ? 0x5a : 0xa5)); else newKey[numKeys][kc]=b; HashByte(b); } numKeys++; } else { PRINTF(L_SYS_EMM,"%d: key length mismatch %d!=%d",CardNum(),plen,sizeof(newKey[0])); cnt=scanlen; } break; case 0xF0: // signature { char str[20], str2[20]; static const char *ptext[] = { 0,0,"SHARED","UNIQUE" }; const char *addr = (updtype==2) ? HexStr(str,mkey->sa,sizeof(mkey->sa)) : HexStr(str,mkey->ua,sizeof(mkey->ua)); Hash(); if(!memcmp(&scan[cnt],hbuff,sizeof(hbuff))) { unsigned char key[8]; memcpy(key,mkey->key,sizeof(key)); if(key[7]) { // Rotate key const unsigned char t1=key[0], t2=key[1]; key[0]=key[2]; key[1]=key[3]; key[2]=key[4]; key[3]=key[5]; key[4]=key[6]; key[5]=t1; key[6]=t2; } while(numKeys--) { Decode(newKey[numKeys],key); PRINTF(L_SYS_EMM,"%02X%02X %02X %s %s - KEY %06X.%02X -> %s", mkey->ident[0],mkey->ident[1],mkey->keyno,addr, ptext[updtype],updPrv[numKeys],updKey[numKeys], HexStr(str2,newKey[numKeys],sizeof(newKey[numKeys]))); FoundKey(); if(keys.NewKey('V',updPrv[numKeys],updKey[numKeys],newKey[numKeys],8)) NewKey(); } cLoaders::SaveCache(); } else PRINTF(L_SYS_EMM,"%02X%02X %02X %s %s - FAIL",mkey->ident[0],mkey->ident[1],mkey->keyno,addr,ptext[updtype]); cnt=scanlen; break; } } } } } } }}// -- cSystemLinkViaccess ------------------------------------------------------class cSystemLinkViaccess : public cSystemLink {public: cSystemLinkViaccess(void); virtual bool CanHandle(unsigned short SysId); virtual cSystem *Create(void) { return new cSystemViaccess; } virtual bool Init(const char *cfgdir); };static cSystemLinkViaccess staticInit;cSystemLinkViaccess::cSystemLinkViaccess(void):cSystemLink(SYSTEM_NAME,SYSTEM_PRI){ Feature.NeedsKeyFile();}bool cSystemLinkViaccess::CanHandle(unsigned short SysId){ SysId&=SYSTEM_MASK; return SYSTEM_CAN_HANDLE(SysId);}bool cSystemLinkViaccess::Init(const char *cfgdir){ Vcards.Load(cfgdir,SYSTEM_NAME,"Viaccess.KID"); return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -