首页
论坛
课程
招聘
[原创]010Editor破解(0xac版key注册算法分析)
2021-11-17 07:18 7766

[原创]010Editor破解(0xac版key注册算法分析)

2021-11-17 07:18
7766

 

近期多次用到了010Editor的文件模板功能,想到自己还是在虚拟机里用大佬patch的老版本,遂决定自己尝试动手分析v12.0.1最新版的注册算法()。


准备阶段

010Editor v12.0.1 portable V
ida 7.5

逆向分析

010Editor没有加壳,直接上ida。

寻找关键函数

在010Editor中以随意写的用户名和注册码注册,反馈如下:

尝试在ida中搜索Invalid name

 

居然直接就找到了,SWEETSCAPE没有走心啊。

 

Ctrl+X定位到引用该字符串的代码处,F5查看。很简单的在上边不远找到了成功注册的代码:

初步分析相关函数

这里要求v17==219,定位到对应汇编码

 

汇编代码对应了%edi0xDB比较
不妨对loc_7FF628EF5595Ctrl+X往上走,可以看到有两个相距不远的引用

 

在这里sub_7FF628D084F4的返回值对%edi做了赋值,跟进去看看
函数的汇编码不算长,不过ida当然是要上效率神器F5的

简单清晰的看到了要找的返回值219抓住主要矛盾,跟进sub_7FF628D06118,我们希望ta返回45

 

这里的函数内容相对复杂(需要动态调试逐步尝试),进入了注册码的验证环节,我贴一下主要部分

对于输入的注册码为123456789ABCDEFF的情况,sub_7FF628D06118会将字符串转化成hex使用。

1
2
3
r[0]=0x12
r[1]=0x34
#...以此类推

根据r[3]的不同,注册码分为三个版本:0x9c,0xfc,0xac

0x9c

  • Evaluation Key:
    8byte长的测试key,经测试可以使用但已不再受官方服务支持,这里不做分析(推荐大佬余生挚爱传奇的文章,对r[3]=0x9c的key做了详实的分析)。
    此版本key已到期

    0xfc

  • VersionLicense Key:
    版本key,不返回我们需要的值45,故不作分析。

    0xac

  • TimeLicense Key:
    key中包含了与有效时间关联的byte,r[4]~r[7]与用户名进行了验证。
    关键代码如下

注册算法详解

对注册算法做一点分析,基于idaF5处理后的代码,主要关注函数sub_7FF628D06118中的各类条件语句,令其返回注册成功需要的值。

  • 第一处if语句:

    对两个地址的值是否为0做判断,我们需要此次为1。
    第一处地址:

    第二处地址:

    很明显两个指针分别指向了两个结构体中字符串的长度,只要保持输入非空即可。

  • 第二处if语句:
    嵌套了一个do{}while()循环,将用户名与特点字符做比较和处理,没有影响,可以无视。

  • switch语句:
    将注册码的hex值赋值后,对r[3]进行switch分支,对应了上边0x9c,0xfc,0xac,三个注册码版本,此次r[3]为0xac

    照例只关注if语句,unsiged int v23的取值区间应在[0x1,0x3e7].为v23赋值的函数对应的python代码如下:

    1
    2
    3
    4
    5
    6
    v15=(r[5]^r[2])+((r[7]^r[1])<<8)
    v23=((v15 ^ 0x7892) + 19760) ^ 0x3421
    if(v23%0xb):
      v23=0
    else:
      v23=v23//0xb

    在后续的算法中,v23的值代表注册码的可使用次数.()

  • 跳转至LABEL_26:
    0xac版本的key还有最后两处if.

第一处:
v25的值与输入的用户名进行验证,要求满足:

v25 & 0xff == r[4]
(v25>>8) & 0xff == r[5]
(v25>>16) & 0xff == r[6]
(v25>>24) & 0xff == r[7]
注册机的编写思路就需要反着来,先基于用户名生成r[4]~r[7],再反推其他r[?]值.

 

第二处:
要求v29>=0x49c7,为v29赋值的函数对应的python代码如下:

1
2
3
4
5
6
a1=(r[6]^r[0])+((r[5]^r[9])<<16)+((r[8]^r[4])<<8)
a2=0x5b8c27
v2 = (((a2 ^ a1 ^ 0x22C078) - 180597) ^ 0xFFE53167) & 0xFFFFFF
v29=0
if(v2%0x11==0):
    v29=v2//0x11

在后续算法中,v29*86400实际上得到了一个时间戳,要求大于0x49c7意味着到期时间要在2021年9月17日之后.推测这应该是安装时写入的一个值.

 

基于上文,给出注册机关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//c语言版
//提供一个指向用户名的指针作为参数,返回注册码。
TCHAR *crack(TCHAR *str){
    int key[310]={969622712, 594890599, 1593930257, 1052452058, 890701766, 1677293387, 394424968, 266815521, 1532978959, 1211194088, 2019260265, 729421127, 953225874, 1117854514, 892543556, 2000911200, 514538256, 1400963072, 486675118, 1862498216, 1136668818, 758909582, 1653935295, 821063674, 888606944, 687085563, 890056597, 1513495898, 365692427, 184357836, 677395407, 863045227, 818746596, 391985767, 1842768403, 758385145, 1478392706, 1985112985, 1552765320, 746944881, 368385984, 1758203153, 1240817244, 660489060, 756944316, 1290697955, 844453952, 288239112, 1769473626, 1922176006, 826636519, 391520695, 1081548223, 1069693142, 1244729994, 766313326, 1101031894, 624951698, 14501479, 1794907983, 1460682958, 1660839647, 1104890686, 897721119, 1442187162, 480708164, 454443986, 1064446153, 1595150448, 1041527979, 1145775470, 1399869657, 255985995, 802693350, 2005610078, 1897360642, 2146073193, 1538606632, 431647857, 964049561, 395138253, 19164808, 856904574, 730737943, 708645054, 1506870658, 933323739, 819349658, 1780571206, 236747382, 533160167, 2042104933, 670325172, 2040165158, 1354372994, 705785180, 1669754395, 1066536508, 1426207888, 1437950089, 741941201, 796931522, 1694313338, 1290302874, 1367672048, 2039808424, 1062939821, 954597728, 1668694488, 859122242, 1369582617, 140269649, 53024683, 729221831, 816609203, 736893191, 55706320, 262747091, 1629838835, 581764799, 1488480625, 1607077349, 1879925846, 1453945819, 1521965565, 856558562, 1530662365, 1230847072, 1404918182, 1281256849, 1238970765, 272453753, 1640907491, 2127893021, 350314733, 556617458, 654390256, 1648581270, 531062411, 1862873022, 1241517385, 1471028336, 5121143, 1444839026, 1183580211, 1573659650, 2018540230, 1487873223, 234237236, 898254600, 1023090193, 728843548, 2007454357, 1451820833, 267351539, 302982385, 26807015, 865879122, 664886158, 195503981, 1625037691, 1330347906, 1742434311, 1330272217, 1645368040, 542321916, 1782121222, 411042851, 435386250, 1176704752, 1454246199, 1136813916, 1707755005, 224415730, 201138891, 989750331, 1006010278, 1147286905, 406860280, 840388503, 1282017578, 1605698145, 23396724, 862145265, 1898780916, 1855549801, 1571519230, 2083204840, 1859876276, 1602449334, 1009413590, 690816450, 86131931, 345661263, 1565025600, 857544170, 1329948960, 1211787679, 994381573, 991984748, 1956475134, 1098146294, 1655714289, 659576699, 689116467, 1485584392, 451884118, 255590636, 2108114754, 1266252396, 1589326471, 2019907768, 15552498, 1651075358, 614606175, 1656823678, 797605325, 1681594366, 2005080248, 624648446, 884695971, 1526931791, 1595240948, 439447199, 2060396292, 680093752, 409028215, 469068267, 195583689, 1791650630, 507724330, 1364025102, 1094582668, 813049577, 32316922, 1240756058, 1176200235, 2104494066, 325396055, 1796606917, 1709197385, 525495836, 1510101430, 735526761, 767523533, 1374043776, 1559389967, 567085571, 1560216161, 867042846, 1001796703, 1568754293, 628841972, 173812827, 379868455, 384973125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    int i,a2,a3,a4;
    for(i=0;str[i];++i);
    char buff[10];
 
    a2=1;           //r[3]!=0xfc,此处为1
    a3=0xafff;      //与注册码官方服务有效期相关
    a4=0x98;        //注册码可使用次数
 
    int v5,v6,v7,v8,v9,v10,v11,v12;
    v5=0;
    v6=-1;
    v7=i;
    v8 = 0;
    v9 = 0;
    v10 = (15 * a4)&0xff;
    v11 = 0;
    v12 = (17 * a3)&0xff;
    for(int j=0;j<i;++j){
        int v13,v14,v15,v16,v17,v18,v19;
        v13=toupper(str[j]);
        v14=key[v12&0xff];
        v15=v5+key[v13&0xff];
        v16=key[v10&0xff];
        v17=key[(v13+13)&0xff];
        v18=v13+47;
        v19=v9;
        v12+=9;
        v10+=13;
        v9+=19;
        v11+=7;
        v8+=1;
        v5=(v16+v14+key[v19&0xff]+key[v18&0xff]*(v15^v17))&0xffffffff;
    }
    for(int i=0;i<4;++i){
        buff[4+i]=(v5>>(i*8))&0xff;
    }
    // printf("v5-%x\n",v5);
    buff[3]=0xac;
    int a1_48=0x98*0xb;
    int v15=((a1_48^0x3421)-19760)^0x7892;
    buff[2]=(v15&0xff)^buff[5];
    buff[1]=((v15>>8)&0xff)^buff[7];
    v6=((((0xafff*0x11)^0xffe53167)+180597)^0x22c078^0x5b8c27)&0xffffff;
    buff[0]=(v6&0xff)^buff[6];
    buff[8]=((v6>>8)&0xff)^buff[4];
    buff[9]=((v6>>16)&0xff)^buff[5];
    sprintf(str,"%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x",buff[0]&0xff,buff[1]&0xff,buff[2]&0xff,buff[3]&0xff,buff[4]&0xff,buff[5]&0xff,buff[6]&0xff,buff[7]&0xff,buff[8]&0xff,buff[9]&0xff);
    return str;
}

注册机生成

通过上面的分析,可以实现一个简单的注册机对010Editor注册。


总结

010Editor可以算是对逆向新手比较友好了,算法复杂度有限,没有各种或经典的或自定义的保护机制,非常适合入门选手尝试patch一番.


【公告】欢迎大家踊跃尝试高研班11月试题,挑战自己的极限!

最后于 2021-11-17 08:28 被rolery编辑 ,原因: 图片显示问题
上传的附件:
收藏
点赞5
打赏
分享
最新回复 (5)
雪    币: 591
活跃值: 活跃值 (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
R0g 活跃值 2021-11-17 09:26
2
0
老哥,稳!
昨天刚想破解v12版本今天就出了
雪    币: 5597
活跃值: 活跃值 (958)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
TopC 活跃值 2021-11-17 09:51
3
0
赞一个~
雪    币: 7020
活跃值: 活跃值 (978)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xie风腾 活跃值 2021-11-17 14:26
4
0

学习了,多谢楼主分享
雪    币: 11
活跃值: 活跃值 (320)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tinxi 活跃值 2021-12-8 11:56
5
0
没用?失效了吗
雪    币: 11
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
rolery 活跃值 2021-12-8 18:11
6
0
tinxi 没用?失效了吗
有联网验证,可以把模板下完后去掉联网权限或者按照https://bbs.pediy.com/thread-250270.htm#msg_header_h2_3手动patch
游客
登录 | 注册 方可回帖
返回