📄 nagra2-0101.cpp
字号:
BN_free(vard8);
BN_CTX_free(t);
BN_CTX_free(t1);
}
//
// Map3b unveiled (by Jagaer)
//
void cN2Map0101::Map3b(unsigned char *data)
{
unsigned char tmpdat[24];
RotateBytes(tmpdat,data ,24); BN_bin2bn(tmpdat,24,keybig);
RotateBytes(tmpdat,data+24,16); BN_bin2bn(tmpdat,16,ukey);
BN_zero(num1);
BN_sub(keymulinv,num1,ukey);
BN_set_bit(num1,64);
BN_mod_inverse(keymulinv,keymulinv,num1,ctx);
BN_set_word(num1,2);
BN_set_word(num2,132);
BN_mod_exp(reinput,num1,num2,ukey,ctx);
for(int i = 0; i<4; i++) {
BN_copy(num1,reinput);
BN_mask_bits(num1,64);
BN_mul(num1,num1,reinput,ctx);
BN_mul(num2,num1,keymulinv,ctx);
BN_mask_bits(num2,64);
BN_mul(num2,ukey,num2,ctx);
BN_add(num1,num1,num2);
BN_rshift(num1,num1,64);
BN_rshift(num2,reinput,64);
BN_mul(num2,num2,reinput,ctx);
BN_add(num1,num2,num1);
BN_mul(num2,num1,keymulinv,ctx);
BN_mask_bits(num2,64);
BN_mul(num2,num2,ukey,ctx);
BN_add(reinput,num1,num2);
BN_rshift(reinput,reinput,64);
if(BN_cmp(reinput,ukey)==1 || BN_cmp(reinput,ushift)>=0)
BN_sub(reinput,reinput,ukey);
BN_mask_bits(reinput,128);
}
BN_zero(sum);
for(int i=0; i<3; i++) {
BN_copy(num1,keybig);
BN_mask_bits(num1,64);
BN_rshift(keybig,keybig,64);
BN_mul(num1,num1,reinput,ctx);
BN_add(sum,sum,num1);
BN_copy(num1,sum);
BN_mask_bits(num1,64);
BN_mul(num1,num1,keymulinv,ctx);
if(i==2) {
BN_lshift(num2,num1,64);
BN_add(num2,num2,num1);
}
else {
BN_mask_bits(num1,64);
BN_mul(num1,num1,ukey,ctx);
BN_add(sum,sum,num1);
BN_rshift(sum,sum,64);
if(BN_cmp(sum, ukey)==1 || BN_cmp(sum,ushift)>=0)
BN_sub(sum,sum,ukey);
BN_mask_bits(sum,128);
}
}
//Low bytes
BN_rshift(num1,num2,2);
BN_add(num1,num1,sum);
BN_rshift(num1,num1,52);
BN_mask_bits(num1,12);
memset(data, 0, 16);
int len=BN_bn2bin(num1,data);
if(len) RotateBytes(data,len);
//High bytes
BN_mask_bits(num2,64);
BN_mul(num2,num2,ukey,ctx);
BN_add(num2,num2,sum);
BN_rshift(num2,num2,64);
BN_lshift(num2,num2,12);
BN_mask_bits(num2,64);
len=BN_bn2bin(num2,data+8);
if(len) RotateBytes(data+8,len);
}
void cN2Map0101::DoMap(int f, unsigned char *data, int l)
{
dn(printf("map0101: calling function %02X\n",f))
switch(f) {
case 0x3b:
if(l>=80) {
Map3b(data);
Map3b(data+40);
}
break;
case 0x57:
Map57(data);
break;
default:
d(printf("map0101: unsupported call %02x\n",f))
break;
}
}
// -- cN2Prov0101 ----------------------------------------------------------------
class cN2Prov0101 : public cMutex, public cN2Prov, public cN2Emu {
private:
static const unsigned char primes[];
cAuxSrv aux;
cN2Map0101 map;
//
void MakePrime(BIGNUM *n, unsigned char *residues);
protected:
virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw);
virtual void Stepper(void);
int mapSize;
int lastActiveReg;
unsigned char mapRegisters[5][2048];
public:
cN2Prov0101(int Id, int Flags):cN2Prov(Id,Flags) {}
virtual int ProcessB1(unsigned char *data, int len, int pos);
};
static cN2ProvLinkReg<cN2Prov0101,0x0101,N2FLAG_MECM|N2FLAG_B1> staticPL0101;
const unsigned char cN2Prov0101::primes[] = {
0x03,0x05,0x07,0x0B,0x0D,0x11,0x13,0x17,0x1D,0x1F,0x25,0x29,0x2B,0x2F,0x35,0x3B,
0x3D,0x43,0x47,0x49,0x4F,0x53,0x59,0x61,0x65,0x67,0x6B,0x6D,0x71,0x7F,0x83,0x89,
0x8B,0x95,0x97,0x9D,0xA3,0xA7,0xAD,0xB3,0xB5,0xBF,0xC1,0xC5,0xC7,0xD3,0xDF,0xE3,
0xE5,0xE9,0xEF,0xF1,0xFB
};
void cN2Prov0101::MakePrime(BIGNUM *n, unsigned char *residues)
{
bool isPrime;
do {
BN_add_word(n,2);
isPrime=true;
for(int i=0; i<53; i++) {
residues[i]+=2;
residues[i]%=primes[i];
if(residues[i]==0) isPrime=false;
}
} while(!isPrime);
}
bool cN2Prov0101::Algo(int algo, const unsigned char *hd, unsigned char *hw)
{
if(algo==0x40) {
memcpy(hw,hd,3);
ExpandInput(hw);
hw[0x18]|=1; hw[0x40]|=1;
map.DoMap(0x3b,hw,80);
RotateBytes(hw,64);
RotateBytes(&hw[64],64);
SHA_CTX ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx,hw,128);
memset(hw,0,128);
hw[0]=ctx.h3&0xFF;
hw[1]=(ctx.h3>>8)&0xFF;
return true;
}
else if(algo==0x60) { // map 4D/4E/57
memcpy(hw,hd,5);
ExpandInput(hw);
cBN bh;
RotateBytes(hw,128);
BN_bin2bn(hw,128,bh);
/* MAP 4D */
unsigned char residues[53];
BN_set_bit(bh,0x3FF);
BN_set_bit(bh,0);
for(int i=0; i<53; i++) residues[i]=BN_mod_word(bh,primes[i]);
/* MAP 4E */
MakePrime(bh,residues);
/* Do some byte jumbling */
BN_bn2bin(bh,hw);
RotateBytes(hw,128);
BN_bin2bn(hw,128,bh);
/* MAP 4E */
MakePrime(bh,residues);
BN_bn2bin(bh,hw);
RotateBytes(hw,128);
/* MAP 57 */
map.DoMap(0x57,hw,128);
//if(!aux.Map(0x57,hw,128,128)) return false;
return true;
}
d(printf("N2Prov%04X: unknown MECM algo %02x\n",id,algo))
return false;
}
int cN2Prov0101::ProcessB1(unsigned char *data, int len, int pos)
{
cMutexLock lock(this);
unsigned short nRegister;
unsigned short addr;
if(Init(0x0101,102)) {
SetMem(0x80,data,len);
SetPc(0x80+pos);
SetSp(0x0FFF,0x0FF0);
ClearBreakpoints();
AddBreakpoint(0x0000);
AddBreakpoint(0x9569);
AddBreakpoint(0xA822);
while (!Run(1000)) {
if (GetPc()==0x9569)
{
printf("B1 Completed Normally\n");
GetMem(0x80,data,len);
HexDump(data, len);
return max((int)a,6);
}
if (GetPc()==0xA822) {
//Map Call
switch (a) {
case 0x02: // set map size
mapSize=Get(0x48)*8;
break;
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
//Import Ram at [44:45] to Map Registers A-E, E is 0x03 the rest in sequence
if (mapSize>0) {
addr=((unsigned short)Get(0x044))+Get(0x45);
nRegister = a-0x04;
if (a==0x03) nRegister=4; //Register E isn't in Sequence
if (a=0x08)
nRegister = lastActiveReg; //Last Active Register op
else
lastActiveReg = nRegister; //Set Last Active Register
GetMem(addr,mapRegisters[nRegister],mapSize,0);
}
break;
case 0x09: //Export Registers A-E with 44:45: 0x09 is E
case 0x0A:
case 0x0B:
case 0x0C:
case 0x0D:
case 0x0E:
if(mapSize>0) {
addr=((unsigned short)Get(0x044))+Get(0x45);
nRegister = a-0x0A;
if (a==0x09) nRegister=4; //Register E isn't in Sequence
if (a=0x0E)
nRegister = lastActiveReg; //Last Active Register op
else
lastActiveReg = nRegister; //Set Last Active Register
SetMem(addr,mapRegisters[nRegister],mapSize,0);
}
break;
case 0x0F: //Swap Registers A-D with 44:45
case 0x10:
case 0x11:
case 0x12:
if(mapSize>0) {
addr=((unsigned short)Get(0x044))+Get(0x45);
nRegister = a-0x0F;
unsigned char tmp[2048];
GetMem(addr,tmp,mapSize,0);
SetMem(addr,mapRegisters[nRegister],mapSize,0);
memcpy(mapRegisters[nRegister],tmp,mapSize);
lastActiveReg = nRegister; //Set Last Active Register
}
break;
case 0x13:
case 0x14:
case 0x15:
case 0x16:
nRegister = a-0x13;
lastActiveReg = nRegister; //Set Last Active Register
memset(mapRegisters[nRegister], mapSize,0);
break;
case 0x17: //copy A to B
lastActiveReg = 1; //Set Last Active Register
memcpy(mapRegisters[0], mapRegisters[1], mapSize);
break;
case 0x18: //Copy B to A
lastActiveReg = 0;
memcpy(mapRegisters[1], mapRegisters[0], mapSize);
break;
case 0x19: //Copy A to C
lastActiveReg = 2; //Set Last Active Register
memcpy(mapRegisters[0], mapRegisters[2], mapSize);
break;
case 0x1A: //Copy C to A
lastActiveReg = 0; //Set Last Active Register
memcpy(mapRegisters[2], mapRegisters[0], mapSize);
case 0x1B: //Copy C to D
lastActiveReg = 3; //Set Last Active Register
memcpy(mapRegisters[2], mapRegisters[3], mapSize);
case 0x1C: //Copy D to C
lastActiveReg = 2; //Set Last Active Register
memcpy(mapRegisters[3], mapRegisters[2], mapSize);
break;
default:
printf("Unrecognized map call %02x",a);
return -1;
}
PopCr(); PopPc();
}
else {
printf("B1 Terminated incorrectly\n\n");
return -1;
}
}
}
return -1;
}
void cN2Prov0101::Stepper(void)
{
unsigned short pc=GetPc();
if(pc>=0x93 && pc<=0xE0) { // pc in EMM data
unsigned char op=Get(pc);
if((op&0xF0)==0x00) { // current opcode BRCLR/BRSET
int fake=0; // 1=branch -1=non-branch
if(Get(pc+3)==0x81) // next opcode == RTS
fake=1; // fake branch
else {
unsigned char off=Get(pc+2);
unsigned short target=pc+3+off;
if(off&0x80) target-=0x100;
if(Get(target)==0x81) // branch target == RTS
fake=-1; // fake non-branch
}
if(fake) {
unsigned char ea=Get(pc+1);
if(ea<=0x0400) {
unsigned char val=Get(dr,ea);
int bit=1<<((op&0xF)>>1);
// set/clr bit according to fake-mode and opcode
if((fake>0 && (op&0x01)) || (fake<0 && !(op&0x01))) {
if(val&bit) dee(printf("*"))
val&=~bit;
}
else {
if(!(val&bit)) dee(printf("*"))
val|=bit;
}
Set(dr,ea,val);
}
}
}
}
}
// -- cN2Prov0901 --------------------------------------------------------------
class cN2Prov0901 : public cN2Prov0101 {
public:
cN2Prov0901(int Id, int Flags):cN2Prov0101(Id,Flags) {}
virtual int ProcessB1(unsigned char *data, int len, int pos);
};
static cN2ProvLinkReg<cN2Prov0901,0x0901,N2FLAG_MECM|N2FLAG_B1> staticPL0901;
int cN2Prov0901::ProcessB1(unsigned char *data, int len, int pos)
{
if(Init(0x0801,102)) {
return cN2Prov0101::ProcessB1(data,len,pos);
}
return -1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -