Author Topic: Sniffing the Rigol's internal I2C bus  (Read 1825239 times)

0 Members and 3 Guests are viewing this topic.

Offline synapsis

  • Regular Contributor
  • *
  • Posts: 140
  • Country: us
    • Blackcow
Re: Sniffing the Rigol's internal I2C bus
« Reply #550 on: July 22, 2013, 08:49:33 pm »
Here's a snippit of code I used to fix the leading 0 and the reseed issue. You can probably cut/paste the changes into the linux version. Just take out the class names/Windows stuff.

Code: [Select]
void Rikey::Generate(const char* pkey, const char* sn, const char* opts, long seed, System::Windows::Forms::TextBox^ txtout)
{
unsigned char *options, *lic1_code, *lic2_code, *lic_all;
unsigned char *out,*chunk,*temp,*final, *l1_temp, *l2_temp;
unsigned char *lic1_key, *lic2_key;
char conText[255];
int  v,i=0, j = 0;
Random^ rng = gcnew Random();

private_key=(unsigned char*)strtoupper((char*)pkey);
serial=(unsigned char*)strtoupper((char*)sn);
options=(unsigned char*)strtoupper((char*)opts);

sprintf(conText, "serial:           %s\n", serial);
txtout->AppendText( gcnew System::String(conText));

sprintf(conText, "options:          %s\n", options);
txtout->AppendText( gcnew System::String(conText));

/* sign the message */
l1_temp=(unsigned char*)calloc(64,1);
l2_temp=(unsigned char*)calloc(64,1);

do
{
ecssign(serial,options,l1_temp, l2_temp, seed);

sprintf(conText, "Seed: %08x lic1: %014s lic2: %014s\n", seed, l1_temp, l2_temp);
txtout->AppendText( gcnew System::String(conText));

seed = rng->Next();
j++;
if (j > 10)
{
txtout->AppendText(gcnew System::String("Failed to find prime seed.\n"));
return;
}
} while(prime_check(l2_temp));



lic1_code=(unsigned char*)calloc(64,1);
lic2_code=(unsigned char*)calloc(64,1);

sprintf((char*)lic1_code, "%014s", l1_temp);
sprintf((char*)lic2_code, "%014s", l2_temp);

/*sprintf(conText, "lic1-code:        %s\n", lic1_code);
txtout->AppendText( gcnew System::String(conText));

sprintf(conText, "lic2-code:        %s\n", lic2_code);
txtout->AppendText( gcnew System::String(conText));*/

lic_all=(unsigned char*)calloc(128,1);
temp=(unsigned char*)calloc(128,1);
chunk=(unsigned char*)calloc(6,1);
final=(unsigned char*)calloc(128,1);
lic1_key=(unsigned char*)calloc(20,1);
lic2_key=(unsigned char*)calloc(20,1);
strcpy((char*)lic_all, (const char*)lic1_code);
strcat((char*)lic_all, "0");
strcat((char*)lic_all, (const char*)lic2_code);
sprintf(conText, "target-code:      %s\n", lic_all);
txtout->AppendText( gcnew System::String(conText));

// split in 5 byte groups and run bruteforce
// run or lic1_code
strcat((char*)lic1_code,"0");
while(i<strlen((const char*)lic1_code))
{
memcpy(chunk,lic1_code+i,5);
out=find_match5(chunk);
if (out)
{
strcat((char*)temp, (const char*)out);
}
i=i+5;
}
strcpy((char *)lic1_key, (const char*)temp);

// run for lic2_code
strcpy((char *)temp,"");
i=0;
while(i<strlen((const char*)lic2_code))
{
memcpy(chunk,lic2_code+i,5);
if (strlen((const char*)chunk)<5)
{
for(v=0;v<5-strlen((const char*)chunk);v++)
strcat((char*)chunk,"0");
}
out=find_match5(chunk);
if (out)
{
strcat((char*)temp, (const char*)out);
}
i=i+5;
}
strcpy((char*)lic2_key, (const char*)temp);
strcpy((char*)temp, (const char*)lic1_key);
strcat((char*)temp, (const char*)lic2_key);
// now add the options
memcpy(final, temp, 1);
final[1]=options[0];
memcpy(final+2, temp+1,7);
final[9]=options[1];
memcpy(final+10, temp+8,7);
final[17]=options[2];
memcpy(final+18, temp+15,7);
final[25]=options[3];
memcpy(final+26, temp+22,4);

txtout->AppendText( gcnew System::String("----------------------------------------------------\n"));


txtout->AppendText( gcnew System::String("your-license-key: "));

for(i=0;i<strlen((const char*)final);i++)
{
if (i%7==0 && i>0) txtout->AppendText( gcnew System::String("-"));


sprintf(conText, "%c", final[i]);
txtout->AppendText( gcnew System::String(conText));

}
txtout->AppendText( gcnew System::String("\n"));
txtout->AppendText( gcnew System::String("----------------------------------------------------\n"));

}

bool Rikey::prime_check(unsigned char* lic2)
{
int prime2_factors[] = {17, 53, 905461, 60291817};
int i;
big tmp;
big s;


tmp = mirvar(0);
s = mirvar(0);
instr(s,(char*)lic2);

for (i = 0; i < (sizeof(prime2_factors) / sizeof(prime2_factors[0])); i++) {
lgconv(prime2_factors[i], tmp);
if (divisible(s, tmp)) {
return true;
}
}

return false;
}
 

Offline zombie28

  • Regular Contributor
  • *
  • Posts: 69
Re: Sniffing the Rigol's internal I2C bus
« Reply #551 on: July 22, 2013, 08:51:19 pm »
received yet another mail from "some guy" - thanks when u read this  :-+
he pointed out a reason why some lic codes are failing, and that guy knows what he is talking about ;-)
see below:

Quote
As prime2 is no prime-number (its prime-factors are [17, 53, 905461,
60291817]) it is possible that the generated s (lic2) is divisible
by one of these factors which will lead to an invalid license key.

This can be detected in ecssign with something like:

Code: [Select]
int prime2_factors[] = {17, 53, 905461, 60291817};
int i;
big tmp;

tmp = mirvar(0);
for (i = 0; i < (sizeof(prime2_factors) / sizeof(prime2_factors[0])); i++) {
lgconv(prime2_factors[i], tmp);
if (divisible(s, tmp)) {
//increment seed and redo signing
...
}
}

This check is not sufficient. Additionaly you have to ensure, that random value of k is not divisible by above factors of 'prime2' (BTW this will also ensure, that k is not equal to 0, which is required by ECDSA algorithm) and that neither r, nor s are equal to 0 (again - ECDSA requirement). If any of these checks fails, then you need to redo signing with a new value of k (note that in keygen this value doesn't need to be random at all - you can start with k=1 and increment it by 1 if necessary).

 

Offline Orange

  • Frequent Contributor
  • **
  • Posts: 346
  • Country: nl
Re: Sniffing the Rigol's internal I2C bus
« Reply #552 on: July 22, 2013, 08:53:53 pm »

DONT USE BELOW, as activates 2102 and also 2202:

2   on   on   ==   ==   ==
3   on   on   ==   ==   on
4   on   on   ==   on   ==
5   on   on   ==   on   on
6   on   on   on   ==   ==
7   on   on   on   ==   on
8   on   on   on   on   ==
9   on   on   on   on   on


Great work! I used DSA9 as cybernet recommended and it works fine.

Why do you still recommend not to use DSA9?

As you can see from your paste, It installs 100M and 200M options, which isn't necessary. 200M supersedes 100M anyway. It likely won't bring any troubles but there's no need for it. DSAZ is equivalent.

OK, so having the DSA9 already installed (license key generated with original rikey.c ) - everything Official Version - I sent an UNINSTALL and my scope got back to a normal 2072. I had the serial intact all the time. I had the latest FW installed before initially starting installing licenses.

Then on a 32 bit linux box I created a DSAZ license key with rikey.c - my serial is DS2A...2 and is 13 chars long. I sent it to the scope: verification failed
Then I used the "no_brute_force" version of rikey.c - this created a different license key for DSAZ with the same serial but sending it to the scope yielded: verification failed again

Both lic1 and lic2 keys have always been 14 chars long.

So I stopped here.
Any ideas/explanations/suggestions?

OK, so I used cybernet's verification routine on all keys generated. And yes, the result is the same. The DSA9 key generated is VALID, while DSAZ key generated is INVALID against my serial.

Edit:
I changed the seed and now it works. Thanks again.

Sorry for talking to myself in the open :)

So ?

DSA9 rules !

The quote "dont use below" (DSA9) is misleading ; to many instances with problems using DSAZ
 

Offline Carrington

  • Super Contributor
  • ***
  • Posts: 1202
  • Country: es
Re: Sniffing the Rigol's internal I2C bus
« Reply #553 on: July 22, 2013, 09:05:11 pm »
So ?

DSA9 rules !

The quote "dont use below" (DSA9) is misleading ; to many instances with problems using DSAZ

Then I remove it?  :-//

Better I change it by: "Not recommended ,as activates 2102 and also 2202:"
« Last Edit: July 22, 2013, 09:42:27 pm by Carrington »
My English can be pretty bad, so suggestions are welcome. ;)
Space Weather.
Lightning & Thunderstorms in Real Time.
 

Offline Orange

  • Frequent Contributor
  • **
  • Posts: 346
  • Country: nl
Re: Sniffing the Rigol's internal I2C bus
« Reply #554 on: July 22, 2013, 09:06:04 pm »
 

Offline alank2

  • Super Contributor
  • ***
  • Posts: 2183
Re: Sniffing the Rigol's internal I2C bus
« Reply #555 on: July 22, 2013, 09:13:25 pm »
DSAZ is perfect - if you can't generate one try a different seed value until you can.  You don't want to use DSA9.
 

Offline Carrington

  • Super Contributor
  • ***
  • Posts: 1202
  • Country: es
Re: Sniffing the Rigol's internal I2C bus
« Reply #556 on: July 22, 2013, 09:16:34 pm »
DSAZ is perfect - if you can't generate one try a different seed value until you can.  You don't want to use DSA9.

That's what I was thinking.  :-+

Thanks for the windows APP synapsis.  ^-^
My English can be pretty bad, so suggestions are welcome. ;)
Space Weather.
Lightning & Thunderstorms in Real Time.
 

Offline doma

  • Contributor
  • Posts: 11
  • Country: 00
Re: Sniffing the Rigol's internal I2C bus
« Reply #557 on: July 22, 2013, 09:29:12 pm »
Here's the generator code amended with "some guy"'s recommendation. Now it generates a VALID code for me w/o manually fiddling around with the seed.

Code: [Select]
/*
** rigol ds2000 keygen / cybernet & the-eevblog-users
**
** to compile this you need MIRACL from [url]https://github.com/CertiVox/MIRACL[/url]
** download the master.zip into a new folder and run 'unzip -j -aa -L master.zip'
** then run 'bash linux' to build the miracle.a library
**
** BUILD WITH:
**
** gcc rikey.c -I../MIRACL ../MIRACL/miracl.a -o rikey
**
** adapt -I and path to miracl.a to your environment
**
** more info: https://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/
**
** then fetch private key from EEV Blog and put into "private_key[]=" below, do not prefix with 0x
** supply your serial and wanted options, and enjoy !
**
**
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "miracl.h"

#define RIGOL_DS2000

// START OF SETTINGS FOR ECC
#ifdef RIGOL_DS2000
 unsigned char private_key[]="8...";   // <- RILOL FILL ME (no 0x prefix !)
 unsigned char prime1[]="AEBF94CEE3E707";
 unsigned char prime2[]="AEBF94D5C6AA71";
 unsigned char curve_a[]="2982";
 unsigned char curve_b[]="3408";
 unsigned char point1[]="7A3E808599A525";
 unsigned char point2[]="28BE7FAFD2A052";
#endif
// END OF SETTINGS FOR ECC

unsigned char codemap_ee00d0[]={ 0x0, 0x0, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
                                 0x0, 0x0, 0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1,  0x2,
                                 0x3, 0x4, 0x5,  0x6,  0x7,  0x0,  0x8,  0x9,  0xa,  0xb,
                                 0xc, 0x0, 0xd,  0xe,  0xf,  0x10, 0x11, 0x12, 0x13, 0x14,
                                 0x15,0x16, 0x17 };

unsigned char codemap_20688e[]={ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,  /* 0-9 = 0x30 */
                                 0x37, 0x37, 0x37, 0x37, 0x37, 0x37 };                        /* A-F = 0x37 */


unsigned char vb[]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9'};

void show_help(void)
{
 printf("./rikey <DSA2XXXXXXXXX> <OPTS>\n\n");
 printf("<DSA2XXXXXXXXX> -  serial number of device\n");
 printf("<OPTS> - \n");
 printf("\t\tDSA? for permanent options\n");
 printf("\t\tVSA? for temporary options\n");
 printf("\n\n");
}
/*
** take serial and options make sha1 hash out of it
*/
static void hashing(unsigned char *opt_str,big hash)
{ /* compute hash function */
    char *p;
    char h[20];
    int ch;
    sha sh;
    shs_init(&sh);
    p=opt_str;
    while(*p)
    {
       shs_process(&sh,*p);
       p++;
    }
    shs_hash(&sh,h);
    bytes_to_big(20,h,hash);
}
/*
** sign the secret message (serial + opts) with the private key
*/
int ecssign(unsigned char *serial, unsigned char *opt, unsigned char *lic1, unsigned char *lic2)
{
    FILE *fp;
    char ifname[50],ofname[50];
    big a,b,p,q,x,y,d,r,s,k,hash,temps;
    epoint *g;
    long seed;
    int bits;
    miracl *mip;
    unsigned char *serial_options;
/* Support variables for checking against divisibility */
    int prime2_factors[] = {17, 53, 905461, 60291817};
    int i;
    int passed;
    big tmp;

    /* randomise */
    seed=1;
    srand(seed);

   do {
passed = 1;
    /* get public data */
mip=mirsys(0x320, 0x10);   /* Use Hex internally */
mip->IOBASE=16;
a=mirvar(0);
b=mirvar(0);
p=mirvar(0);
q=mirvar(0);
x=mirvar(0);
y=mirvar(0);
d=mirvar(0);
r=mirvar(0);
s=mirvar(0);
k=mirvar(0);
hash=mirvar(0);

instr(p,prime1);     /* modulus        */
instr(a,curve_a);     /* curve parameters */
instr(b,curve_b);
instr(q,prime2);     /* order of (x,y) */
instr(x,point1);     /* (x,y) point on curve of order q */
instr(y,point2);


ecurve_init(a,b,p,MR_PROJECTIVE);  /* initialise curve */
g=epoint_init();

if (!epoint_set(x,y,0,g)) /* initialise point of order q */
{
    printf("1. Problem - point (x,y) is not on the curve\n");
    exit(0);
}

    /* calculate r - this can be done offline,
      and hence amortized to almost nothing   */
bigrand(q,k);
ecurve_mult(k,g,g);      /* see ebrick.c for method to speed this up */
epoint_get(g,r,r);
divide(r,q,q);

    /* get private key of signer */
instr(d, private_key);

    /* calculate message digest */
serial_options=calloc(128,1);
strcpy(serial_options, serial);
strcat(serial_options, opt);
hashing(serial_options,hash);

    /* calculate s */
xgcd(k,q,k,k,k);
mad(d,r,hash,q,q,s);
mad(s,k,k,q,q,s);

    /* check if we got a valid lic2 (s) */
tmp = mirvar(0);
for (i = 0; i < (sizeof(prime2_factors) / sizeof(prime2_factors[0])); i++) {
    lgconv(prime2_factors[i], tmp);
    if (divisible(s, tmp)) {
    passed = 0;
    srand(++seed);
            break;
    }
}
   } while (!passed);

    cotstr(r,lic1);
    cotstr(s,lic2);

    return 0;
}


/*
** convert string to uppercase chars
*/
unsigned char *strtoupper(unsigned char *str)
{
    unsigned char *newstr, *p;
    p = newstr = (unsigned char*) strdup((char*)str);
    while((*p++=toupper(*p)));
    return newstr;
}

/*
**
*/
unsigned char code_map_206846(unsigned char i)
{
 if ((i >= 'A') && (i <= 'F')) return(i-0x37);
 if ((i >= '0') && (i <= '9')) return(i-0x30);
 return(0x0);
}

/*
** Encryption Routine 1
*/
unsigned char *lic_code_map(unsigned char *lic_skipped)
{
 unsigned char lv1,lv2;
 unsigned char b1_mapped, b1_shifted, b1_remapped;
 unsigned char b2_mapped, b2_shifted, b2_remapped;
 unsigned char b3_mapped, b3_shifted, b3_remapped;
 unsigned char b4_mapped, b4_shifted, b4_remapped;
 unsigned char b5_shifted, b5_remapped;
 unsigned char *lic_mapbytes;

 lic_mapbytes=calloc(28, 1);
 if (!lic_mapbytes) return(0);
lv1=lv2=0;
 while(lv1 < strlen((unsigned char*)lic_skipped))
 {
    b1_mapped =  codemap_ee00d0[ *(lic_skipped+lv1) - 0x30 ];
    b1_shifted = (b1_mapped / 2) & 0xf;
    b1_remapped = b1_shifted + codemap_20688e[b1_shifted];
    lic_mapbytes[lv2++]=b1_remapped;
    b1_mapped = b1_mapped & 0x1;

    b2_mapped =  codemap_ee00d0[ *(lic_skipped+lv1+1) - 0x30 ];
    b2_shifted =  ((b1_mapped << 0x3) | (b2_mapped / 4)) & 0xF;
    b2_remapped = b2_shifted + codemap_20688e[b2_shifted];
    lic_mapbytes[lv2++]=b2_remapped;

    b3_mapped = codemap_ee00d0[ *(lic_skipped+lv1+2) - 0x30 ];
    b3_shifted = ((b3_mapped / 8) | ( (b2_mapped & 0x3) << 2 )) & 0xF;
    b3_remapped = b3_shifted + codemap_20688e[b3_shifted];
    lic_mapbytes[lv2++]=b3_remapped;

    b4_mapped = codemap_ee00d0[ *(lic_skipped+lv1+3) - 0x30 ];
    b4_shifted = ((b4_mapped / 16 ) |((b3_mapped & 0x7) << 0x1)) & 0xf;
    b4_remapped = b4_shifted + codemap_20688e[b4_shifted];
    lic_mapbytes[lv2++]=b4_remapped;

    b5_shifted = b4_mapped & 0xF;
    b5_remapped = b5_shifted + codemap_20688e[b5_shifted];
    lic_mapbytes[lv2++]=b5_remapped;

    lv1 = lv1 + 4;
  }
  return(lic_mapbytes);
}

unsigned char * find_match5(unsigned char *code5)
{
  unsigned char c1,c2,c3,c4;
  unsigned char *input;
  unsigned char *lic_mapbytes;
  input=calloc(40,1);

  /* lets bruteforce it ;-) */
  for (c1=0;c1<sizeof(vb);c1++) {
   for (c2=0;c2<sizeof(vb);c2++) {
    for (c3=0;c3<sizeof(vb);c3++) {
     for (c4=0;c4<sizeof(vb);c4++) {
      input[0]=vb[c1];
      input[1]=vb[c2];
      input[2]=vb[c3];
      input[3]=vb[c4];
      input[4]='\0';
      lic_mapbytes=lic_code_map(input);
      if (!strcmp(lic_mapbytes, code5))
      {
           return(input);
      }
     }
    }
   }
  }
  return(0); // no match
}

int main(int argc, char *argv[0])
{
 unsigned char *options,*lic1_code, *lic2_code, *lic_all;
 unsigned char *out,*chunk,*temp,*final;
 unsigned char *lic1_key, *lic2_key;
 unsigned char *serial;
 int            v,i=0;

 if (strlen(private_key)<14)
 {
  printf("\n\n");
  printf("set the private_key variable on top of this file\n");
  printf("you can find it here: https://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/msg264690/#msg264690\n");
  printf("\n\n");
  exit(-1);
 }

 if (argc != 3)
 {
  show_help();
  exit(-1);
 }
 serial=strtoupper((unsigned char*)argv[1]);
 options=strtoupper((unsigned char*)argv[2]);
 if (strlen(serial)<13)
 {
   printf("\nINVALID SERIAL LENGTH\n");
   show_help();
   exit(-1);
 }
 if (strlen(options)!=4)
 {
   printf("\nINVALID OPTIONS LENGTH\n");
   show_help();
   exit(-1);
 }
printf("serial:           %s\n", serial);
 printf("options:          %s\n", options);
 /* sign the message */
 lic1_code=calloc(64,1);
 lic2_code=calloc(64,1);
 ecssign(serial,options,lic1_code, lic2_code);
 printf("lic1-code:        %s\n", lic1_code);
 printf("lic2-code:        %s\n", lic2_code);

 lic_all=calloc(128,1);
 temp=calloc(128,1);
 chunk=calloc(6,1);
 final=calloc(128,1);
 lic1_key=calloc(20,1);
 lic2_key=calloc(20,1);
 strcpy(lic_all, lic1_code);
 strcat(lic_all, "0");
 strcat(lic_all, lic2_code);
 printf("target-code:      %s\n", lic_all);

 // split in 5 byte groups and run bruteforce
 // run or lic1_code
 strcat(lic1_code,"0");
 while(i<=strlen(lic1_code))
 {
   memcpy(chunk,lic1_code+i,5);
   out=find_match5(chunk);
   if (out)
   {
    strcat(temp, out);
   }
   i=i+5;
 }
 strcpy(lic1_key, temp);

 // run for lic2_code
 strcpy(temp,"");
 i=0;
 while(i<strlen(lic2_code))
 {
   memcpy(chunk,lic2_code+i,5);
   if (strlen(chunk)<5)
   {
    for(v=0;v<5-strlen(chunk);v++)
     strcat(chunk,"0");
   }
   out=find_match5(chunk);
   if (out)
   {
    strcat(temp, out);
   }
   i=i+5;
 }
strcpy(lic2_key, temp);
 strcpy(temp, lic1_key);
 strcat(temp, lic2_key);
 // now add the options
 memcpy(final, temp, 1);
 final[1]=options[0];
 memcpy(final+2, temp+1,7);
 final[9]=options[1];
 memcpy(final+10, temp+8,7);
 final[17]=options[2];
 memcpy(final+18, temp+15,7);
 final[25]=options[3];
 memcpy(final+26, temp+22,4);
 printf("----------------------------------------------------\n");
 printf("your-license-key: ");
 for(i=0;i<strlen(final);i++)
 {
  if (i%7==0 && i>0) printf("-");
  printf("%c", final[i]);
 }
 printf("\n");
 printf("----------------------------------------------------\n");
}

So you can spare the seed field on the GUI...
« Last Edit: July 22, 2013, 09:42:16 pm by doma »
 

Offline Orange

  • Frequent Contributor
  • **
  • Posts: 346
  • Country: nl
Re: Sniffing the Rigol's internal I2C bus
« Reply #558 on: July 22, 2013, 09:43:06 pm »
DSAZ is perfect - if you can't generate one try a different seed value until you can.  You don't want to use DSA9.
Apparently you have not read to all the posts where the DSAZ is giving problems, but no problem, the tools we have are flexible :)
 

studio25

  • Guest
Re: Sniffing the Rigol's internal I2C bus
« Reply #559 on: July 22, 2013, 09:44:19 pm »
Here is my current state. There are a few checks and simplifications. For me it works perfectly. Still missing something?

Code: [Select]

/*
** rigol ds2000 keygen / cybernet & the-eevblog-users
 **
 ** to compile this you need MIRACL from [url]https://github.com/CertiVox/MIRACL[/url]
 ** download the master.zip into a new folder and run 'unzip -j -aa -L master.zip'
 ** then run 'bash linux' to build the miracle.a library
 **
 ** BUILD WITH:
 **
 ** gcc rikey.c -I../MIRACL ../MIRACL/miracl.a -o rikey
 **
 ** adapt -I and path to miracl.a to your environment
 **
 ** more info: https://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/
 **
 ** then fetch private key from EEV Blog and put into "private_key[]=" below, do not prefix with 0x
 ** supply your serial and wanted options, and enjoy !
 **
 **
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "miracl.h"

#define RIGOL_DS2000

// START OF SETTINGS FOR ECC
#ifdef RIGOL_DS2000
unsigned char private_key[]="8EEBD4D04C3771";   // <- RILOL FILL ME (no 0x prefix !)
unsigned char prime1[]="AEBF94CEE3E707";
unsigned char prime2[]="AEBF94D5C6AA71";
unsigned char curve_a[]="2982";
unsigned char curve_b[]="3408";
unsigned char point1[]="7A3E808599A525";
unsigned char point2[]="28BE7FAFD2A052";
#endif
// END OF SETTINGS FOR ECC

void show_help(void)
{
  printf("./rikey <DSA2XXXXXXXXX> <OPTS>\n\n");
  printf("<DSA2XXXXXXXXX> -  serial number of device\n");
  printf("<OPTS> - \n");
  printf("\t\tDSA? for permanent options\n");
  printf("\t\tVSA? for temporary options\n");
  printf("\n\n");
}
/*
** take serial and options make sha1 hash out of it
 */
static void hashing(unsigned char *opt_str,big hash)
{ /* compute hash function */
  char *p;
  char h[20];
  int ch;
  sha sh;
  shs_init(&sh);
  p=opt_str;
  while(*p)
  {
    shs_process(&sh,*p);
    p++;
  }
  shs_hash(&sh,h);
  bytes_to_big(20,h,hash);
}

/*
** sign the secret message (serial + opts) with the private key
 */
int ecssign(unsigned char *serial, unsigned char *opt, unsigned char *lic1, unsigned char *lic2)
{
  big a,b,p,q,x,y,d,r,s,k,hash,tmp;
  epoint *g;
  int bits,i,fail;
  miracl *mip;
  unsigned char *serial_options;
  long seed=1;
  int prime2_factors[] = {17, 53, 905461, 60291817    };

  do {
    fail=0;

    /* get public data */
    mip=mirsys(0x320, 0x10);   /* Use Hex internally */
    mip->IOBASE=16;
    a=mirvar(0);
    b=mirvar(0);
    p=mirvar(0);
    q=mirvar(0);
    x=mirvar(0);
    y=mirvar(0);
    d=mirvar(0);
    r=mirvar(0);
    s=mirvar(0);
    k=mirvar(0);
    hash=mirvar(0);

    instr(p,prime1);     /* modulus        */
    instr(a,curve_a);     /* curve parameters */
    instr(b,curve_b);
    instr(q,prime2);     /* order of (x,y) */
    instr(x,point1);     /* (x,y) point on curve of order q */
    instr(y,point2);

    /* randomise */
    irand(seed);

    ecurve_init(a,b,p,MR_PROJECTIVE);  /* initialise curve */
    g=epoint_init();

    if (!epoint_set(x,y,0,g)) /* initialise point of order q */
    {
      printf("1. Problem - point (x,y) is not on the curve\n");
      exit(0);
    }

    /* calculate r - this can be done offline,
     and hence amortized to almost nothing   */
    bigrand(q,k);
    ecurve_mult(k,g,g);      /* see ebrick.c for method to speed this up */
    epoint_get(g,r,r);
    divide(r,q,q);

    /* get private key of signer */
    instr(d, private_key);

    /* calculate message digest */
    serial_options=calloc(128,1);
    strcpy(serial_options, serial);
    strcat(serial_options, opt);
    hashing(serial_options,hash);

    /* calculate s */
    xgcd(k,q,k,k,k);
    mad(d,r,hash,q,q,s);
    mad(s,k,k,q,q,s);

    /* some checks */
    tmp = mirvar(0);
    for (i=0; i < (sizeof(prime2_factors) / sizeof(prime2_factors[0])); i++) {
      lgconv(prime2_factors[i], tmp);
      if (divisible(s, tmp)) fail=1;
      if (divisible(k, tmp)) fail=1;
    }
    if (r==0) fail=1;
    if (s==0) fail=1;
    if (fail) seed++;
  }
  while (fail);

  cotstr(r,lic1);
  cotstr(s,lic2);
  return 0;
}

/*
** convert string to uppercase chars
 */
unsigned char *strtoupper(unsigned char *str)
{
  unsigned char *newstr, *p;
  p = newstr = (unsigned char*) strdup((char*)str);
  while((*p++=toupper(*p)));
  return newstr;
}

void find_match5(unsigned char *io)
{
  unsigned char vb[]={'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','2','3','4','5','6','7','8','9'};
  unsigned long long b=0;
  int i=0;

  // hex2dez
  while (io[i] != '\0') {
    if (io[i]>='0' && io[i]<='9')
      b=b*16+io[i]-'0';
    else if (io[i]>='A' && io[i]<='F')
      b=b*16+io[i]-'A'+10;
    else if (io[i]>='a' && io[i]<='f')
      b=b*16+io[i]-'a'+10;
    i++;
  }   

  for (i=3;;i--) {
    io[i]=vb[b & 0x1F];
    if (i==0) break;
    b>>=5;
  }
  io[4]='\0';
}

char *strrev(char *str)
{
  char *p1, *p2;

  if (! str || ! *str)
    return str;
  for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
  {
    *p1 ^= *p2;
    *p2 ^= *p1;
    *p1 ^= *p2;
  }
  return str;
}

int main(int argc, char *argv[0])
{
  unsigned char *options,*lic1_code, *lic2_code, *lic_all;
  unsigned char *chunk,*temp,*final;
  unsigned char *lic1_key, *lic2_key;
  unsigned char *serial;
  int            v,i=0;

  if (strlen(private_key)<14)
  {
    printf("\n\n");
    printf("set the private_key variable on top of this file\n");
    printf("you can find it here: https://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/msg264690/#msg264690\n");
    printf("\n\n");
    exit(-1);
  }

  if (argc != 3)
  {
    show_help();
    exit(-1);
  }
  serial=strtoupper((unsigned char*)argv[1]);
  options=strtoupper((unsigned char*)argv[2]);
  if (strlen(serial)<13)
  {
    printf("\nINVALID SERIAL LENGTH\n");
    show_help();
    exit(-1);
  }
  if (strlen(options)!=4)
  {
    printf("\nINVALID OPTIONS LENGTH\n");
    show_help();
    exit(-1);
  }
  printf("serial:           %s\n", serial);
  printf("options:          %s\n", options);

  /* sign the message */
  lic1_code=calloc(64,1);
  lic2_code=calloc(64,1);
  ecssign(serial,options,lic1_code, lic2_code);

  if (strlen(lic2_code)<14)
  {
    strrev(lic2_code);
    while (strlen(lic2_code)<14) strcat(lic2_code, "0");
    strrev(lic2_code);
  }

  if (strlen(lic1_code)<14)
  {
    strrev(lic1_code);
    while (strlen(lic1_code)<14) strcat(lic1_code, "0");
    strrev(lic1_code);
  }

  printf("lic1-code:        %s\n", lic1_code);
  printf("lic2-code:        %s\n", lic2_code);

  lic_all=calloc(128,1);
  temp=calloc(128,1);
  chunk=calloc(6,1);
  final=calloc(128,1);
  lic1_key=calloc(20,1);
  lic2_key=calloc(20,1);
  strcpy(lic_all, lic1_code);
  strcat(lic_all, "0");
  strcat(lic_all, lic2_code);
  printf("target-code:      %s\n", lic_all);

  // split in 5 byte groups
  i=0;
  while(i<strlen(lic_all))
  {
    memcpy(chunk,lic_all+i,5);
    if (strlen(chunk)<5)
    {
      for(v=0;v<5-strlen(chunk);v++)
        strcat(chunk,"0");
    } 
    find_match5(chunk);
    strcat(temp, chunk);
    i=i+5;
  }

  // now add the options
  memcpy(final, temp, 1);
  final[1]=options[0];
  memcpy(final+2, temp+1,7);
  final[9]=options[1];
  memcpy(final+10, temp+8,7);
  final[17]=options[2];
  memcpy(final+18, temp+15,7);
  final[25]=options[3];
  memcpy(final+26, temp+22,4);
  printf("----------------------------------------------------\n");
  printf("your-license-key: ");
  for(i=0;i<strlen(final);i++)
  {
    if (i%7==0 && i>0) printf("-");
    printf("%c", final[i]);
  }
  printf("\n");
  printf("----------------------------------------------------\n");
}

 

Offline doma

  • Contributor
  • Posts: 11
  • Country: 00
Re: Sniffing the Rigol's internal I2C bus
« Reply #560 on: July 22, 2013, 09:50:45 pm »
Here is my current state. There are a few checks and simplifications. For me it works perfectly. Still missing something?

Code: [Select]

/*
** rigol ds2000 keygen / cybernet & the-eevblog-users
 **
 ** to compile this you need MIRACL from [url]https://github.com/CertiVox/MIRACL[/url]
 ** download the master.zip into a new folder and run 'unzip -j -aa -L master.zip'
 ** then run 'bash linux' to build the miracle.a library
 **
 ** BUILD WITH:
 **
 ** gcc rikey.c -I../MIRACL ../MIRACL/miracl.a -o rikey
 **
 ** adapt -I and path to miracl.a to your environment
 **
 ** more info: https://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/
 **
 ** then fetch private key from EEV Blog and put into "private_key[]=" below, do not prefix with 0x
 ** supply your serial and wanted options, and enjoy !
 **
 **
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "miracl.h"

#define RIGOL_DS2000

// START OF SETTINGS FOR ECC
#ifdef RIGOL_DS2000
unsigned char private_key[]="8...";   // <- RILOL FILL ME (no 0x prefix !)
unsigned char prime1[]="AEBF94CEE3E707";
unsigned char prime2[]="AEBF94D5C6AA71";
unsigned char curve_a[]="2982";
unsigned char curve_b[]="3408";
unsigned char point1[]="7A3E808599A525";
unsigned char point2[]="28BE7FAFD2A052";
#endif
// END OF SETTINGS FOR ECC

void show_help(void)
{
  printf("./rikey <DSA2XXXXXXXXX> <OPTS>\n\n");
  printf("<DSA2XXXXXXXXX> -  serial number of device\n");
  printf("<OPTS> - \n");
  printf("\t\tDSA? for permanent options\n");
  printf("\t\tVSA? for temporary options\n");
  printf("\n\n");
}
/*
** take serial and options make sha1 hash out of it
 */
static void hashing(unsigned char *opt_str,big hash)
{ /* compute hash function */
  char *p;
  char h[20];
  int ch;
  sha sh;
  shs_init(&sh);
  p=opt_str;
  while(*p)
  {
    shs_process(&sh,*p);
    p++;
  }
  shs_hash(&sh,h);
  bytes_to_big(20,h,hash);
}

/*
** sign the secret message (serial + opts) with the private key
 */
int ecssign(unsigned char *serial, unsigned char *opt, unsigned char *lic1, unsigned char *lic2)
{
  big a,b,p,q,x,y,d,r,s,k,hash,tmp;
  epoint *g;
  int bits,i,fail;
  miracl *mip;
  unsigned char *serial_options;
  long seed=1;
  int prime2_factors[] = {17, 53, 905461, 60291817    };

  do {
    fail=0;

    /* get public data */
    mip=mirsys(0x320, 0x10);   /* Use Hex internally */
    mip->IOBASE=16;
    a=mirvar(0);
    b=mirvar(0);
    p=mirvar(0);
    q=mirvar(0);
    x=mirvar(0);
    y=mirvar(0);
    d=mirvar(0);
    r=mirvar(0);
    s=mirvar(0);
    k=mirvar(0);
    hash=mirvar(0);

    instr(p,prime1);     /* modulus        */
    instr(a,curve_a);     /* curve parameters */
    instr(b,curve_b);
    instr(q,prime2);     /* order of (x,y) */
    instr(x,point1);     /* (x,y) point on curve of order q */
    instr(y,point2);

    /* randomise */
    irand(seed);

    ecurve_init(a,b,p,MR_PROJECTIVE);  /* initialise curve */
    g=epoint_init();

    if (!epoint_set(x,y,0,g)) /* initialise point of order q */
    {
      printf("1. Problem - point (x,y) is not on the curve\n");
      exit(0);
    }

    /* calculate r - this can be done offline,
     and hence amortized to almost nothing   */
    bigrand(q,k);
    ecurve_mult(k,g,g);      /* see ebrick.c for method to speed this up */
    epoint_get(g,r,r);
    divide(r,q,q);

    /* get private key of signer */
    instr(d, private_key);

    /* calculate message digest */
    serial_options=calloc(128,1);
    strcpy(serial_options, serial);
    strcat(serial_options, opt);
    hashing(serial_options,hash);

    /* calculate s */
    xgcd(k,q,k,k,k);
    mad(d,r,hash,q,q,s);
    mad(s,k,k,q,q,s);

    /* some checks */
    tmp = mirvar(0);
    for (i=0; i < (sizeof(prime2_factors) / sizeof(prime2_factors[0])); i++) {
      lgconv(prime2_factors[i], tmp);
      if (divisible(s, tmp)) fail=1;
      if (divisible(k, tmp)) fail=1;
    }
    if (r==0) fail=1;
    if (s==0) fail=1;
    if (fail) seed++;
  }
  while (fail);

  cotstr(r,lic1);
  cotstr(s,lic2);
  return 0;
}

/*
** convert string to uppercase chars
 */
unsigned char *strtoupper(unsigned char *str)
{
  unsigned char *newstr, *p;
  p = newstr = (unsigned char*) strdup((char*)str);
  while((*p++=toupper(*p)));
  return newstr;
}

void find_match5(unsigned char *io)
{
  unsigned char vb[]={'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','2','3','4','5','6','7','8','9'};
  unsigned long long b=0;
  int i=0;

  // hex2dez
  while (io[i] != '\0') {
    if (io[i]>='0' && io[i]<='9')
      b=b*16+io[i]-'0';
    else if (io[i]>='A' && io[i]<='F')
      b=b*16+io[i]-'A'+10;
    else if (io[i]>='a' && io[i]<='f')
      b=b*16+io[i]-'a'+10;
    i++;
  }   

  for (i=3;;i--) {
    io[i]=vb[b & 0x1F];
    if (i==0) break;
    b>>=5;
  }
  io[4]='\0';
}

char *strrev(char *str)
{
  char *p1, *p2;

  if (! str || ! *str)
    return str;
  for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
  {
    *p1 ^= *p2;
    *p2 ^= *p1;
    *p1 ^= *p2;
  }
  return str;
}

int main(int argc, char *argv[0])
{
  unsigned char *options,*lic1_code, *lic2_code, *lic_all;
  unsigned char *chunk,*temp,*final;
  unsigned char *lic1_key, *lic2_key;
  unsigned char *serial;
  int            v,i=0;

  if (strlen(private_key)<14)
  {
    printf("\n\n");
    printf("set the private_key variable on top of this file\n");
    printf("you can find it here: https://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/msg264690/#msg264690\n");
    printf("\n\n");
    exit(-1);
  }

  if (argc != 3)
  {
    show_help();
    exit(-1);
  }
  serial=strtoupper((unsigned char*)argv[1]);
  options=strtoupper((unsigned char*)argv[2]);
  if (strlen(serial)<13)
  {
    printf("\nINVALID SERIAL LENGTH\n");
    show_help();
    exit(-1);
  }
  if (strlen(options)!=4)
  {
    printf("\nINVALID OPTIONS LENGTH\n");
    show_help();
    exit(-1);
  }
  printf("serial:           %s\n", serial);
  printf("options:          %s\n", options);

  /* sign the message */
  lic1_code=calloc(64,1);
  lic2_code=calloc(64,1);
  ecssign(serial,options,lic1_code, lic2_code);

  if (strlen(lic2_code)<14)
  {
    strrev(lic2_code);
    while (strlen(lic2_code)<14) strcat(lic2_code, "0");
    strrev(lic2_code);
  }

  if (strlen(lic1_code)<14)
  {
    strrev(lic1_code);
    while (strlen(lic1_code)<14) strcat(lic1_code, "0");
    strrev(lic1_code);
  }

  printf("lic1-code:        %s\n", lic1_code);
  printf("lic2-code:        %s\n", lic2_code);

  lic_all=calloc(128,1);
  temp=calloc(128,1);
  chunk=calloc(6,1);
  final=calloc(128,1);
  lic1_key=calloc(20,1);
  lic2_key=calloc(20,1);
  strcpy(lic_all, lic1_code);
  strcat(lic_all, "0");
  strcat(lic_all, lic2_code);
  printf("target-code:      %s\n", lic_all);

  // split in 5 byte groups
  i=0;
  while(i<strlen(lic_all))
  {
    memcpy(chunk,lic_all+i,5);
    if (strlen(chunk)<5)
    {
      for(v=0;v<5-strlen(chunk);v++)
        strcat(chunk,"0");
    } 
    find_match5(chunk);
    strcat(temp, chunk);
    i=i+5;
  }

  // now add the options
  memcpy(final, temp, 1);
  final[1]=options[0];
  memcpy(final+2, temp+1,7);
  final[9]=options[1];
  memcpy(final+10, temp+8,7);
  final[17]=options[2];
  memcpy(final+18, temp+15,7);
  final[25]=options[3];
  memcpy(final+26, temp+22,4);
  printf("----------------------------------------------------\n");
  printf("your-license-key: ");
  for(i=0;i<strlen(final);i++)
  {
    if (i%7==0 && i>0) printf("-");
    printf("%c", final[i]);
  }
  printf("\n");
  printf("----------------------------------------------------\n");
}


1.) I'd use srand instead of irand  and add srand(++seed) instead - as per the manual it should not work at all like this as irand will always use a seed of 1 if no srand is called :)
2.) You could put "break;"s in the check cycle to save some CPU
« Last Edit: July 23, 2013, 07:47:35 am by doma »
 

Offline alank2

  • Super Contributor
  • ***
  • Posts: 2183
Re: Sniffing the Rigol's internal I2C bus
« Reply #561 on: July 22, 2013, 10:22:01 pm »
Apparently you have not read to all the posts where the DSAZ is giving problems, but no problem, the tools we have are flexible :)

I think that codes that are failing because of a seed issue.  Keep trying DSAZ with new seeds until a good code is found.
 

Offline Maalobs

  • Contributor
  • Posts: 16
  • Country: se
Re: Sniffing the Rigol's internal I2C bus
« Reply #562 on: July 22, 2013, 10:52:24 pm »
Here's the generator code amended with "some guy"'s recommendation. Now it generates a VALID code for me w/o manually fiddling around with the seed.

So you can spare the seed field on the GUI...

Great work, the math problem was beyond me, but you didn't take into account preceding zeros in lic1 or lic2, which must be nullpadded to keep those variables at 14 characters long each.
I've added it to your code here:
Code: [Select]
/*
** rigol ds2000 keygen / cybernet & the-eevblog-users
**
** to compile this you need MIRACL from [url]https://github.com/CertiVox/MIRACL[/url]
** download the master.zip into a new folder and run 'unzip -j -aa -L master.zip'
** then run 'bash linux' to build the miracle.a library
**
** BUILD WITH:
**
** gcc rikey.c -I../MIRACL ../MIRACL/miracl.a -o rikey
**
** adapt -I and path to miracl.a to your environment
**
** more info: https://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/
**
** then fetch private key from EEV Blog and put into "private_key[]=" below, do not prefix with 0x
** supply your serial and wanted options, and enjoy !
**
**
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "miracl.h"

#define RIGOL_DS2000

// START OF SETTINGS FOR ECC
#ifdef RIGOL_DS2000
 unsigned char private_key[]="8...";   // <- RILOL FILL ME (no 0x prefix !)
 unsigned char prime1[]="AEBF94CEE3E707";
 unsigned char prime2[]="AEBF94D5C6AA71";
 unsigned char curve_a[]="2982";
 unsigned char curve_b[]="3408";
 unsigned char point1[]="7A3E808599A525";
 unsigned char point2[]="28BE7FAFD2A052";
#endif
// END OF SETTINGS FOR ECC

unsigned char codemap_ee00d0[]={ 0x0, 0x0, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
                                 0x0, 0x0, 0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1,  0x2,
                                 0x3, 0x4, 0x5,  0x6,  0x7,  0x0,  0x8,  0x9,  0xa,  0xb,
                                 0xc, 0x0, 0xd,  0xe,  0xf,  0x10, 0x11, 0x12, 0x13, 0x14,
                                 0x15,0x16, 0x17 };

unsigned char codemap_20688e[]={ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,  /* 0-9 = 0x30 */
                                 0x37, 0x37, 0x37, 0x37, 0x37, 0x37 };                        /* A-F = 0x37 */


unsigned char vb[]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9'};

void show_help(void)
{
 printf("./rikey <DSA2XXXXXXXXX> <OPTS>\n\n");
 printf("<DSA2XXXXXXXXX> -  serial number of device\n");
 printf("<OPTS> - \n");
 printf("\t\tDSA? for permanent options\n");
 printf("\t\tVSA? for temporary options\n");
 printf("\n\n");
}
/*
** take serial and options make sha1 hash out of it
*/
static void hashing(unsigned char *opt_str,big hash)
{ /* compute hash function */
    char *p;
    char h[20];
    int ch;
    sha sh;
    shs_init(&sh);
    p=opt_str;
    while(*p)
    {
       shs_process(&sh,*p);
       p++;
    }
    shs_hash(&sh,h);
    bytes_to_big(20,h,hash);
}
/*
** sign the secret message (serial + opts) with the private key
*/
int ecssign(unsigned char *serial, unsigned char *opt, unsigned char *lic1, unsigned char *lic2)
{
    FILE *fp;
    char ifname[50],ofname[50];
    big a,b,p,q,x,y,d,r,s,k,hash,temps;
    epoint *g;
    long seed;
    int bits;
    miracl *mip;
    unsigned char *serial_options;
/* Support variables for checking against divisibility */
    int prime2_factors[] = {17, 53, 905461, 60291817};
    int i;
    int passed;
    big tmp;

    /* randomise */
    seed=1;
    srand(seed);

    do {
passed = 1;
    /* get public data */
mip=mirsys(0x320, 0x10);   /* Use Hex internally */
mip->IOBASE=16;
a=mirvar(0);
b=mirvar(0);
p=mirvar(0);
q=mirvar(0);
x=mirvar(0);
y=mirvar(0);
d=mirvar(0);
r=mirvar(0);
s=mirvar(0);
k=mirvar(0);
hash=mirvar(0);

instr(p,prime1);     /* modulus        */
instr(a,curve_a);     /* curve parameters */
instr(b,curve_b);
instr(q,prime2);     /* order of (x,y) */
instr(x,point1);     /* (x,y) point on curve of order q */
instr(y,point2);


ecurve_init(a,b,p,MR_PROJECTIVE);  /* initialise curve */
g=epoint_init();

if (!epoint_set(x,y,0,g)) /* initialise point of order q */
{
     printf("1. Problem - point (x,y) is not on the curve\n");
     exit(0);
}

    /* calculate r - this can be done offline,
      and hence amortized to almost nothing   */
bigrand(q,k);
ecurve_mult(k,g,g);      /* see ebrick.c for method to speed this up */
epoint_get(g,r,r);
divide(r,q,q);

    /* get private key of signer */
instr(d, private_key);

    /* calculate message digest */
serial_options=calloc(128,1);
strcpy(serial_options, serial);
strcat(serial_options, opt);
hashing(serial_options,hash);

    /* calculate s */
xgcd(k,q,k,k,k);
mad(d,r,hash,q,q,s);
mad(s,k,k,q,q,s);

    /* check if we got a valid lic2 (s) */
tmp = mirvar(0);
for (i = 0; i < (sizeof(prime2_factors) / sizeof(prime2_factors[0])); i++) {
     lgconv(prime2_factors[i], tmp);
     if (divisible(s, tmp)) {
     passed = 0;
     srand(++seed);
            break;
     }
}
   } while (!passed);

    cotstr(r,lic1);
    cotstr(s,lic2);

    return 0;
}


/*
** convert string to uppercase chars
*/
unsigned char *strtoupper(unsigned char *str)
{
    unsigned char *newstr, *p;
    p = newstr = (unsigned char*) strdup((char*)str);
    while((*p++=toupper(*p)));
    return newstr;
}

/*
**
*/
unsigned char code_map_206846(unsigned char i)
{
 if ((i >= 'A') && (i <= 'F')) return(i-0x37);
 if ((i >= '0') && (i <= '9')) return(i-0x30);
 return(0x0);
}

/*
** Encryption Routine 1
*/
unsigned char *lic_code_map(unsigned char *lic_skipped)
{
 unsigned char lv1,lv2;
 unsigned char b1_mapped, b1_shifted, b1_remapped;
 unsigned char b2_mapped, b2_shifted, b2_remapped;
 unsigned char b3_mapped, b3_shifted, b3_remapped;
 unsigned char b4_mapped, b4_shifted, b4_remapped;
 unsigned char b5_shifted, b5_remapped;
 unsigned char *lic_mapbytes;

 lic_mapbytes=calloc(28, 1);
 if (!lic_mapbytes) return(0);
lv1=lv2=0;
 while(lv1 < strlen((unsigned char*)lic_skipped))
 {
    b1_mapped =  codemap_ee00d0[ *(lic_skipped+lv1) - 0x30 ];
    b1_shifted = (b1_mapped / 2) & 0xf;
    b1_remapped = b1_shifted + codemap_20688e[b1_shifted];
    lic_mapbytes[lv2++]=b1_remapped;
    b1_mapped = b1_mapped & 0x1;

    b2_mapped =  codemap_ee00d0[ *(lic_skipped+lv1+1) - 0x30 ];
    b2_shifted =  ((b1_mapped << 0x3) | (b2_mapped / 4)) & 0xF;
    b2_remapped = b2_shifted + codemap_20688e[b2_shifted];
    lic_mapbytes[lv2++]=b2_remapped;

    b3_mapped = codemap_ee00d0[ *(lic_skipped+lv1+2) - 0x30 ];
    b3_shifted = ((b3_mapped / 8) | ( (b2_mapped & 0x3) << 2 )) & 0xF;
    b3_remapped = b3_shifted + codemap_20688e[b3_shifted];
    lic_mapbytes[lv2++]=b3_remapped;

    b4_mapped = codemap_ee00d0[ *(lic_skipped+lv1+3) - 0x30 ];
    b4_shifted = ((b4_mapped / 16 ) |((b3_mapped & 0x7) << 0x1)) & 0xf;
    b4_remapped = b4_shifted + codemap_20688e[b4_shifted];
    lic_mapbytes[lv2++]=b4_remapped;

    b5_shifted = b4_mapped & 0xF;
    b5_remapped = b5_shifted + codemap_20688e[b5_shifted];
    lic_mapbytes[lv2++]=b5_remapped;

    lv1 = lv1 + 4;
  }
  return(lic_mapbytes);
}

unsigned char * find_match5(unsigned char *code5)
{
  unsigned char c1,c2,c3,c4;
  unsigned char *input;
  unsigned char *lic_mapbytes;
  input=calloc(40,1);

  /* lets bruteforce it ;-) */
  for (c1=0;c1<sizeof(vb);c1++) {
   for (c2=0;c2<sizeof(vb);c2++) {
    for (c3=0;c3<sizeof(vb);c3++) {
     for (c4=0;c4<sizeof(vb);c4++) {
      input[0]=vb[c1];
      input[1]=vb[c2];
      input[2]=vb[c3];
      input[3]=vb[c4];
      input[4]='\0';
      lic_mapbytes=lic_code_map(input);
      if (!strcmp(lic_mapbytes, code5))
      {
           return(input);
      }
     }
    }
   }
  }
  return(0); // no match
}

char *strrev(char *str)
{
      char *p1, *p2;

      if (! str || ! *str)
            return str;
      for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
      {
            *p1 ^= *p2;
            *p2 ^= *p1;
            *p1 ^= *p2;
      }
      return str;
}

int main(int argc, char *argv[0])
{
 unsigned char *options,*lic1_code, *lic2_code, *lic_all;
 unsigned char *out,*chunk,*temp,*final;
 unsigned char *lic1_key, *lic2_key;
 unsigned char *serial;
 int            v,i=0;

 if (strlen(private_key)<14)
 {
  printf("\n\n");
  printf("set the private_key variable on top of this file\n");
  printf("you can find it here: https://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/msg264690/#msg264690\n");
  printf("\n\n");
  exit(-1);
 }

 if (argc != 3)
 {
  show_help();
  exit(-1);
 }
 serial=strtoupper((unsigned char*)argv[1]);
 options=strtoupper((unsigned char*)argv[2]);
 if (strlen(serial)<13)
 {
   printf("\nINVALID SERIAL LENGTH\n");
   show_help();
   exit(-1);
 }
 if (strlen(options)!=4)
 {
   printf("\nINVALID OPTIONS LENGTH\n");
   show_help();
   exit(-1);
 }
printf("serial:           %s\n", serial);
 printf("options:          %s\n", options);
 /* sign the message */
 lic1_code=calloc(64,1);
 lic2_code=calloc(64,1);
 ecssign(serial,options,lic1_code, lic2_code);

 int diff1 = 14 - strlen(lic1_code);
 while(diff1 > 0) {
  strrev(lic1_code);
  strcat(lic1_code, "0");
  strrev(lic1_code);
  diff1--;
 }

 int diff2 = 14 - strlen(lic2_code);
 while(diff2 > 0) {
  strrev(lic2_code);
  strcat(lic2_code, "0");
  strrev(lic2_code);
  diff2--;
 }

 printf("lic1-code:        %s\n", lic1_code);
 printf("lic2-code:        %s\n", lic2_code);

 lic_all=calloc(128,1);
 temp=calloc(128,1);
 chunk=calloc(6,1);
 final=calloc(128,1);
 lic1_key=calloc(20,1);
 lic2_key=calloc(20,1);
 strcpy(lic_all, lic1_code);
 strcat(lic_all, "0");
 strcat(lic_all, lic2_code);
 printf("target-code:      %s\n", lic_all);

 // split in 5 byte groups and run bruteforce
 // run or lic1_code
 strcat(lic1_code,"0");
 while(i<=strlen(lic1_code))
 {
   memcpy(chunk,lic1_code+i,5);
   out=find_match5(chunk);
   if (out)
   {
    strcat(temp, out);
   }
   i=i+5;
 }
 strcpy(lic1_key, temp);

 // run for lic2_code
 strcpy(temp,"");
 i=0;
 while(i<strlen(lic2_code))
 {
   memcpy(chunk,lic2_code+i,5);
   if (strlen(chunk)<5)
   {
    for(v=0;v<5-strlen(chunk);v++)
     strcat(chunk,"0");
   }
   out=find_match5(chunk);
   if (out)
   {
    strcat(temp, out);
   }
   i=i+5;
 }
strcpy(lic2_key, temp);
 strcpy(temp, lic1_key);
 strcat(temp, lic2_key);
 // now add the options
 memcpy(final, temp, 1);
 final[1]=options[0];
 memcpy(final+2, temp+1,7);
 final[9]=options[1];
 memcpy(final+10, temp+8,7);
 final[17]=options[2];
 memcpy(final+18, temp+15,7);
 final[25]=options[3];
 memcpy(final+26, temp+22,4);
 printf("----------------------------------------------------\n");
 printf("your-license-key: ");
 for(i=0;i<strlen(final);i++)
 {
  if (i%7==0 && i>0) printf("-");
  printf("%c", final[i]);
 }
 printf("\n");
 printf("----------------------------------------------------\n");
}
 

Offline Maalobs

  • Contributor
  • Posts: 16
  • Country: se
Re: Sniffing the Rigol's internal I2C bus
« Reply #563 on: July 22, 2013, 11:03:05 pm »
DSAZ is perfect - if you can't generate one try a different seed value until you can.  You don't want to use DSA9.
Apparently you have not read to all the posts where the DSAZ is giving problems, but no problem, the tools we have are flexible :)
I think you are focusing on the wrong detail; Using DSA9 is what has resulted in an invalid state in the scope for some people, which in turn resulted in the serialnumbers getting mangled for them.
DSAZ just had a math problem in rikey.c that triggered on some serialnumbers (which may have been fixed now by doma and "some guy"), it had no effect at all on the scopes (as I understood it the license codes weren't even accepted by the scopes, so no effect was possible).
 

Offline true

  • Frequent Contributor
  • **
  • Posts: 329
  • Country: us
  • INTERNET
Re: Sniffing the Rigol's internal I2C bus
« Reply #564 on: July 22, 2013, 11:16:51 pm »
Too much code fragmentation  |O

Need to get the best parts all put together, maybe I will do this too when I get home
 

Offline UberSteve

  • Contributor
  • Posts: 21
  • Country: au
Re: Sniffing the Rigol's internal I2C bus
« Reply #565 on: July 23, 2013, 12:36:57 am »
Too much code fragmentation  |O

Need to get the best parts all put together, maybe I will do this too when I get home

Maybe worth sticking it on GitHub? (Or perhaps that might violate their policies?)

 

Offline bluesmoke

  • Contributor
  • Posts: 24
  • Country: us
Re: Sniffing the Rigol's internal I2C bus
« Reply #566 on: July 23, 2013, 12:39:22 am »
Quote
I think you are focusing on the wrong detail; Using DSA9 is what has resulted in an invalid state in the scope for some people, which in turn resulted in the serialnumbers getting mangled for them.

Actually it was a DSAZ code that locked up my scope on reboot and reset the serial to 1.

 

Offline UberSteve

  • Contributor
  • Posts: 21
  • Country: au
Re: Sniffing the Rigol's internal I2C bus
« Reply #567 on: July 23, 2013, 12:40:53 am »
DSAZ is perfect - if you can't generate one try a different seed value until you can.  You don't want to use DSA9.
Apparently you have not read to all the posts where the DSAZ is giving problems, but no problem, the tools we have are flexible :)
I think you are focusing on the wrong detail; Using DSA9 is what has resulted in an invalid state in the scope for some people, which in turn resulted in the serialnumbers getting mangled for them.
DSAZ just had a math problem in rikey.c that triggered on some serialnumbers (which may have been fixed now by doma and "some guy"), it had no effect at all on the scopes (as I understood it the license codes weren't even accepted by the scopes, so no effect was possible).

This is my general feeling as well. The reports of serial numbers getting hosed, etc are a little concerning. Assuming the feature table posted earlier is correct, DSAZ would seem to be more "valid" than DSA9.

I used the DSAZ code on my brand new DS2072 (came with latest fw) and it worked perfectly, serial remained, etc.
 

Offline UberSteve

  • Contributor
  • Posts: 21
  • Country: au
Re: Sniffing the Rigol's internal I2C bus
« Reply #568 on: July 23, 2013, 12:42:32 am »
Quote
I think you are focusing on the wrong detail; Using DSA9 is what has resulted in an invalid state in the scope for some people, which in turn resulted in the serialnumbers getting mangled for them.

Actually it was a DSAZ code that locked up my scope on reboot and reset the serial to 1.

Hmm, well that blows my theory out of the water. Perhaps it was the combination of using the DSAZ code and other previous codes you may(?) have used?
 

Offline alank2

  • Super Contributor
  • ***
  • Posts: 2183
Re: Sniffing the Rigol's internal I2C bus
« Reply #569 on: July 23, 2013, 12:43:13 am »
Quote
I think you are focusing on the wrong detail; Using DSA9 is what has resulted in an invalid state in the scope for some people, which in turn resulted in the serialnumbers getting mangled for them.

Actually it was a DSAZ code that locked up my scope on reboot and reset the serial to 1.

The test DSAZ code (LLLLLLL) or a generated DSAZ code?

What FW did you have at the time?
 

Offline Uup

  • Regular Contributor
  • *
  • Posts: 82
  • Country: au
Re: Sniffing the Rigol's internal I2C bus
« Reply #570 on: July 23, 2013, 12:56:30 am »
I tried the DSAZ code and the generated licence didn't work on my DS4024.

However, the temporary options key (LLLLLLL-RLGLLDS-DSH9LLL-LLLLLLL) worked. So I tried generating a key with DSH9 and it worked! I have 5 official options now  :)

Serial number is unchanged and options hold after a power cycle. I wonder if it would be possible to increase the bandwidth to 500MHz...   ;D

Thanks guys for the truly awesome work!  :-+

 

Offline BravoV

  • Super Contributor
  • ***
  • Posts: 7547
  • Country: 00
  • +++ ATH1
Re: Sniffing the Rigol's internal I2C bus
« Reply #571 on: July 23, 2013, 01:12:32 am »
Damn, so this works also at DS4xxx series, great news.  :clap:

Edit : Fyi, I keep saving the offline version of this whole thread, just in case Dave received a cease & desist love letter from Rigol's lawyer.
« Last Edit: July 23, 2013, 01:16:37 am by BravoV »
 

Offline bluesmoke

  • Contributor
  • Posts: 24
  • Country: us
Re: Sniffing the Rigol's internal I2C bus
« Reply #572 on: July 23, 2013, 01:20:30 am »
Quote
Quote from: bluesmoke on Today at 10:39:22 AM

    Quote

        I think you are focusing on the wrong detail; Using DSA9 is what has resulted in an invalid state in the scope for some people, which in turn resulted in the serialnumbers getting mangled for them.


    Actually it was a DSAZ code that locked up my scope on reboot and reset the serial to 1.

Quote
The test DSAZ code (LLLLLLL) or a generated DSAZ code?

What FW did you have at the time?

It was a code generated from my serial... firmware 00.01.00.05
 

Offline alank2

  • Super Contributor
  • ***
  • Posts: 2183
Re: Sniffing the Rigol's internal I2C bus
« Reply #573 on: July 23, 2013, 01:22:48 am »
firmware 00.01.00.05

I think the FW05 is the issue.  I don't advise anyone with FW05 to enter any codes until they upgrade.
 

Offline true

  • Frequent Contributor
  • **
  • Posts: 329
  • Country: us
  • INTERNET
Re: Sniffing the Rigol's internal I2C bus
« Reply #574 on: July 23, 2013, 03:44:23 am »
Too much code fragmentation  |O

Need to get the best parts all put together, maybe I will do this too when I get home

Maybe worth sticking it on GitHub? (Or perhaps that might violate their policies?)

Not Github, but somewhere.

Anyway here's a cleaned up version, with more verbose help - do you like it? Beautified, fixes bugs (license padding, lic2 prime check, no brute-force). Adds optional run-time requirement for the private key (if not compiled with it, it is required).

EDIT: the single downloader, minor bug! you don't need to redownload, but if you want to send it to others, send this version.
« Last Edit: July 23, 2013, 03:47:05 am by true »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf