老文章档案 · 2003 年

IrfanView 注册机分析(初级版) (13千字) 算法分析

赢政天下 [WINZHENG.COM] · 网络学院 · 2003-08-01 · 作者:少昊 人气: · 出处:赢政天下整理收藏)

初学解密,很想做一个 KeyGen,这是低级菜鸟向高级菜鸟升级的必经之路。于是驾猫寻得一看图软件

IfanView 效果不错,功能强大,可和 ACDSee 相媲美。这个软件不需要注册即可使用其全部功能,不过他

还是设置了注册选项,注册成功后,在关于对话框中就有你的大名了。正好那他开刀。拿宝刀 Trw2000 。

下 bpx hmemcpy,截下后 bc *,再 pmodule,这时已得到输入的名字,F10 跟下去,又得到输入的假注册

码(d eax 看看,里面放着输入数据的长度)。再跟下去领空会进入系统内核,下 pmodule 跳出来,往下

走来到一个循环,别管它,用 g 命令跳过去,接下来就是本文的正题了:(顺便提一下,姓名必须大于 2

各字符且小于 85 个字符。仔细看就会发现)

..................................

0167:0044FC1E LEA ECX,[ESP+11D0]----放入你输入的假注册码

0167:0044FC25 LEA EDX,[ESP+10D0]----放入你输入的名字

0167:0044FC2C PUSH ECX

0167:0044FC2D PUSH EDX

0167:0044FC2E CALL 00435F40----应该有点感觉吧,真正的注册码就在里面产生

//这个CALL下面的内容我就省略了,应位于主题无关。

...................................

0167:00435F40 MOV EAX,[ESP+08]----从上面的CALL跳过来的。开工哦^o^

0167:00435F44 SUB ESP,BYTE +14

0167:00435F47 PUSH EBX

0167:00435F48 PUSH EBP

0167:00435F49 PUSH ESI

0167:00435F4A PUSH EDI

0167:00435F4B PUSH EAX

0167:00435F4C XOR EBX,EBX

0167:00435F4E CALL 004B0863----这个CALL可能有用,不过随叫咱还是菜鸟,别管它,抓住关键最重要

0167:00435F53 MOV ESI,[ESP+2C]

0167:00435F57 MOV EBP,EAX

0167:00435F59 MOV EDI,ESI

0167:00435F5B OR ECX,BYTE -01

0167:00435F5E XOR EAX,EAX

0167:00435F60 ADD ESP,BYTE +04

0167:00435F63 XOR EDX,EDX

0167:00435F65 REPNE SCASB

0167:00435F67 NOT ECX

0167:00435F69 DEC ECX

0167:00435F6A TEST ECX,ECX

0167:00435F6C JNG 00435F85

0167:00435F6E MOVSX ECX,BYTE [EDX+ESI]----从这里开始工作哦

0167:00435F72 ADD EBX,ECX

0167:00435F74 MOV EDI,ESI

0167:00435F76 OR ECX,BYTE -01

0167:00435F79 XOR EAX,EAX

0167:00435F7B INC EDX

0167:00435F7C REPNE SCASB

0167:00435F7E NOT ECX

0167:00435F80 DEC ECX

0167:00435F81 CMP EDX,ECX----EDX放名字的长度

0167:00435F83 JL 00435F6E----将名字的各个ASCII码相加后放入EBX

0167:00435F85 MOV EAX,0104----以下各部生成密文

0167:00435F8A PUSH BYTE +0A

0167:00435F8C SUB EAX,EBX

0167:00435F8E CDQ

0167:00435F8F XOR EAX,EDX

0167:00435F91 SUB EAX,EDX

0167:00435F93 ADD EAX,014C

0167:00435F98 LEA EDX,[EAX*8+00]

0167:00435F9F SUB EDX,EAX

0167:00435FA1 LEA ECX,[EAX+EDX*4]

0167:00435FA4 LEA EDX,[ESP+14]

0167:00435FA8 PUSH EDX

0167:00435FA9 LEA ESI,[EAX+ECX*2]

0167:00435FAC SHL ESI,03

0167:00435FAF PUSH ESI----到此为止输入? esi后看到的十进制数即为密文

0167:00435FB0 CALL 004BB8D4----处理密文的有效性,并且将十进制密文转换为ASCII码

0167:00435FB5 ADD ESP,BYTE +0C

0167:00435FB8 CMP ESI,000F423F----查看十进制的密文是否大于999999按它的算法大于999999的

//可能性不大。不过我还是写了C源代码。你可以忽略不管。

0167:00435FBE JA NEAR 004360B3----大就跳,一般是小

0167:00435FC4 MOV CL,[ESP+14]----开始进行密文数据的移位,大致顺序是:(第一位记为0)

//第4位到第6位,第5位到第8位,第3位到第5位,

//第2位到第3位,第1位到第2位

0167:00435FC8 MOV AL,[ESP+15]

0167:00435FCC MOV DL,[ESP+13]

0167:00435FD0 MOV [ESP+16],CL

0167:00435FD4 MOV CL,[ESP+11]

0167:00435FD8 MOV [ESP+18],AL

0167:00435FDC MOV AL,[ESP+12]

0167:00435FE0 MOV [ESP+15],DL

0167:00435FE4 MOV [ESP+12],CL

0167:00435FE8 MOV ECX,[ESP+14]

0167:00435FEC AND ECX,FF----和上面的一句加起来其实就是一句MOV CL,[ESP+14]。这样的语句后面还

//有,要注意哦。

0167:00435FF2 MOV [ESP+13],AL-------数据移位结束,多看看就明白了^_^

0167:00435FF6 MOV EAX,ECX----ECX里放的是第4位,不了解就再仔细看看上面的数据移位方法

0167:00435FF8 SHL EAX,05----接下来是一大堆无聊的操作,大家都是菜鸟,每句用C语言表示就可以了

0167:00435FFB SUB EAX,ECX

0167:00435FFD MOV ECX,[ESP+18]

0167:00436001 AND ECX,FF

0167:00436007 LEA EDX,[EAX+EAX*2]----无聊,不就是EAX*3吗!_^

0167:0043600A LEA EAX,[ECX+ECX*4]

0167:0043600D SHL EAX,03

0167:00436010 SUB EAX,ECX

0167:00436012 SUB EAX,EDX

0167:00436014 CDQ ----把EAX的符号扩展到EDX中去(若EAX为负,则EDX为-1,否则为0)后面

//也有这样的语句

0167:00436015 MOV ECX,EAX

0167:00436017 XOR ECX,EDX

0167:00436019 SUB ECX,EDX

0167:0043601B LEA EAX,[ECX+ECX*4]又来了,写成C语言的时候可别范傻

0167:0043601E SHL EAX,03

0167:00436021 SUB EAX,ECX

0167:00436023 MOV ECX,09

0167:00436028 CDQ

0167:00436029 IDIV ECX

0167:0043602B MOV EAX,[ESP+13]

0167:0043602F AND EAX,FF

0167:00436034 ADD DL,30

0167:00436037 MOV [ESP+17],DL

0167:0043603B LEA EDX,[EAX+EAX*2]

0167:0043603E SHL EDX,04

0167:00436041 SUB EDX,EAX

0167:00436043 MOV EAX,[ESP+15]

0167:00436047 AND EAX,FF

0167:0043604C LEA ECX,[EAX+EAX*8]

0167:0043604F LEA EAX,[EAX+ECX*4]

0167:00436052 LEA EAX,[EDX+EAX*2]

0167:00436055 CDQ

0167:00436056 XOR EAX,EDX

0167:00436058 SUB EAX,EDX

0167:0043605A LEA ECX,[EAX+EAX*8]

0167:0043605D LEA EAX,[EAX+ECX*4]

0167:00436060 MOV ECX,09

0167:00436065 SHL EAX,1

0167:00436067 CDQ

0167:00436068 IDIV ECX

0167:0043606A MOV ECX,[ESP+10]

0167:0043606E AND ECX,FF

0167:00436074 LEA EAX,[ECX+ECX*2]

0167:00436077 LEA EAX,[EAX+EAX*8]

0167:0043607A SHL EAX,1

0167:0043607C SUB EAX,ECX

0167:0043607E ADD DL,30

0167:00436081 MOV [ESP+14],DL

0167:00436085 MOV ECX,[ESP+11]

0167:00436089 AND ECX,FF

0167:0043608F LEA EDX,[ECX*8+00]

0167:00436096 SUB EDX,ECX

0167:00436098 LEA EDX,[EDX+EDX*4]

0167:0043609B SUB EAX,EDX

0167:0043609D CDQ

0167:0043609E MOV ECX,EAX

0167:004360A0 XOR ECX,EDX

0167:004360A2 SUB ECX,EDX

0167:004360A4 LEA EAX,[ECX+ECX*2]

0167:004360A7 LEA EAX,[EAX+EAX*8]

0167:004360AA SHL EAX,1

0167:004360AC SUB EAX,ECX----慢慢长路。吾等菜鸟,就把上面的汇编语句

//一句一句翻成C语句吧!!!_!

0167:004360AE JMP 004361A8----跳过去检测生成的注册码的正确性

0167:004360B3 MOV AL,[ESP+15]----密文大于999999时的处理方法,和前面的有些相识

0167:004360B7 MOV DL,[ESP+16]

0167:004360BB MOV CL,[ESP+14]

0167:004360BF MOV [ESP+16],AL

0167:004360C3 MOV AL,[ESP+11]

0167:004360C7 MOV [ESP+18],DL

0167:004360CB MOV DL,[ESP+12]

0167:004360CF MOV [ESP+12],AL

0167:004360D3 MOV EAX,[ESP+16]

0167:004360D7 MOV [ESP+15],CL

0167:004360DB AND EAX,FF

0167:004360E0 MOV [ESP+13],DL

0167:004360E4 MOV ECX,EAX

0167:004360E6 SHL ECX,06

0167:004360E9 SUB ECX,EAX

0167:004360EB MOV EAX,[ESP+18]

0167:004360EF AND EAX,FF

0167:004360F4 LEA EAX,[EAX+EAX*8]

0167:004360F7 SHL EAX,02

0167:004360FA SUB EAX,ECX

0167:004360FC MOV ECX,09

0167:00436101 CDQ

0167:00436102 XOR EAX,EDX

0167:00436104 SUB EAX,EDX

0167:00436106 LEA EAX,[EAX+EAX*8]

0167:00436109 SHL EAX,02

0167:0043610C CDQ

0167:0043610D IDIV ECX

0167:0043610F ADD DL,30

0167:00436112 MOV [ESP+17],DL

0167:00436116 MOV EAX,[ESP+14]

0167:0043611A AND EAX,FF

0167:0043611F ADD EAX,BYTE +20

0167:00436122 LEA EDX,[EAX*8+00]

0167:00436129 SUB EDX,EAX

0167:0043612B LEA EAX,[EAX+EDX*4]

0167:0043612E LEA ECX,[EAX+EAX*2]

0167:00436131 MOV EAX,[ESP+13]

0167:00436135 AND EAX,FF

0167:0043613A LEA EDX,[EAX+EAX*4]

0167:0043613D SHL EDX,03

0167:00436140 SUB EDX,EAX

0167:00436142 LEA EAX,[ECX+EDX*2]

0167:00436145 CDQ

0167:00436146 XOR EAX,EDX

0167:00436148 SUB EAX,EDX

0167:0043614A LEA ECX,[EAX*8+00]

0167:00436151 SUB ECX,EAX

0167:00436153 LEA EAX,[EAX+ECX*4]

0167:00436156 MOV ECX,09

0167:0043615B LEA EAX,[EAX+EAX*2]

0167:0043615E CDQ

0167:0043615F IDIV ECX

0167:00436161 MOV EAX,[ESP+10]

0167:00436165 AND EAX,FF

0167:0043616A ADD DL,30

0167:0043616D MOV [ESP+14],DL

0167:00436171 LEA EDX,[EAX*8+00]

0167:00436178 SUB EDX,EAX

0167:0043617A LEA EAX,[EAX+EDX*4]

0167:0043617D MOV EDX,[ESP+11]

0167:00436181 AND EDX,FF

0167:00436187 MOV ECX,EDX

0167:00436189 SHL ECX,04

0167:0043618C ADD ECX,EDX

0167:0043618E SHL EAX,1

0167:00436190 LEA ECX,[ECX+ECX*4]

0167:00436193 SUB EAX,ECX

0167:00436195 CDQ

0167:00436196 XOR EAX,EDX

0167:00436198 SUB EAX,EDX

0167:0043619A LEA EDX,[EAX*8+00]

0167:004361A1 SUB EDX,EAX

0167:004361A3 LEA EAX,[EAX+EDX*4]

0167:004361A6 SHL EAX,1

0167:004361A8 CDQ ---上面的正确性检测跳转语句跳过来的。这里也是一条语句别忘哦!

0167:004361A9 MOV ECX,09

0167:004361AE MOV BYTE [ESP+19],00----加上字符串结尾符'\0',这里可知注册码必为10位

0167:004361B3 IDIV ECX

0167:004361B5 ADD DL,30

0167:004361B8 MOV [ESP+11],DL

0167:004361BC LEA EDX,[ESP+10]

0167:004361C0 PUSH EDX----一般来说到这里就能找到正确的注册码了,打d esp+10看看

0167:004361C1 CALL 004B0863----这里开始对生成的注册码进行正确性检测。不过用处不大,不需要

//为他编写源程序,通常都能校验通过(随叫我是菜鸟,只要把问题大

//致解决就可以了,想要进一步了解的话,自己进去就是了吧)

0167:004361C6 ADD ESP,BYTE +04----下面的对于注册机源文件已无多大用处

0167:004361C9 XOR ECX,ECX

0167:004361CB CMP EBP,EAX

0167:004361CD POP EDI

0167:004361CE POP ESI

0167:004361CF SETZ CL

0167:004361D2 POP EBP

0167:004361D3 MOV EAX,ECX

0167:004361D5 POP EBX

0167:004361D6 ADD ESP,BYTE +14

0167:004361D9 RET ----返回(什么,你还不知道注册码是多少。拜托,在EDX里啦。你是不是没再看)

.....................................

好了,解说完毕。下面是我的C源代码,写的有些傻,就是一句一句的直译汇编语句(你可别笑,通俗易懂吗)

#include "stdio.h"

#include "string.h"

void main()

{

static char name[100]={0},sn[10]={0};//初始化

int i=0,len;

long sum=0,eax=0,ebx=0,ecx=0,edx=0,esi=0,esitemp=0;

printf("Please Input Your Name:");

gets(name);

len=strlen(name);

for(i=0;i<len;i++)//累加姓名的ASCII码

sum+=name[i];

ebx=sum;

eax=0x104;//算得密文

eax-=ebx;

if(eax<0)

edx=-1;

else

edx=0;

eax^=edx;

eax-=edx;

eax+=0x014c;

edx-=eax;

edx=eax*8;

edx-=eax;

ecx=eax+edx*4;

esi=eax+ecx*2;

esi<<=0x3;

i=5;

esitemp=esi;

while(esitemp)//将密文转为字符串

{

sn[i--]=esitemp%10+'0';

esitemp/=10;

}

if(esi<=999999)//开始处理密文

{

sn[6]=sn[4];//移位(在了解了移位过程后的简化步骤)

sn[8]=sn[5];

sn[5]=sn[3];

sn[3]=sn[2];

sn[2]=sn[1];

eax=ecx=sn[4];//开始计算注册码

eax<<=0x05;

eax-=ecx;

ecx=sn[8];

edx=eax*3;

eax=ecx*5;

eax<<=0x03;

eax-=ecx;

eax-=edx;

if(eax<0)

edx=-1;

else

edx=0;

ecx=eax;

ecx^=edx;

ecx-=edx;

eax=ecx*5;

eax<<=0x03;

eax-=ecx;

ecx=0x09;

if(eax<0)

edx=-1;

else

edx=0;

edx=eax%ecx;

eax/=ecx;

eax=sn[3];

edx+='0';

sn[7]=edx;

edx=eax*3;

edx<<=0x04;

edx-=eax;

eax=sn[5];

ecx=eax*9;

eax=eax+ecx*4;

eax=edx+eax*2;

if(eax<0)

edx=-1;

else

edx=0;

eax^=edx;

eax-=edx;

ecx=eax*9;

eax=eax+ecx*4;

ecx=9;

eax<<=0x01;

if(eax<0)

edx=-1;

else

edx=0;

edx=eax%ecx;

eax/=ecx;

ecx=sn[0];

eax=ecx*3;

eax*=9;

eax<<=0x01;

eax-=ecx;

edx+='0';

sn[4]=edx;

ecx=sn[1];

edx=ecx*8;

edx-=ecx;

edx*=5;

eax-=edx;

if(eax<0)

edx=-1;

else

edx=0;

ecx=eax;

ecx^=edx;

ecx-=edx;

eax=ecx*3;

eax*=9;

eax<<=0x01;

eax-=ecx;

if(eax<0)

edx=-1;

else

edx=0;

}

else//这里是大于999999的处理

{

sn[8]=sn[6];

sn[6]=sn[5];

sn[5]=sn[4];

sn[3]=sn[2];

sn[2]=sn[1];

ecx=eax=sn[6];

ecx<<=0x06;

ecx-=eax;

eax=sn[8];

eax*=9;

eax<<=0x02;

eax-=ecx;

ecx=0x09;

if(eax<0)

edx=-1;

else

edx=0;

eax^=edx;

eax-=edx;

eax*=9;

eax<<=0x02;

if(eax<0)

edx=-1;

else

edx=0;

edx=eax%ecx;

eax/=ecx;

edx+='0';

sn[7]=edx;

eax=sn[4];

eax+=0x20;

edx=eax*8;

edx-=eax;

eax=eax+edx*4;

ecx=eax*3;

eax=sn[3];

edx=eax*5;

edx<<=0x03;

edx-=eax;

eax=ecx+edx*2;

if(eax<0)

edx=-1;

else

edx=0;

eax^=edx;

eax-=edx;

ecx=eax*8;

ecx-=eax;

eax=eax+ecx*4;

ecx=0x09;

eax*=3;

if(eax<0)

edx=-1;

else

edx=0;

edx=eax%ecx;

eax/=ecx;

eax=sn[0];

edx+='0';

sn[4]=edx;

edx=eax*8;

edx-=eax;

eax=eax+edx*4;

edx=sn[1];

ecx=edx;

ecx<<=0x04;

ecx+=edx;

eax<<=0x01;

ecx*=5;

eax-=ecx;

if(eax<0)

edx=-1;

else

edx=0;

eax^=edx;

eax-=edx;

edx=eax*8;

edx-=eax;

eax=eax+edx*4;

eax<<=0x01;

if(eax<0)

edx=-1;

else

edx=0;

}

ecx=0x09;//这一段为大于999999和小于999999都要处理的部分(看一下汇编源程序就明白了)

edx=eax%ecx;

eax/=ecx;

edx+='0';

sn[1]=edx;

printf("Your Serial Numbers:%s\n",sn);//当然是梦寐以求的啦!

}

为了能够方便的输入中文,可用用VC作了一个图形界面的KeyGen(可能有点大材小用了^_^)。

Note:用户名别输的太长,否则算出的注册码不正确(水平有限?_?)。

写这片文只是希望能启到抛砖引玉的作用,用C直译汇编语言(很傻不过很有用)。

谢谢观赏(初次露面,混个脸熟o_o)

(出处:赢政天下整理收藏)

相关文章:

·语音界面2.0算法分析及注册机源码!

·侠客系统修改器1.21破解手记--算法分析

·中文拨号上网计时计费器 V4.12注册算法分析

·ClockWise 3.22e注册码算法分析

·CoolClock V1.02注册算法分析

·Directory Scanner v1.5 注册算法分析

·Disk Chief 1.2 简单注册算法分析

·EffeTech HTTP Sniffer 3.2注册算法分析

·eLib2.01算法分析

·EZ MP3 Recorder 1.15 注册算法分析

相关软件:

→ 特别推荐

→ 热点TOP10

关于我们 |

帮助(?)

| 广告服务 |

版权声明 |

商业合作 |

发展历程 |

加盟我们 |

联系我们

Copyright © 1999-2003

winzheng.com All Rights Reserved.

繁体版:由华琦数码技术提供

Powered

by:MeSky.Net

2003-2004 年,宽带刚刚普及,下载站的文章区是许多人学电脑的第一课堂。
🕰 → 🤖 从那时到现在

当年一篇教程能让一台电脑焕然一新;今天的效率工具换成了 AI。 想知道当下最可靠的 AI 模型怎么选?看 赢政指数——我们用了 28 年的选软件严谨,现在用来评测大模型。

档案性质声明:本页为赢政天下(1998-2011)老文章的历史档案复原, 内容反映当年发表时的原貌——包括当年的技术表述、软件版本与观点,部分方法在今天已不适用或不合规,仅作互联网历史记录与研究用途, 不提供任何形式的下载。原始数据经由公共网络存档(Internet Archive)复原。发现问题请联系我们
← 返回老文章档案 · 软件史档案馆 · 赢政天下站史