【软件名称】   Image2Lcd 2.9
【下载页面】   http://www.onlinedown.net/soft/12995.htm
【加密方式】   注册码
【破解声明】   破解只是学习,没有任何目的。失误之处难免,敬望诸位大侠赐教!
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////


今天有时间,看了一个软件,老版本的曾经分析过,现在的注册过程与以前有明显不同,就重新分析了下
简单至极,与和我一样的菜鸟交流学习,下面是我的分析过程:
输入试验码:1234 45678 abcd efgh ligy,下断点bp getdlgitem,点确定,程序被断下,Alt+F9
返回:
0040BED5  push ebx
0040BED6  push 0A
0040BED8  push 0D
0040BEDA  push eax
0040BEDB  push esi
0040BEDC  call dword ptr ds:[<&USER32.SendDlgItemMessag>;得到一个指向一组注册码的地址
0040BEE2  push ebx                                      ;Alt+F9返回到这里 依次获取一组注册码 
0040BEE3  call Img2Lcd.0040BBF0                         ;这里是对每一组注册码字符进行处理(F7跟进)
0040BEE8  mov word ptr ss:[ebp],ax                      ;把每一组注册码依次保存 
0040BEEC  add edi,4
0040BEEF  add esp,4
0040BEF2  add ebx,0A
0040BEF5  add ebp,2                                     
0040BEF8  cmp edi,Img2Lcd.00415B7C                      ; 因为0x415b7c-0x415b68=0x14=20
0040BEFE  jl short Img2Lcd.0040BED3                     ; 应次要运行20/4=5次
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
跟进上面的call:
0040BBF0  mov edx,dword ptr ss:[esp+4]                  ;得到注册码的地址
0040BBF4  xor eax,eax
0040BBF6  mov cl,byte ptr ds:[edx]                      ;取一个注册码     
0040BBF8  test cl,cl                                    
0040BBFA  je short Img2Lcd.0040BC36                     
0040BBFC  inc edx 
0040BBFD  cmp cl,30                                     ;比较是不是'0'<=cl<='9'
0040BC00  jl short Img2Lcd.0040BC0C                     ;不是做下一次比较
0040BC02  cmp cl,39
0040BC05  jg short Img2Lcd.0040BC0C
0040BC07  add cl,0D0                                    ;是则cl+=0xd0
0040BC0A  jmp short Img2Lcd.0040BC28
0040BC0C  cmp cl,41                                     ;比较是不是'A'<=cl<='F'
0040BC0F  jl short Img2Lcd.0040BC1B                     ;不是做下一次比较
0040BC11  cmp cl,46                                     
0040BC14  jg short Img2Lcd.0040BC1B
0040BC16  add cl,0C9                                    ;是则cl+=0xc9
0040BC19  jmp short Img2Lcd.0040BC28
0040BC1B  cmp cl,61                                     ;比较是不是'a'<=cl<='f'
0040BC1E  jl short Img2Lcd.0040BC28
0040BC20  cmp cl,66
0040BC23  jg short Img2Lcd.0040BC28                    
0040BC25  add cl,0A9                                    ;是则cl+=0xa9
0040BC28  movsx ecx,cl
0040BC2B  shl eax,4                                     ;eax的值即是转换后注册码
0040BC2E  or eax,ecx
0040BC30  mov cl,byte ptr ds:[edx]                    ;取下一个注册码
0040BC32  test cl,cl
0040BC34  jnz short Img2Lcd.0040BBFC
0040BC36  retn
这一段代码可以看出注册码的标准形式应该是由16进制的字符组成的,把注册码 由字符串转换成
它表示的16进制形式,说不好,就是"ABCF"或"abcf"转换成ABCF这个16进制值,其它字符会使格式
产生异化,就会不符合标准,写注册机就相对复杂化。
重新输入试验码:1234 45678 abcd fedc 9876 再来
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////

0040BF00  lea ecx,dword ptr ss:[esp+1C]
0040BF04  push 0
0040BF06  push ecx
0040BF07  mov word ptr ss:[esp+2E],11D2                ;有四个数据保存
0040BF0E  mov dword ptr ss:[esp+30],50AEF62F
0040BF16  mov word ptr ss:[esp+34],15F8
0040BF1D  mov word ptr ss:[esp+36],2063                 ;很明显下面就是关键call
0040BF24  call dword ptr ds:[<&sss.SSS_Reg>]            ; sss.SSS_Reg
0040BF2A  mov edi,dword ptr ss:[esp+74]
0040BF2E  add esp,8                                                    
0040BF31  xor eax,eax
0040BF33  cmp word ptr ss:[esp+26],572
0040BF3A  pop ebp
0040BF3B  sete al
0040BF3E  test eax,eax
0040BF40  mov dword ptr ds:[edi],eax
0040BF42  je Img2Lcd.0040BFDB                           ; 这里是关键跳转,eax为零就跳走
0040BF48  lea edx,dword ptr ss:[esp+18]                 ; 估计注册码不正确关键call有xor语句,去看看
0040BF4C  push edx
0040BF4D  call Img2Lcd.004022F0
0040BF52  mov eax,dword ptr ds:[4140D0]
0040BF57  add esp,4
0040BF5A  push 0
0040BF5C  push 40
0040BF5E  push eax
0040BF5F  push 15FAD
0040BF64  call Img2Lcd.00401780
0040BF69  add esp,4
0040BF6C  push eax
0040BF6D  push esi
0040BF6E  call dword ptr ds:[<&USER32.MessageBoxExA>]   ; 这里就是注册成功的对话框了
0040BF74  mov ecx,dword ptr ds:[edi+44]
0040BF77  mov esi,dword ptr ds:[<&USER32.SendMessageA>] ; USER32.SendMessageA
0040BF7D  push 0
0040BF7F  push 0
0040BF81  push 130C
0040BF86  push ecx
0040BF87  call esi
0040BF89  mov edx,dword ptr ds:[edi+44]
0040BF8C  lea eax,dword ptr ss:[esp+C]
0040BF90  push eax
0040BF91  mov ecx,edi
////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
跟进来到这里:
10007090 >sub esp,18
10007093  mov ecx,6
10007098  push ebp
10007099  mov ebp,dword ptr ss:[esp+20]
1000709D  push esi
1000709E  push edi
1000709F  mov esi,ebp
100070A1  lea edi,dword ptr ss:[esp+C]
100070A5  rep movs dword ptr es:[edi],dword ptr d>
100070A7  cmp word ptr ss:[esp+1E],0
100070AD  je short sss.100070C7
100070AF  mov ecx,dword ptr ss:[esp+C]            ; 取转化后的前2组注册码(56781234)
100070B3  xor edx,edx
100070B5  mov eax,ecx                             
100070B7  imul eax,dword ptr ss:[esp+1E]          ; eax*=0x2063
100070BC  mov dl,ah
100070BE  mov dh,al
100070C0  add edx,ecx
100070C2  mov word ptr ss:[esp+E],dx              ; 替换第2组(第2组真码保存)
100070C7  mov eax,dword ptr ss:[esp+E]            ; 取2,3组
100070CB  mov ecx,dword ptr ss:[esp+C]            ; 取1,2组
100070CF  and eax,0FFFF                           ; 取低16 位
100070D4  and ecx,0FFFF
100070DA  add eax,ecx                             ; eax+ecx(1组+2组)
100070DC  lea edx,dword ptr ss:[esp+C]
100070E0  mov dword ptr ss:[esp+20],eax           ; 保存
100070E4  xor eax,eax
100070E6  mov ah,byte ptr ss:[esp+E]              ; 取注册码的
100070EA  push edx
100070EB  mov al,byte ptr ss:[esp+11]
100070EF  push eax                                ; 计算中用到的第一个参数  
100070F0  call sss.10007050                       ; 计算下组注册码
100070F5  mov ecx,9988
100070FA  add esp,8
100070FD  mov word ptr ss:[esp+10],ax             ; 替换第3组注册码(保存第3组真码)
10007102  xor esi,esi
10007104  mov dword ptr ss:[esp+20],ecx
10007108  lea edx,dword ptr ss:[esp+C]
1000710C  mov edi,3
10007111  mov ax,word ptr ds:[edx]
10007114  add edx,2
10007117  add esi,eax                             ; esi=1组+2组+3组
10007119  and eax,0FFFF
1000711E  shl ecx,10
10007121  add ecx,eax
10007123  dec edi
10007124  mov dword ptr ss:[esp+20],ecx          ; 最终保存的是2,3组真码
10007128  jnz short sss.10007111
1000712A  mov edx,dword ptr ss:[esp+10]          ; 取3,4组
1000712E  lea ecx,dword ptr ss:[esp+C]
10007132  xor edx,esi
10007134  push ecx
10007135  push edx                               ; 计算中用到的第一个参数
10007136  call sss.10007050
1000713B  mov word ptr ss:[esp+1A],ax            ; 第4组真码
10007140  mov eax,dword ptr ss:[esp+1A]
10007144  lea ecx,dword ptr ss:[esp+14]
10007148  lea esi,dword ptr ds:[esi+eax-1E92]
1000714F  push ecx
10007150  xor eax,esi
10007152  push eax                               ; 计算中用到的第一个参数
10007153  call sss.10007050                      ; 产生第5组真码->ax
10007158  mov ecx,dword ptr ss:[esp+3C]
1000715C  add esp,10
1000715F  test ecx,ecx
10007161  mov word ptr ss:[esp+14],ax
10007166  je short sss.10007184
10007168  cmp word ptr ss:[ebp+A],572
1000716E  jnz short sss.100071BF
10007170  mov ecx,6
10007175  lea esi,dword ptr ss:[esp+C]
10007179  mov edi,ebp
1000717B  rep movs dword ptr es:[edi],dword ptr d>
1000717D  pop edi
1000717E  pop esi
1000717F  pop ebp
10007180  add esp,18
10007183  retn
10007184  cmp ax,word ptr ss:[ebp+8]              ; 与第5组注册码比较
10007188  jnz short sss.100071B8
1000718A  mov dx,word ptr ss:[esp+12]
1000718F  cmp dx,word ptr ss:[ebp+6]              ; 与第4组注册码比较
10007193  jnz short sss.100071B8
10007195  mov ax,word ptr ss:[esp+10]
1000719A  cmp ax,word ptr ss:[ebp+4]              ; 与第3组注册码比较
1000719E  jnz short sss.100071B8
100071A0  mov cx,word ptr ss:[esp+E]
100071A5  cmp cx,word ptr ss:[ebp+2]              ; 与第2组注册码比较
100071A9  jnz short sss.100071B8
100071AB  pop edi
100071AC  mov word ptr ss:[ebp+A],572
100071B2  pop esi
100071B3  pop ebp
100071B4  add esp,18
100071B7  retn
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
计算第3.4.5组主册码的call
10007050  mov ecx,dword ptr ss:[esp+8]
10007054  mov eax,dword ptr ss:[esp+4]            ; call前面保存的一个值
10007058  and eax,0FFFF
1000705D  mov edx,dword ptr ds:[ecx+14]           ; call前面保存的一个值
10007060  add eax,edx
10007062  mov edx,dword ptr ds:[ecx+C]            ; 里面的值是0x50AEF62F
10007065  add edx,434713EA
1000706B  imul eax,edx
1000706E  xor edx,edx
10007070  mov dx,word ptr ds:[ecx+10]             ; 里面的值是0x15F8
10007074  lea eax,dword ptr ds:[eax+edx+D431]     ; eax=eax+edx+0xd431
1000707B  mov dword ptr ds:[ecx+14],eax           ; 保存temp
1000707E  shr eax,10
10007081  retn                                    ; ax的值就是注册码
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////

【算法总结:】由输入第一组注册码,依次得到真正第2,3,4,5组册码与输入比较,全符合则能够正确注册
1.第2组生成过程:eax=code1*0x2063取ax低8位a和高8位b组成新数ab,ab+code1=code2
2.第3组生成过程:取code1前2位a,code2后2位b,组成ba,eax=(ba+(code1+code2))*(0x50AEF62F+0x434713EA)
code3=(eax+0x15F8+0xD431)高16位
3.第4组生成过程:eax=(code3^(code1+code2+code3)+temp)*(0x50AEF62F*0x434713EA) (这里temp=code2<<16+code3)
code3=(eax+0x15F8+0xD431)高16位
4.第5组生成过程:eax=(code4^(code1+code2+code3+code4)+temp)*(0x50AEF62F*0x434713EA) (这里temp由3产生)
code3=(eax+0x15F8+0xD431)高16位
写了一个简单算法注册机,只是把作者的简单改写下,没有什么技术含量,见笑
void main(){
  unsigned short code[5]={0x1234,0,0,0,0};
    unsigned short * p=code;
  time_t tt;
    srand((unsigned) time(&tt));
  code[0]=rand()%0xffff;
  
  __asm{
    xor ecx,ecx
    mov ebx,p
    mov cx,word ptr [ebx]
    mov eax,ecx
    imul eax,02063h
    mov dl,ah
    mov dh,al
    add edx,ecx
    mov word ptr [ebx+2],dx ;第2组注册码
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    shl dx,8
    mov dl,ch 
    mov ax,word ptr [ebx+2]
    and eax,0ffffh
    add eax,ecx
    and edx,0ffffh
    add eax,edx
    imul eax,093F60A19h
    add  eax,0ea29h
    shr eax,010h
    mov word ptr [ebx+4],ax ;第3组注册码
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    xor ecx,ecx
    mov edx,eax
    add dx,word ptr [ebx+2]
    add dx,word ptr [ebx]
    xor eax,edx
    mov cx,word ptr [ebx+2]
    shl ecx,010h
                mov cx,word ptr [ebx+4]
          add eax,ecx
    imul eax,093F60A19h
    add  eax,0ea29h
    mov ecx,eax
    shr eax,010h
    mov word ptr [ebx+6],ax ;第4组注册码
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                add edx,eax
    sub edx,01e92h
    xor eax,edx
    and eax,0ffffh
    add eax,ecx
    imul eax,093F60A19h
    add  eax,0ea29h
    shr eax,010h
    mov word ptr [ebx+8],ax ;第5组注册码
       
  }
  printf("注册码:"); 
  for(int i=0;i<5;i++)
  printf("%X ",code[i]);
  printf("\n");
}
注册信息保存在[HKEY_LOCAL_MACHINE\SOFTWARE\Image2Lcd]