【软件名称】 Image2Lcd 2.9
【下载页面】 http://www.onlinedown.net/soft/12995.htm
【加密方式】 注册码
【软件简介】
Image2Lcd 是一款工具软件,它能使你把各种来源的图片转换成特定的数据格式以用来匹配
单片机系统所需要的显示数据格式。Image2Lcd支持的输入图像格式包括: BMP, WBMP, JPG,
GIF, WMF, EMF, ICO, 等等。Image2Lcd的输出数据类型包括定制的二进制类型、C语言数组
类型和标准的BMP格式、WBMP格式。Image2Lcd能可视调节输入图象的数据扫描方式、灰度(颜
色数)、图像数据排列方式、亮度、对比度、等等。对于包含了图像头数据保存的图像数据文
件,Image2Lcd能重新打开作为输入图像。未注册的版本将在输入输出图像上加上“Image2Lc
d”字样,注册后该字样将立即永久消失。
【破解声明】 破解只是学习,没有任何目的。失误之处难免,敬望诸位大侠赐教!
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
今天有时间,看了一个软件,老版本的曾经分析过,现在的注册过程与以前有明显不同,就重新分析了下
简单至极,与和我一样的菜鸟交流学习,下面是我的分析过程:
输入试验码: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]
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)