吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 7559|回复: 48

[原创逆向图文] Okdo Document Converter Professional 二次验证算法分析

  [复制链接]
LYQingYe 发表于 2016-8-2 15:00 | 显示全部楼层 |阅读模式

[软件名称]  :  OkdoDocument Converter Professional
[编译类型]  :  Delphi
[是否有壳]  :  无壳
[注册类型]  :  注册码注册
[作者信息]  :  LYQingYe
[FBI Warning]  :    学到东西的别忘记评分!


//
//相关算法帖
//
ZD SoftScreen Recorder v9.8算法逆向+keygen
PDFPassword Remover 算法逆向
EditPlus v4.0 算法分析+ keygen

https://www.52hb.com/thread-17607-1-1.html

游客,如果您要查看本帖隐藏内容请回复

//第一次校验思路总结
//将我们输入的Key 总共20位 “01234567890123456789”  , 每次取一位 ‘0’ 调用 CharToHex 将字符串//转换为 整数(hex)数据 0 , 循环19次,将 Key的前 19为数字加起来 得到Addupdate.
//余数 =Addupdate % 0XA , 然后余数跟Key第20位比较,一定要相等,否则失败,在此我们得到了 Key第20位的来源.

//且看第二次校验中的 -> 零散校验

[Asm] 纯文本查看 复制代码
009D5B84  push ebp
009D5B85  mov ebp,esp
009D5B87  mov ecx,0xD
009D5B8C  push 0x0
009D5B8E  push 0x0
009D5B90  dec ecx                                  ;  Converte.00653D8C
009D5B91  jnz short Converte.009D5B8C
009D5B93  push ebx
009D5B94  push esi                                 ;  Converte.0047D780
009D5B95  push edi
009D5B96  mov dword ptr ss:[ebp-0x4],eax
009D5B99  xor eax,eax
009D5B9B  push ebp
009D5B9C  push Converte.009D5FB6
009D5BA1  push dword ptr fs:[eax]
009D5BA4  mov dword ptr fs:[eax],esp
009D5BA7  push 0x1F4                               ; /Timeout = 500. ms
009D5BAC  call <jmp.&kernel32.Sleep>               ; \Sleep
009D5BB1  xor eax,eax
009D5BB3  push ebp
009D5BB4  push Converte.009D5EBF
009D5BB9  push dword ptr fs:[eax]
009D5BBC  mov dword ptr fs:[eax],esp
009D5BBF  lea edx,dword ptr ss:[ebp-0xC]
009D5BC2  mov eax,dword ptr ss:[ebp-0x4]
009D5BC5  mov eax,dword ptr ds:[eax+0x310]
009D5BCB  call Converte.00484EB8                        ;获取输入Key的长度
009D5BD0  mov eax,dword ptr ss:[ebp-0xC]                ;Eax -> Key
009D5BD3  lea edx,dword ptr ss:[ebp-0x8]
009D5BD6  call Converte.0040AC10
009D5BDB  mov eax,dword ptr ss:[ebp-0x8]                ;Eax -> key
009D5BDE  call Converte.00762F98                   ;第一个核心校验Call
009D5BE3  test al,al
009D5BE5  jnz short Converte.009D5C34                ;跳转则失败[/align]
[/align][align=left]//且看第一个核心校验CALL[/align]
[align=left][mw_shl_code=asm,true]00762F98  push ebp
00762F99  mov ebp,esp
00762F9B  add esp,-0xC
00762F9E  push ebx
00762F9F  push esi                                 ;  Converte.0047D780
00762FA0  push edi
00762FA1  xor edx,edx
00762FA3  mov dword ptr ss:[ebp-0xC],edx
00762FA6  mov dword ptr ss:[ebp-0x4],eax
00762FA9  mov eax,dword ptr ss:[ebp-0x4]
00762FAC  call Converte.0040548C                   ;  LoadKey,获取输入的Key
00762FB1  xor eax,eax
00762FB3  push ebp
00762FB4  push Converte.007630BE
00762FB9  push dword ptr fs:[eax]
00762FBC  mov dword ptr fs:[eax],esp
00762FBF  xor eax,eax
00762FC1  push ebp
00762FC2  push Converte.00763094
00762FC7  push dword ptr fs:[eax]
00762FCA  mov dword ptr fs:[eax],esp
00762FCD  mov bl,0x1
00762FCF  mov eax,dword ptr ss:[ebp-0x4]
00762FD2  call Converte.0040529C                   ;  GetKeyLength,获取Key的长度
00762FD7  test eax,eax                                ;  判断长度是否为0
00762FD9  jnz short Converte.00762FEA
00762FDB  xor ebx,ebx
00762FDD  xor eax,eax
00762FDF  pop edx                                  ;  0012FBC4
00762FE0  pop ecx                                  ;  0012FBC4
00762FE1  pop ecx                                  ;  0012FBC4
00762FE2  mov dword ptr fs:[eax],edx
00762FE5  jmp Converte.007630A0
00762FEA  mov eax,dword ptr ss:[ebp-0x4]
00762FED  call Converte.0040529C                   ;  GetKeyLength,获取Key的长度
00762FF2  cmp eax,0x14                                ;  判断Key的长度是否为20
00762FF5  je short Converte.00763006               ;  若不为20,则失败
00762FF7  xor ebx,ebx
00762FF9  xor eax,eax
00762FFB  pop edx                                  ;  0012FBC4
00762FFC  pop ecx                                  ;  0012FBC4
00762FFD  pop ecx                                  ;  0012FBC4
00762FFE  mov dword ptr fs:[eax],edx
00763001  jmp Converte.007630A0
00763006  xor eax,eax
00763008  mov dword ptr ss:[ebp-0x8],eax
0076300B  mov esi,0x1                              ;  ESI = 1 ,Esi作为计数器,循环20次,遍历完整个Key
00763010  xor eax,eax
00763012  push ebp
00763013  push Converte.00763041
00763018  push dword ptr fs:[eax]
0076301B  mov dword ptr fs:[eax],esp
0076301E  lea eax,dword ptr ss:[ebp-0xC]
00763021  mov edx,dword ptr ss:[ebp-0x4]                ; Edx -> Key
00763024  mov dl,byte ptr ds:[edx+esi-0x1]                ; 每次获取一位Key数据
00763028  call Converte.004051B4                   ;  CopyByteDataToNewBuffer,拷贝数据到新的缓冲区
0076302D  mov eax,dword ptr ss:[ebp-0xC]
00763030  call Converte.0040B2E0                   ;  CharToHex,将获取到的Key数据字符转换为hex数值
00763035  mov edi,eax                              ;  EDI = Hex
00763037  xor eax,eax
00763039  pop edx                                  ;  0012FBC4
0076303A  pop ecx                                  ;  0012FBC4
0076303B  pop ecx                                  ;  0012FBC4
0076303C  mov dword ptr fs:[eax],edx
0076303F  jmp short Converte.0076305C
00763041  jmp Converte.00404598
00763046  xor ebx,ebx
00763048  call Converte.004049C4
0076304D  xor eax,eax
0076304F  pop edx                                  ;  0012FBC4
00763050  pop ecx                                  ;  0012FBC4
00763051  pop ecx                                  ;  0012FBC4
00763052  mov dword ptr fs:[eax],edx
00763055  jmp short Converte.007630A0
00763057  call Converte.004049C4
0076305C  cmp esi,0x14                                ; 判断是否遍历结束,20次遍历
0076305F  jge short Converte.00763064              ;  是否遍历结束
00763061  add dword ptr ss:[ebp-0x8],edi           ;  将获取到的hex 累加在一起
00763064  cmp esi,0x14                                ;  是否循环到19次
00763067  jnz short Converte.00763084              ;  Trace END ,若完成19次,则开始计算
00763069  mov eax,dword ptr ss:[ebp-0x8]           ;  ADD UP KEY 1~19 ,将1~19位数值加起来,称为Addupdate
0076306C  mov ecx,0xA                              ;  ECX = 0XA
00763071  cdq        
00763072  idiv ecx                                        ;  将Addupdate / 0xA  ,Edx为余数
00763074  cmp edi,edx                              ;  EDI 为KEY的最后一位,EDX为余数
00763076  je short Converte.00763084               ;  判断余数是否等于 KEY最后一位 ,一定要等于 否则失败

//上面是零散校验的准备阶段,准备阶段很简单,重要的就是 Str4 = ‘267’ ,他会被用作计算值.

//零散校验的次数有很多次,每次Str4 的值都不一样,下面看零散校验,不难和第一次校验有些区别

[Asm] 纯文本查看 复制代码
009D5BE3   test al,al                                        ;接着上面第一次校验
009D5BE5   jnz short Converte.009D5C34
009D5BE7   mov eax,dword ptr ds:[0xA40360]
009D5BEC   push dword ptr ds:[eax]
009D5BEE   mov eax,dword ptr ds:[0xA40BB0]
009D5BF3   push dword ptr ds:[eax]
009D5BF5   push Converte.009D5FCC                   ;  _regcode.ini
009D5BFA   lea eax,dword ptr ss:[ebp-0x10]
009D5BFD   mov edx,0x3
009D5C02   call Converte.0040535C
009D5C07   mov eax,dword ptr ss:[ebp-0x10]
009D5C0A   xor ecx,ecx
009D5C0C   xor edx,edx
009D5C0E   call Converte.007631EC
009D5C13   mov eax,dword ptr ds:[0xA4079C]
009D5C18   mov byte ptr ds:[eax],0x0
009D5C1B   mov eax,dword ptr ds:[0xA401A0]
009D5C20   mov eax,dword ptr ds:[eax]
009D5C22   call Converte.009B4544
009D5C27   mov eax,dword ptr ss:[ebp-0x4]
009D5C2A   call Converte.004A37CC
009D5C2F   jmp Converte.009D5EB5
009D5C34   lea edx,dword ptr ss:[ebp-0x1C]          ;  EDX = NewBuffer
009D5C37   mov eax,dword ptr ds:[0xA40994]
009D5C3C   mov eax,dword ptr ds:[eax]
009D5C3E   call Converte.0040B090                   ;  生成静态字符串str 1 = “31000000”
009D5C43   mov edx,dword ptr ss:[ebp-0x1C]          ;  EDX = Str1
009D5C46   lea ecx,dword ptr ss:[ebp-0x18]          ;  ECX = NewBuffer2
009D5C49   mov eax,dword ptr ds:[0xA3FEF8]

009D5C4E   mov eax,dword ptr ds:[eax]               ; 又得到静态字符串Str2 = 
"363530353A303332363633363530363233373137343434343B36373034353736353A3034333335313B34"
009D5C50   call Converte.009D6944                   ; 得到静态字符串 Str3 = "472782104414724015356666945267547826117396"

009D5C55   mov eax,dword ptr ss:[ebp-0x18]
009D5C58   lea ecx,dword ptr ss:[ebp-0x14]
009D5C5B   mov edx,0xA
009D5C60   call Converte.00762F0C                        ;获得静态字符串Str4
009D5C65   mov eax,dword ptr ss:[ebp-0x14]          ;  Str4 = ‘267’
009D5C68   call Converte.0040B2E0                   ;  CharToHex,将字符串转换为hex数据
009D5C6D   push eax
009D5C6E   lea edx,dword ptr ss:[ebp-0x24]          ;  NEWBUFFER
009D5C71   mov eax,dword ptr ss:[ebp-0x4]
009D5C74   mov eax,dword ptr ds:[eax+0x310]
009D5C7A   call Converte.00484EB8                   ;  GetKeyLength 获取Key的长度
009D5C7F   mov eax,dword ptr ss:[ebp-0x24]          ;  Eax -> Key
009D5C82   lea edx,dword ptr ss:[ebp-0x20]          ;  EDX -> Buffer
009D5C85   call Converte.0040AC10
009D5C8A   mov edx,dword ptr ss:[ebp-0x20]                 ; Edx -> Key
009D5C8D   mov eax,dword ptr ds:[0xA40048]
009D5C92   mov eax,dword ptr ds:[eax]
009D5C94   pop ecx                                  ;  0012FAC8
009D5C95   call Converte.008D62B4                         ;  开始零散校验
009D5C9A   test al,al
009D5C9C   je Converte.009D5D76

//零散校验算法总结.,零散校验1
初始化阶段会生成静态字符串Str4 = ‘267’ ,并转换为 整数
获取Key前4位转换为整数,命名为 Key4bit .
商= Key4bit / 267
余数= Key4bit % 267
余数2= (商 + 余数) % 0XA
Key的第0XD位要等于余数2 ,所以我们得到的Key第14位的来源
//同样的代码校验,下面依次进行零散校验2
初始化阶段会生成静态字符串Str4 = ‘945’ ,并转换为 整数
00948860    . 8A52 0C   mov dl,byte ptrds:[edx+0xC]             ;  第14位
获取Key前4位转换为整数,命名为 Key4bit .
商= Key4bit / 945
余数= Key4bit % 945
余数2= (商 + 余数) % 0XA
Key的第0XD位要等于余数2 ,所以我们得到的Key第14位的来源

//同样的代码校验,下面依次进行零散校验3
初始化阶段会生成静态字符串Str4 = ‘356’ ,并转换为 整数
0092E16C    . 8A52 0A   mov dl,byte ptrds:[edx+0xA]        ; 第11位
获取Key前4位转换为整数,命名为 Key4bit .
商= Key4bit / 356
余数= Key4bit % 356
余数2= (商 + 余数) % 0XA
Key的第0XB位要等于余数2 ,所以我们得到的Key第11位的来源

//有三次零散校验
分别可以得到Key的第 11, 14 ,15 位的来源 ,加上 第一次校验 可以得到 第20位的来源
//下面手动算一个注册码
随机取一个四位数字 ,例如 ‘1687’
1687 / 267 = 6
1687 % 267 = 85
(6 + 85) % 10 = 1  所以第14位为1
继续
1687 / 945  = 1
1687 % 945 = 742
(742 + 1) % 10 = 3 所以第13位为 3
继续
1687 / 356 = 4
1687 % 356 = 263
(4 + 263) % 10 = 7 所以第11位为 7
这样我们可以生成一个 19位的 Key其它位用随机值 填充
1687 1234 58 7 1311 5874
下面计算20位
Addupdate = 1 + 6 + 8 + 7 + 1 + 2+ 3 + 4 + 5 + 8 + 7 + 1 + 3 + 1+ 1+ 5 + 8 + 7 + 4
       = 82
82 % 10 = 2 所以第20位为2
组装成20位Key则为
16871234587131158742

输入Key显示成功

2.png


//但发现重启程序后还是未注册,这就触发了二次验证,可以通过,搜索字符串找到二次验证CALL

3.png

//得到重启验证CALL sub_007630D0  , 跟随后可以到达校验位置
//009A54A7    . 55        push ebp

[Asm] 纯文本查看 复制代码
008D62B4    >push ebp
008D62B5    >mov ebp,esp
008D62B7    >add esp,-0x10
008D62BA    >push ebx
008D62BB    >push esi
008D62BC    >push edi
008D62BD    >xor ebx,ebx
008D62BF    >mov dword ptr ss:[ebp-0x10],ebx
008D62C2    >mov dword ptr ss:[ebp-0xC],ebx
008D62C5    >mov esi,ecx
008D62C7    >mov dword ptr ss:[ebp-0x4],edx
008D62CA    >mov eax,dword ptr ss:[ebp-0x4]
008D62CD    >call Converte.0040548C                   ;  GetKey 获得输入的Key,和第一次校验差不多的步骤
008D62D2    >xor eax,eax
008D62D4    >push ebp
008D62D5    >push Converte.008D63A9
008D62DA    >push dword ptr fs:[eax]
008D62DD    >mov dword ptr fs:[eax],esp
008D62E0    >mov byte ptr ss:[ebp-0x5],0x0
008D62E4    >mov eax,dword ptr ss:[ebp-0x4]
008D62E7    >call Converte.0040529C                        ;GetKeyLength 获取Key长度
008D62EC    >test eax,eax                                ;判断长度是否为0
008D62EE    >jnz short Converte.008D62F9                
008D62F0    >mov byte ptr ss:[ebp-0x5],0x0
008D62F4    >jmp Converte.008D6386
008D62F9    >mov eax,dword ptr ss:[ebp-0x4]
008D62FC    >call Converte.0040529C
008D6301    >cmp eax,0x14                                ;判断长度是否为20,若不是则失败
008D6304    >je short Converte.008D630C
008D6306    >mov byte ptr ss:[ebp-0x5],0x0
008D630A    >jmp short Converte.008D6386
008D630C    >xor eax,eax
008D630E    >push ebp
008D630F    >push Converte.008D637C
008D6314    >push dword ptr fs:[eax]
008D6317    >mov dword ptr fs:[eax],esp
008D631A    >lea eax,dword ptr ss:[ebp-0xC]
008D631D    >push eax
008D631E    >mov ecx,0x4
008D6323    >mov edx,0x1
008D6328    >mov eax,dword ptr ss:[ebp-0x4]                   : Eax -> Key         
008D632B    >call Converte.004054FC                   ;  获取KEY 前4位
008D6330    >mov eax,dword ptr ss:[ebp-0xC]
008D6333    >call Converte.0040B2E0                   ;  CharToHex ,将Key前四位转换为整数,我们设为key4bit
008D6338    >mov ebx,eax
008D633A    >lea eax,dword ptr ss:[ebp-0x10]
008D633D    >mov edx,dword ptr ss:[ebp-0x4]                   ; Edx ->Key        
008D6340    >mov dl,byte ptr ds:[edx+0xD]             ;  获取Key的 第0xD位,
008D6343    >call Converte.004051B4                   ;  
008D6348    >mov eax,dword ptr ss:[ebp-0x10]           ;  Key的第 0xE位        
008D634B    >call Converte.0040B2E0                   ;  CharToHex ,将第0xD位转换为整数
008D6350    >mov ecx,eax                              ;  ECX = Key的0XD位
008D6352    >mov eax,ebx                                   ;  EAX= key4bit        
008D6354    >cdq
008D6355    >idiv esi                                 ; Esi 为零散校验前初始化的Str4 ‘267’ 对应的整数 267
008D6357    >mov edi,eax                              ; edi =  key4bit / 267 ,Edi存放商
008D6359    >mov eax,ebx
008D635B    >cdq
008D635C    >idiv esi                                 ;  再次计算 key4bit / 267 ,EDX为余数
008D635E    >add edi,edx                              ;  calc = 余数 + 商
008D6360    >mov eax,edi                                   ;  Eax = calc
008D6362    >mov ebx,0xA                              ;  EBX = 0XA
008D6367    >cdq
008D6368    >idiv ebx                                           ;  余数2 = calc % 0XA        
008D636A    >cmp ecx,edx                              ;  判断余数2是否等于Key的0XD位
008D636C    >jnz short Converte.008D6372                   ; 一定要等于,否则失败

4.png

评分

参与人数 27威望 +1 HB +68 THX +17 收起 理由
longge188 + 1 [吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少!
托马斯 + 1 【不符版规】您所发布的内容,不符合版规要求。5HB为系统默认发帖奖励,现已撤销。
sjtkxy + 1
虚心学习 + 1 [吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩!
24567 + 1
Jawon + 2
zxjzzh + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
一路走来不容易 + 1
消逝的过去 + 2
禽大师 + 1
ldljlzw + 1
liugu0hai + 1 + 1 [吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩!
逢场作旭 + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
hetao8003200 + 2
lies + 1
菜鸟中的菜鸟 + 5 + 1 膜拜算法牛
Baiyebuhao + 1 小白一枚,看到已经觉得好屌啊,感谢楼主的分享,要多向楼主学习
小不点吃肉 + 1 精品,谢谢分享
Rooking + 2 + 1 希望有时间多跟楼主讨教讨教
woshinimaq + 1 评分=感恩!简单却充满爱!感谢您的作品!
soberkiing + 1 + 1 分享精神,是最值得尊敬的!
小久久 + 3 + 1 分享精神,是最值得尊敬的!
Bu弃 + 5 + 1 强大,不评分,天理难容
duanbin109 + 1 + 1 分享精神,是最值得尊敬的!
小彬来了 + 4 + 1 不评分 天理难容
剑不会断的 + 3 + 1 评分=感恩!简单却充满爱!感谢您的作品!
Shark恒 + 1 + 30 + 1 精彩分析,不给精华天理难容哇!

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Shark恒 发表于 2016-8-2 17:05 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| LYQingYe 发表于 2016-8-2 17:36 | 显示全部楼层

Shark恒 发表于 2016-8-2 17:05
精彩分析,不给精华天理难容哇!

算发帖基本没人看啊

点评

Shark恒”点评说:
相对来讲看懂的人少,我建议增加寻找关键CALL的部分。  详情 回复 发表于 2016-8-3 08:11
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Very_good 发表于 2016-8-2 17:38 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| LYQingYe 发表于 2016-8-2 17:44 | 显示全部楼层


多谢大哥赏脸
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
小彬来了 发表于 2016-8-2 17:49 | 显示全部楼层

这些代码 你说一般人是看不懂的。  膜拜玩C的
大牛 论坛有你这种人才 才叫论坛  评分走一波
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Shark恒 发表于 2016-8-3 08:11 | 显示全部楼层

LYQingYe 发表于 2016-8-2 17:36
算发帖基本没人看啊

相对来讲看懂的人少,我建议增加寻找关键CALL的部分。
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| LYQingYe 发表于 2016-8-3 08:46 | 显示全部楼层

Shark恒 发表于 2016-8-3 08:11
相对来讲看懂的人少,我建议增加寻找关键CALL的部分。

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
jiajiayu 发表于 2016-8-3 10:12 来自手机端 | 显示全部楼层

算法太过高深
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
2570505044 发表于 2016-8-3 10:16 | 显示全部楼层

一脸懵逼的新人看着一连串的英文字母表示不懂
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层
7层
8层
9层
10层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表