📄 tps.c
字号:
} return sections>=6;}bool cOpenTVModule::Decompress(void){ comp_header_t comp; comp.magic=UINT32_BE(mem); comp.csize=UINT32_BE(mem+4); comp.dsize=UINT32_BE(mem+8); comp.usize=UINT32_BE(mem+12); comp.end =UINT8_BE(mem+16); if((COMP_SECTION_HDR!=comp.magic) || (comp.dsize<=comp.csize) || (comp.usize>comp.dsize) || (comp.end>=1) || (comp.csize<=17)) return true; unsigned char *decomp=MALLOC(unsigned char,comp.dsize); if(!decomp || !DoDecompress(decomp,mem+17,comp.dsize,comp.csize-17,comp.usize)) return false; free(mem); mem=decomp; modlen=comp.dsize; return true;}#define BYTE() ((odd)?((in_ptr[0]&0x0F)|(in_ptr[1]&0xF0)):in_ptr[0])#define NIBBLE(__v) \ do { \ odd^=1; \ if(odd) __v=in_ptr[0]&0xF0; \ else { __v=(in_ptr[0]&0xF)<<4; in_ptr++; } \ } while(0)bool cOpenTVModule::DoDecompress(unsigned char *out_ptr, const unsigned char *in_ptr, int dsize, int data_size, int usize){ if(usize==0) return false; const unsigned char *data_start=in_ptr; unsigned char *out_start=out_ptr; unsigned char *out_end=out_ptr+usize; int odd=0; while(1) { unsigned char mask=BYTE(); in_ptr++; for(int cnt=8; cnt>0; mask<<=1,cnt--) { if(mask&0x80) { out_ptr[0]=BYTE(); in_ptr++; out_ptr++; } else { int off=0, len=0; unsigned char cmd=BYTE(); in_ptr++; switch(cmd>>4) { case 0x0 ... 0x6: off=((cmd&0xF)<<8)+BYTE(); in_ptr++; len=((cmd>>4)&0x7)+3; break; case 0x7: { unsigned char high=BYTE(); in_ptr++; off=((high&0x7F)<<8)+BYTE(); in_ptr++; if((cmd==0x7F) && (high&0x80)) { len=BYTE(); in_ptr++; if(len==0xFF) { len=BYTE(); in_ptr++; len=((len<<8)+BYTE()+0x121)&0xFFFF; in_ptr++; } else len+=0x22; } else { len=((cmd&0x0F)<<1)+3; if(high&0x80) len++; } break; } case 0x8 ... 0xB: if(cmd&0x20) NIBBLE(off); else off=0; off=(off<<1)|(cmd&0x1F); len=2; break; case 0xC: off=cmd&0x0F; len=3; break; case 0xD ... 0xF: NIBBLE(off); off|=cmd&0x0F; len=((cmd>>4)&0x3)+2; break; } const unsigned char *from=out_ptr-(off+1); if(from<out_start || from>=out_ptr || len>(out_end-out_ptr)) { PRINTF(L_SYS_TPSAU,"length mismatch in OpenTV decompress"); return false; } while(--len>=0) *out_ptr++=*from++; } if(out_end<=out_ptr) { if(out_end!=out_ptr) { PRINTF(L_SYS_TPSAU,"pointer mismatch in OpenTV decompress"); return false; } int len=out_start+dsize-out_ptr; if(len>0) memmove(out_ptr,data_start+(data_size-(dsize-usize)),len); return true; } } }}#undef BYTE#undef NIBBLE// -- cTpsKey ------------------------------------------------------------------cTpsKey::cTpsKey(void){ timestamp=0;}void cTpsKey::Set(const cTpsKey *k){ timestamp=k->timestamp; opmode=k->opmode; memcpy(step,k->step,sizeof(step));}void cTpsKey::Set(const unsigned char *mem){ timestamp=*((unsigned int *)mem); opmode=mem[52+3]; for(int i=0; i<3; i++) { memcpy(step[i].key,&mem[4+i*16],16); step[i].mode=mem[52+i]; }}void cTpsKey::Put(unsigned char *mem) const{ *((unsigned int *)mem)=timestamp; mem[52+3]=opmode; for(int i=0; i<3; i++) { memcpy(&mem[4+i*16],step[i].key,16); mem[52+i]=step[i].mode; }}// -- cTpsAuHook ---------------------------------------------------------------#define BUFF_SIZE 20000class cTpsAuHook : public cLogHook {private: cOpenTVModule *mod; int pmtpid, aupid;public: cTpsAuHook(void); ~cTpsAuHook(); virtual void Process(int pid, unsigned char *data); };// -- cTpsKeys -----------------------------------------------------------------cTpsKeys tpskeys;cTpsKeys::cTpsKeys(void):cLoader("TpsAu"),lastLoad(-LOADBIN_TIME),lastAu(-TPSAU_TIME){ list=new cSimpleList<cTpsKey>; first=last=0; algomem=0;}cTpsKeys::~cTpsKeys(){ delete list; free(algomem);}const cTpsKey *cTpsKeys::GetKey(time_t t){ cMutexLock lock(this); for(cTpsKey *k=list->First(); k; k=list->Next(k)) if(t<k->Timestamp()) return k; return 0;}void cTpsKeys::Check(time_t now, int cardnum){ checkMutex.Lock(); if(first==0 && last==0 && list->Count()>0) GetFirstLast(); if(now>0 && lastCheck.Elapsed()>CHECK_TIME) { Purge(now); lastCheck.Set(); } bool nokey=now+2*3600>last;/* if(lastLoad.Elapsed()>(nokey ? LOADBIN_TIME/60 : LOADBIN_TIME)) { PRINTF(L_SYS_TPSAU,"loading "TPSBIN" triggered"); LoadBin(); if(now>0) Purge(now); lastLoad.Set(); }*/ if(lastAu.Elapsed()>(nokey ? TPSAU_TIME/60 : TPSAU_TIME)) { if(ScSetup.AutoUpdate>0) { PRINTF(L_SYS_TPSAU,"TPS AU triggered"); if(!cSoftCAM::TriggerHook(cardnum,HOOK_TPSAU)) { cTpsAuHook *hook=new cTpsAuHook; cSoftCAM::AddHook(cardnum,hook); PRINTF(L_SYS_TPSAU,"TPS AU hook added"); } } lastAu.Set(); } checkMutex.Unlock();}void cTpsKeys::Purge(time_t now){ cMutexLock lock(this); PRINTF(L_SYS_TPSAU,"purging TPS keylist"); bool del=false; for(cTpsKey *k=list->First(); k;) { cTpsKey *n=list->Next(k); if(k->Timestamp()<now-3600) { list->Del(k); del=true; } k=n; } if(del) { GetFirstLast(); Modified(); cLoaders::SaveCache(); }}void cTpsKeys::Join(cSimpleList<cTpsKey> *nlist){ cMutexLock lock(this); cTpsKey *k; while((k=nlist->First())) { nlist->Del(k,false); cTpsKey *p=list->First(); do { if(!p) { list->Add(k); Modified(); break; } cTpsKey *n=list->Next(p); if(k->Timestamp()==p->Timestamp()) { p->Set(k); Modified(); delete k; break; } if(k->Timestamp()>p->Timestamp() && (!n || k->Timestamp()<n->Timestamp())) { list->Add(k,p); Modified(); break; } p=n; } while(p); } delete nlist; GetFirstLast(); cLoaders::SaveCache();}cString cTpsKeys::Time(time_t t){ char str[32]; struct tm tm_r; strftime(str,sizeof(str),"%b %e %T",localtime_r(&t,&tm_r)); return str;}void cTpsKeys::GetFirstLast(void){ if(list->Count()>0) { cTpsKey *k=list->First(); first=last=k->Timestamp(); for(; k; k=list->Next(k)) { if(k->Timestamp()<last) PRINTF(L_SYS_TPSAU,"TPS keys not in accending order!"); last=k->Timestamp(); } PRINTF(L_SYS_TPS,"%d TPS keys available (from %s to %s)",list->Count(),*Time(first),*Time(last)); } else { last=first=0; PRINTF(L_SYS_TPS,"no TPS keys available"); }}bool cTpsKeys::ProcessAu(const cOpenTVModule *mod){ PRINTF(L_SYS_TPSAU,"processing TPS AU data"); const code_header_t *codehdr=mod->CodeHdr(); const data_header_t *datahdr=mod->DataHdr(); const unsigned char *c=codehdr->code; const unsigned char *d=datahdr->data; unsigned int kd=0, cb1=0, cb2=0, cb3=0; for(unsigned int i=0; i<codehdr->size; i++) { if(c[i] == 0x81) { // PushEA DS:$xxxx unsigned int addr=(c[i+1]<<8)|c[i+2]; if(addr<(datahdr->dlen-3)) { if(d[addr+1]==0x00 && d[addr+3]==0x00 && d[addr+4]==3) kd=addr; else if(d[addr]==0x73 && d[addr+1]==0x25) { static const unsigned char scan1[] = { 0x28, 0x20, 0x20, 0xC0 }; for(int j=2; j < 0xC; j++) if(!memcmp(&d[addr+j],scan1,sizeof(scan1))) { cb1=addr; break; } } else if((d[addr]&0xF0)==0x60 && (d[addr+1]&0xF0)==0xB0) { int vajw = (int)(((~(d[addr]&0x0F))<<4)|(d[addr+1]&0x0F)); unsigned char hits=0; for(int j=2; j < 0x30; j++) { int vld = ((d[addr+j]&0x0F)<<4)|(d[addr+j+1]&0x0F); if((d[addr+j]&0xF0)==0x20 && (d[addr+j+1]&0xF0)==0x70) { int val=vajw+vld; if(val==3 || val==4 || val==5) hits++; } } if(hits==3) cb3=addr; else if(hits==2) cb2=addr; } } } } if(!kd || !cb1 || !cb2 || !cb3) { PRINTF(L_SYS_TPSAU,"couldn't locate all pointers in data section"); return false; } RegisterAlgo3(d,cb1,cb2,cb3,kd); const unsigned char *data=&d[kd]; int seclen, numkeys; seclen=data[0] | (data[1]<<8); numkeys=data[2] | (data[3]<<8); int algo=data[4]; int mkidx=data[5]&7; unsigned char *sec[7]; sec[0]=(unsigned char *)data+6; for(int i=1; i<6; i++) sec[i]=sec[i-1]+seclen; sec[6]=sec[5]+numkeys; unsigned char key[16]; cPlainKey *pk=keys.FindKey('V',0x7c00,MBC3('M','K',mkidx),16); if(!pk) { PRINTF(L_SYS_KEY,"missing V 7C00 TPSMK%d key",mkidx); return false; } pk->Get(key); if(sec[6]>=d+datahdr->dlen) { PRINTF(L_SYS_TPSAU,"section 5 exceeds buffer"); return false; } int keylen=0; for(int i=0; i<numkeys; i++) keylen+=sec[5][i]; keylen=(keylen+15)&~15; if(sec[6]+keylen>=d+datahdr->dlen) { PRINTF(L_SYS_TPSAU,"section 6 exceeds buffer"); return false; } for(int i=0; i<keylen; i+=16) TpsDecrypt(&sec[6][i],algo,key); cSimpleList<cTpsKey> *nlist=new cSimpleList<cTpsKey>; for(int i=0; i<seclen; i++) { static const unsigned char startkey[] = { 0x01,0x01 }; static const unsigned char startaes[] = { 0x09,0x10 }; static const unsigned char startse[] = { 0x0a,0x10 }; unsigned char tmp[56]; tmp[0]=sec[0][i]; tmp[1]=sec[1][i]; tmp[2]=sec[2][i]; tmp[3]=sec[3][i]; if(CheckFF(tmp,4)) continue; int keyid=sec[4][i]; int keylen=sec[5][keyid]; if(keylen<32) continue; const unsigned char *tkey=sec[6]; for(int j=0; j<keyid; j++) tkey+=sec[5][j]; unsigned char ke[128]; if(keylen!=45) { if(!Handle80008003(tkey,keylen,ke)) continue; tkey=ke; } if(memcmp(tkey,startkey,sizeof(startkey))) continue; tmp[52]=0; tmp[53]=tkey[5]; //tkey[4]; tmp[54]=1; //tkey[5]; tmp[55]=0x1c; tkey+=9; if(memcmp(tkey,startaes,sizeof(startaes))) continue; memset(&tmp[4+ 0],0,16);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -