第13课 注册算法进阶.docx

上传人:b****5 文档编号:6659215 上传时间:2023-01-08 格式:DOCX 页数:20 大小:386.81KB
下载 相关 举报
第13课 注册算法进阶.docx_第1页
第1页 / 共20页
第13课 注册算法进阶.docx_第2页
第2页 / 共20页
第13课 注册算法进阶.docx_第3页
第3页 / 共20页
第13课 注册算法进阶.docx_第4页
第4页 / 共20页
第13课 注册算法进阶.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

第13课 注册算法进阶.docx

《第13课 注册算法进阶.docx》由会员分享,可在线阅读,更多相关《第13课 注册算法进阶.docx(20页珍藏版)》请在冰豆网上搜索。

第13课 注册算法进阶.docx

第13课注册算法进阶

第13课注册算法进阶

[例1]目标程序:

easy1.exe。

0167:

004014FC8D45FCLEAEAX,[EBP-04]

0167:

004014FFE814040000CALL00401918

0167:

004015048B5594MOVEDX,[EBP-6C]

0167:

004015070FBE0C10MOVSXECX,BYTE[EAX+EDX]//依次取name中的字符

0167:

0040150B014DA0ADD[EBP-60],ECX//累加到ebp-60中

0167:

0040150EFF4594INCDWORD[EBP-6C]//计数

0167:

004015118D45FCLEAEAX,[EBP-04]

0167:

00401514E8DDE10000CALL0040F6F6

0167:

004015193B4594CMPEAX,[EBP-6C]

0167:

0040151C7FDEJG004014FC//如果没取完,就跳转,形成循环

上面程序的功能是将所有输入的name字符累加起来,以我输入的”TAE”为例,程序每次取一个字符然后将他们相加,就像这样:

”T”的ascii码为0x54,”A”的ascii码为0x41,”E”的ascii码为0x45,”!

”的ascii码为0x21,所以0x54+0x41+0x45+0x21=0xFB,结果就是0xFB,现在还没有结束,请看下面程序对这个0xFB的操作:

0167:

0040151E6955A032130000IMULEDX,[EBP-60],1332

0167:

004015258955A0MOV[EBP-60],EDX

0167:

00401528694DA032130000IMULECX,[EBP-60],1332

0167:

0040152F894DA0MOV[EBP-60],ECX

0167:

004015326945A032130000IMULEAX,[EBP-60],1332

0167:

004015398945A0MOV[EBP-60],EAX

0167:

0040153C8145A04A0F0000ADDDWORD[EBP-60],0F4A

大家能看懂上面的程序吗?

其实就是用0xFB连续乘三次0x1332,然后用这个结果加上0x0F4A,经过这样的计算就得到了你的注册码了

0167:

004015438B5598MOVEDX,[EBP-68]

0167:

004015463B55A0CMPEDX,[EBP-60]//”ebp-60”中保存正确注册码

0167:

004015490F8571010000JNZNEAR004016C0//判断注册码是否正确,不同的话就跳到出错提示了

0167:

0040154F66C745C05000MOVWORD[EBP-40],50

0167:

004015558D45E8LEAEAX,[EBP-18]

0167:

004015588B55A0MOVEDX,[EBP-60]

我得到的注册码:

Name:

TAE!

Sn:

-1861903902

下面给出easy1的keymake的算法注册机(keygen.rek):

.const

.data

szHomePagedb"",0

szEmaildb"mailto:

fpx425@",0

szErrMessdb"请输入姓名!

",0

szBufferdb50dup(0)

szHexdb"%ld",0

.code

movesi,eax

invokelstrlen,esi

movecx,eax

xoredx,edx

xorebx,ebx

xoreax,eax

n1:

movbl,byteptr[esi+eax]

addedx,ebx

inceax

cmpecx,eax

jgn1

moveax,edx

imuleax,eax,1332h

imuleax,eax,1332h

imuleax,eax,1332h

addeax,0F4Ah

invokewsprintf,addrszBuffer,addrszHex,eax

leaeax,szBuffer

注意其中红字标出的部分。

[例2]目标程序nullz的第1、2关。

大家看到了吧,是分三六九等的,一起来试试,先来个最简单的吧!

方法一:

工具:

WinHex

过程:

用前面教过的方法,一试就出来,不信请看

看到了吗?

qJT62aWfviq0P57JGs2FelQkX这个就是注册码,什么?

不信?

我有证据,请看!

还有一种方法就是直接用W32DASM反汇编即可!

如图:

是不是更简单?

呵呵,好的,我们进入下一层!

开始,如图:

出现错误提示?

肯定的了,让我们来一步步分析它,这次光用WINHEX和W32DASM可就不管用了,要动用“动态分析软件”了,例如使用ollydbg。

过程:

:

00401AE48D4C247Cleaecx,dwordptr[esp+7C]

:

00401AE86A33push00000033

:

00401AEA51pushecx

:

00401AEB68ED030000push000003ED

:

00401AF08BCBmovecx,ebx

*ReferenceTo:

MFC42.Ordinal:

0C1A,Ord:

0C1Ah

|

:

00401AF2E8E7100000Call00402BDE

:

00401AF78D542414leaedx,dwordptr[esp+14]

:

00401AFB52pushedx

*ReferenceTo:

KERNEL32.lstrlenA,Ord:

02A1h

|

:

00401AFCFF1500404000Calldwordptr[00404000]

:

00401B028BF0movesi,eax

:

00401B0483FE05cmpesi,00000005-------------比较用户名是否大于5位

:

00401B077311jnb00401B1A  -------------小于就出现错误信息

:

00401B096A40push00000040

*PossibleStringDataReffromDataObj->"CrackMe"

|

:

00401B0B6804514000push00405104

*PossibleStringDataReffromDataObj->"UserNamemusthaveatleast5"

->"characters."

|

:

00401B1068D8504000push004050D8

:

00401B15E9BA000000jmp00401BD4

*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:

|:

00401B07(C)

|

:

00401B1AB801000000moveax,00000001----给EAX赋值为1,做为计数器

:

00401B1F33FFxoredi,edi------------EDI清零,做储数器

:

00401B213BF0cmpesi,eax

:

00401B237211jb00401B36

*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:

|:

00401B34(C)

|

:

00401B250FBE4C0414movsxecx,byteptr[esp+eax+14]---------

提取你输入用户名的第二位的十六进制

:

00401B2A03CFaddecx,edi

                  ECX=ECX+EDI

:

00401B2C0FAFC8imulecx,eax

                  ECX=ECX*EAX

:

00401B2F40inceax

                  EAX+1

:

00401B308BF9movedi,ecx

                   EDI=ECX

:

00401B323BC6cmpeax,esi 

:

00401B3476EFjbe00401B25  形成循环

以我输入的名字lllufh为例

l的十六进制6C、u的十六进制75、f的十六进制66、h的十六进制68

计算过程如下:

初始化:

EDX=0EAX=1

第一次循环:

1.ecx=6c

2.ecx=ecx+edi=6c

3.ecx=ecx*eax=6c

4.eax=eax+1=2

5.edi=ecx=6c

第二次循环:

1.ecx=6c

2.ecx=ecx+edi=d8

3.ecx=ecx*eax=1b0

4.eax=eax+1=3

5.edi=ecx=1b0

第三次循环:

1.ecx=75

2.ecx=ecx+edi=225

3.ecx=ecx*eax=66f

4.eax=eax+1=4

5.edi=ecx=66f

第四次循环:

1.ecx=66

2.ecx=ecx+edi=6d5

3.ecx=ecx*eax=1b54

4.eax=eax+1=5

5.edi=ecx=1b54

第五次循环:

1.ecx=68

2.ecx=ecx+edi=1bbc

3.ecx=ecx*eax=8aac

4.eax=eax+1=6

5.edi=ecx=8aac

第六次循环:

1.ecx=0

2.ecx=ecx+edi=8aac

3.ecx=ecx*eax=34008

4.eax=eax+1=7

5.edi=ecx=34008

循环结束.

*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:

|:

00401B23(C)

|

:

00401B3633C9xorecx,ecx--------ecx清零做计数器

:

00401B3885F6testesi,esi

:

00401B3A7620jbe00401B5C

*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:

|:

00401B5A(C)

|第二次计算开始。

:

00401B3C0FBE6C0C14movsxebp,byteptr[esp+ecx+14]

提取用户名的第一位

:

00401B418BC7moveax,edi

                 //eax=edi

:

00401B4333D2xoredx,edx

//edx清零

:

00401B45F7F5divebp

                 //eax=eax/ebp商进EAX,余数进EDX

:

00401B4733D2xoredx,edx

//edx清零

:

00401B49BD0A000000movebp,0000000A

//ebp=0xA

:

00401B4EF7F5divebp

//eax=ex/ebp商进EAX,余数进EDX

:

00401B5080C230adddl,30

//edx=edx+0x30

:

00401B5388540C48movbyteptr[esp+ecx+48],dl

//把EDX的值赋到字符串中

:

00401B5741incecx

ecx=ecx+1

:

00401B583BCEcmpecx,esi

:

00401B5A72E0jb00401B3C形成循环

接着以我输入的名字lllufh为例继续计算:

第一次循环:

1.ebp=6c

2.eax=edi=34008

3.edx=0

4.eax=eax/ebp=7b4edx=18

5.edx=0

6.ebp=a

7.eax=eax/ebp=c5edx=02

8.edx=02+30=32

9.[esp+ecx+48]=32

10.ecx=ecx+1=1

因为我输入的用户名的都三位都一样,所以第二次、第三次循环的值也都是一样的

第四次循环:

1.ebp=75

2.eax=edi=34008

3.edx=0

4.eax=eax/ebp=71cedx=3c

5.edx=0

6.ebp=a

7.eax=eax/ebp=b6edx=0

8.edx=0+30=30

9.[esp+ecx+48]=30

10.ecx=ecx+1=4

第五次循环:

1.ebp=66

2.eax=edi=34008

3.edx=0

4.eax=eax/ebp=828edx=18

5.edx=0

6.ebp=a

7.eax=eax/ebp=0edx=08

8.edx=8+30=38

9.[esp+ecx+48]=38

11.ecx=ecx+1=5

第六次循环:

1.ebp=68

2.eax=edi=34008

3.edx=0

4.eax=eax/ebp=800edx=08

5.edx=0

6.ebp=a

7.eax=eax/ebp=ccedx=08

8.edx=8+30=38

9.[esp+ecx+48]=38

11.ecx=ecx+1=6

跳出循环。

依次把六次循环的余数提出,为222088,这就是注册码喽!

晕,又不信,自己看图吧!

*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:

|:

00401B3A(C)

|

:

00401B5C8D542448leaedx,dwordptr[esp+48]-----这里是真码

:

00401B608D44247Cleaeax,dwordptr[esp+7C]----这里是假码

:

00401B6452pushedx

:

00401B6550pusheax

*ReferenceTo:

KERNEL32.lstrcmpA,Ord:

0295h

|

:

00401B66FF1508404000Calldwordptr[00404008]

:

00401B6C85C0testeax,eax

:

00401B6E7550jne00401BC0

:

00401B706870434000push00404370

:

00401B758D4C2414leaecx,dwordptr[esp+14]

*ReferenceTo:

MFC42.Ordinal:

0219,Ord:

0219h

|

:

00401B79E85A100000Call00402BD8

*PossibleStringDataReffromDataObj->"

DifficultyLEVEL-2Completed!

"

下面给出nullz的第2关的keymake的算法注册机(keygen.rek):

.const

.data

szHomePagedb"",0

szEmaildb"mailto:

fpx425@",0

szErrMessdb"请输入姓名!

",0

szBufferdb50dup(0)

szHexdb"%d",0

lendd0

.code

movesi,eax

invokelstrlen,esi

movlen,eax

moveax,1

xoredi,edi

n1:

movsxecx,byteptr[esi+eax]

addecx,edi

imulecx,eax

inceax

movedi,ecx

cmpeax,len

jben1

xorecx,ecx

n2:

movsxebp,byteptr[esi+ecx]

moveax,edi

xoredx,edx

divebp

xoredx,edx

movebp,0Ah

divebp

adddl,30h

movbyteptr[szBuffer+ecx],dl

incecx

cmpecx,len

jbn2

leaeax,szBuffer

以上基本上来自程序的反汇编代码:

注意其中的红字部分,我第一次编译没通过,就是因为数字后面没加h。

[例3]目标程序nullz的第3关。

该第三阶段了,可是一个比上一个要难哟,睁大眼睛仔细看呀!

什么?

和第二个一样?

别急呀,外表一样,芯可不一样喽,跟我一步步来吧!

:

00401C728D4C2414leaecx,dwordptr[esp+14]

:

00401C7651pushecx

:

00401C7768ED030000push000003ED

:

00401C7C8BCFmovecx,edi

*ReferenceTo:

MFC42.Ordinal:

0C19,Ord:

0C19h

|

:

00401C7EE8670F0000Call00402BEA

:

00401C838B6C2418movebp,dwordptr[esp+18]

ebp=0x650088以后计算用

:

00401C878B55F8movedx,dwordptr[ebp-08]

为用户名个数

:

00401C8A83FA05cmpedx,00000005

进行比较

:

00401C8D7D11jge00401CA0

不能小于5位

:

00401C8F6A40push00000040

*PossibleStringDataReffromDataObj->"CrackMe"

|

:

00401C916804514000push00405104

*PossibleStringDataReffromDataObj->"UserNamemusthaveatleast5"

->"characters."

|

:

00401C9668D8504000push004050D8

:

00401C9BE9E2000000jmp00401D82

*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:

|:

00401C8D(C)

|

:

00401CA033C0xoreax,eax

//eax清零

:

00401CA23BD3cmpedx,ebx

//比较是否输入注册码

:

00401CA47E3Cjle00401CE2

//没有则出错

:

00401CA6B901000000movecx,00000001

//ecx=1

:

00401CAB33FFxoredi,edi

//edi清零

:

00401CAD2BCDsubecx,ebp

//ecx=ecx-ebp

:

00401CAF894C241Cmovdwordptr[esp+1C],ecx

//把ecx的值放入[esp+1c]中

*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:

|:

00401CDA(C)

|

计算注册码过程开始:

:

00401CB30FBE5C0500movsxebx,byteptr[ebp+eax]

//依次提取用户名第一位的十六进制

:

00401CB88D4C0500leaecx,dwordptr[ebp+eax]

//ecx=ebp+eax

:

00401CBC03F3addesi,ebx

//esi=esi+ebx

:

00401CBE8BD8movebx,eax

//ebx=ebx+eax

:

00401CC0C1E308shlebx,08

//ebx左移三位

:

00401CC333F3xoresi,ebx

//esi=esixorebx

:

00401CC58B5C241Cmovebx,dwordptr[esp+1C]

//ebx=[esp+1c]

:

00401CC903D9addebx,ecx

//ebx=ebx+ecx

:

00401CCB8BCFmovecx,edi

//ecx=edi

:

00401CCD0FAFF3imulesi,ebx

//esi=esi*ebx

:

00401CD0F7D1notecx

//ecx取反

:

00401CD20FAFF1imulesi,ecx

//esi=esi*ecx

:

00401CD540inceax

//eax=eax+1

:

00401CD603FAaddedi,edx

//edi=edi+edx

:

00401CD83BC2cmpeax,edx

:

00401CDA7CD7jl00401CB3

形成循环

 

:

00401CDC8B7C2420movedi,dwordptr[esp+20]

:

00401CE033DBxorebx,ebx

*Referencedbya(U)nconditionalor(C)onditionalJumpatAddress:

|:

00401CA4(C)

|

:

00401CE256pushesi

:

00401CE38D542414leaedx,dwordptr[esp+14]

*PossibleStringDataReffromDataObj->"%lu"

|

:

00401CE7682C514000push0040512C

:

00401CEC52pushedx

*ReferenceTo:

MFC42.Ordinal:

0B02,Ord:

0B02h

|

:

00401CEDE8F20E0000Call00402BE4

:

00401CF28B74241Cmovesi,dwordptr[esp+1C]---------这里就是真码了

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1