📄 tps.c
字号:
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: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 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: case 0x9: case 0xA: case 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: case 0xE: case 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); if((unsigned int)timestamp>0x7FFFFFFFUL) timestamp=0x7FFFFFFFL; 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; }}cString cTpsKey::ToString(bool hide){ unsigned char tmp[60]; Put(&tmp[4]); *((unsigned int *)tmp)=crc32_le(0,&tmp[4],sizeof(tmp)-4); char str[420]; HexStr(str,tmp,sizeof(tmp)); return str;}// -- cTpsAuHook ---------------------------------------------------------------#ifndef TESTER#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); };#endif //TESTER// -- cTpsKeys -----------------------------------------------------------------cTpsKeys tpskeys;#define AU_STREAM 0#define AU_TPSBIN 1int tpsAuMode=AU_STREAM;cTpsKeys::cTpsKeys(void):cStructListPlain<cTpsKey>("TPS keys","tps.cache",SL_READWRITE|SL_MISSINGOK|SL_WATCH|SL_NOPURGE),lastLoad(-LOADBIN_TIME),lastAu(-TPSAU_TIME){ first=last=0; algomem=0; loadlist=0;}cTpsKeys::~cTpsKeys(){ free(algomem); delete loadlist;}const cTpsKey *cTpsKeys::GetKey(time_t t){ ListLock(false); cTpsKey *k; for(k=First(); k; k=Next(k)) if(t<k->Timestamp()) break; ListUnlock(); return k;}const cTpsKey *cTpsKeys::GetV2Key(int id){ unsigned char tmp[56]; memset(tmp,0,sizeof(tmp)); cPlainKey *pk=keys.FindKey('V',id,MBC3('T','P','S'),16,0); if(pk) { pk->Get(&tmp[4+2*16]); tmp[52+2]=1; tmp[52+3]=0x1C; cTpsKey *tk=new cTpsKey; if(tk) { tk->Set(tmp); return tk; } } else PRINTF(L_SYS_KEY,"missing %.4x TPS key\n",id); return 0;}void cTpsKeys::Check(time_t now, int cardnum){ checkMutex.Lock(); if(first==0 && last==0 && Count()>0) GetFirstLast(); if(now>0 && lastCheck.Elapsed()>CHECK_TIME) { Purge(now); lastCheck.Set(); } bool nokey=now+2*3600>last; if(tpsAuMode==AU_TPSBIN && lastLoad.Elapsed()>(nokey ? LOADBIN_TIME/60 : LOADBIN_TIME)) { PRINTF(L_SYS_TPSAU,"loading "TPSBIN" triggered"); LoadBin(); if(now>0) Purge(now); lastLoad.Set(); } if(tpsAuMode==AU_STREAM && 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){ PRINTF(L_SYS_TPSAU,"purging TPS keylist"); bool del=false; ListLock(true); for(cTpsKey *k=First(); k;) { cTpsKey *n=Next(k); if(k->Timestamp()<now-3600) { Del(k); del=true; } k=n; } ListUnlock(); if(del) { GetFirstLast(); Modified(); }}void cTpsKeys::Join(cSimpleList<cTpsKey> *nlist){ ListLock(true); cTpsKey *k; while((k=nlist->First())) { nlist->Del(k,false); cTpsKey *p=First(); do { if(!p) { Add(k); Modified(); break; } cTpsKey *n=Next(p); if(k->Timestamp()==p->Timestamp()) { p->Set(k); Modified(); delete k; break; } if(k->Timestamp()>p->Timestamp() && (!n || k->Timestamp()<n->Timestamp())) { Add(k,p); Modified(); break; } p=n; } while(p); } ListUnlock(); delete nlist; GetFirstLast();}cString cTpsKeys::Time(time_t t){ char str[32]; struct tm tm_r; strftime(str,sizeof(str),"%b %e %Y %T",localtime_r(&t,&tm_r)); return str;}void cTpsKeys::GetFirstLast(void){ if(Count()>0) { ListLock(false); cTpsKey *k=First(); first=last=k->Timestamp(); for(; k; k=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)",Count(),*Time(first),*Time(last)); ListUnlock(); } 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]==0x79 && d[addr+1]==0x00 && d[addr+2]==0x79 && d[addr+3]==0x00) kd=addr;//XXX this needs proper fix sometime... else if(d[addr+1]==0x00 && d[addr+3]==0x00 && (d[addr+4]==3||d[addr+4]==2)) kd=addr;//XXX else if(d[addr]==0x73 && d[addr+1]==0x25 && d[addr+2]==0xFA) cb1=addr; else if(d[addr]==0x64 && (d[addr+1]&0xB0)==0xB0 && d[addr+2]==0x24) cb2=addr; else if((d[addr]&0x60)==0x60 && (d[addr+1]&0xB0)==0xB0 && (d[addr+2]&0x20)==0x20) cb3=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(cb1 && !cb2) cb2=addr; else if(cb1 && cb2 && !cb3) cb3=addr;*/ } } } if(!kd || !cb1 || !cb2 || !cb3) { PRINTF(L_SYS_TPSAU,"couldn't locate all pointers in data section (%d,%d,%d,%d)",kd,cb1,cb2,cb3); return false; } unsigned int end=(kd>cb1 && kd>cb2 && kd>cb3) ? kd : datahdr->dlen; unsigned int off=min(cb1,min(cb2,cb3))-2; PRINTF(L_SYS_TPSAU,"pointers in data section kd=%d cb1=%d cb2=%d cb3=%d - dlen=%d off=%d end=%d - cb1=%d cb2=%d cb3=%d",kd,cb1,cb2,cb3,datahdr->dlen,off,end,cb1-off,cb2-off,cb3-off); RegisterAlgo3(d+off,cb1-off,cb2-off,cb3-off,end-off); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -