Хак для Rigol 2000 серии
Помните известный хак, позволявший сделать из 50МГц осциллографа Rigol (DS1052) 100МГц версию (DS1102) с помощью всего пары команд?
Как оказалось, история повторилась и с новыми осциллографами Rigol 2000 и теперь можно из DS2072 (70МГц) за 800$ сделать DS2202 (200МГц) за $1600 просто введя пароль, сгенерированный кейгеном. Кроме того, кейген открывает опциональные декодеры протоколов, которые тоже стоят денег.

Хак разработали на форуме EEVBlog, декодируя передачу данных между процессором и EEPROMом.
В Rigol используется эллиптическая криптография (вид асимметричного шифрования). Ошибка Rigol заключалась в том, что они не верно выбрали параметры для криптоалгоритма, в частности, для модуля использовали не простое число. Из-за этого, ключ относительно легко подобрался. Хороший урок по криптографии вышел :)
Как оказалось, история повторилась и с новыми осциллографами Rigol 2000 и теперь можно из DS2072 (70МГц) за 800$ сделать DS2202 (200МГц) за $1600 просто введя пароль, сгенерированный кейгеном. Кроме того, кейген открывает опциональные декодеры протоколов, которые тоже стоят денег.

Хак разработали на форуме EEVBlog, декодируя передачу данных между процессором и EEPROMом.
В Rigol используется эллиптическая криптография (вид асимметричного шифрования). Ошибка Rigol заключалась в том, что они не верно выбрали параметры для криптоалгоритма, в частности, для модуля использовали не простое число. Из-за этого, ключ относительно легко подобрался. Хороший урок по криптографии вышел :)
Исходники кейгена
/*
** 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;
epoint *g;
long seed;
int bits;
miracl *mip;
unsigned char *serial_options;
/* 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 */
seed=1;
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);
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");
}
4 комментария
:(
www.scienceprog.com/did-i-just-increased-ds1022cd-bandwidth-four-times/#more-3846
инструкция по переделке DS1022CD (20 мгц) в DS1102CD (100 мгц) путем нажатия нескольких кнопок