文章作者:qduwg
软件介绍:该软件可以在不同浏览器(IE,NetScape等)之间转换你的收藏夹(书签),里面有你常用的网络地址。并且可以产生非常专
业的层叠菜单,还可把产生的菜单发布到网络上供随时查看。软件来自《电脑爱好者2003光盘》。
工具:Softice,PEID
引子:今天又安装调试了一个软件,用PEID查看,得知这个软件是VB写的,无壳。试用期20天,过期则有功能限制(启动时有NAG,只可
以生成40个菜单项)。启动程序,打开HELP菜单,单击Register,输入用户名iloveu,注意用户名必须大于6位。激活码1234-5678。调出
SOFTICE,下断点bpxhmemcpy,F5退出,点击Register按钮,被拦截。7次F12,换F10跟踪,很快就来到如下代码处。
0046D3F4.FF90A0000000CALLDWORDPTRDS:[EAX+A0]
0046D3FA.DBE2FCLEX//我们回到这里。
0046D3FC.898538FFFFFFMOVDWORDPTRSS:[EBP-C8],EAX
0046D402.83BD38FFFFFF>CMPDWORDPTRSS:[EBP-C8],0
0046D409.7D26JGESHORTBOOKEXPO.0046D431//自然跳。
***省略几行****
0046D4D3.DBE2FCLEX
0046D4D5.898528FFFFFFMOVDWORDPTRSS:[EBP-D8],EAX
0046D4DB.83BD28FFFFFF>CMPDWORDPTRSS:[EBP-D8],0
0046D4E2.7D26JGESHORTBOOKEXPO.0046D50A//自然跳。
***省略几行****
0046D50A>C785F8FEFFFF>MOVDWORDPTRSS:[EBP-108],0//从这里正式开始。
0046D514>8B45D4MOVEAX,DWORDPTRSS:[EBP-2C]//第一部分注册码"1234"地址送EAX。
0046D517.50PUSHEAX
0046D518.8B4DD0MOVECX,DWORDPTRSS:[EBP-30]//第二部分注册码地址"5678"送ECX。
0046D51B.51PUSHECX
0046D51C.FF157C104000CALLDWORDPTRDS:[<&MSVBVM60.__vbaStrCa>//串接两部分注册码。
0046D522.8BD0MOVEDX,EAX
0046D524.8D4DD8LEAECX,DWORDPTRSS:[EBP-28]
***省略几行****
0046D595.FF92A0000000CALLDWORDPTRDS:[EDX+A0]
0046D59B.DBE2FCLEX
0046D59D.898540FFFFFFMOVDWORDPTRSS:[EBP-C0],EAX
0046D5A3.83BD40FFFFFF>CMPDWORDPTRSS:[EBP-C0],0
0046D5AA.7D26JGESHORTBOOKEXPO.0046D5D2//此处自然跳。
***省略几行****
0046D5FB.8D8D48FFFFFFLEAECX,DWORDPTRSS:[EBP-B8]
0046D601.51PUSHECX
0046D602.8D55D0LEAEDX,DWORDPTRSS:[EBP-30]//用户名地址送EDX。
0046D605.52PUSHEDX
0046D606.8B4508MOVEAX,DWORDPTRSS:[EBP+8]
0046D609.8B08MOVECX,DWORDPTRDS:[EAX]
0046D60B.8B5508MOVEDX,DWORDPTRSS:[EBP+8]
0046D60E.52PUSHEDX
0046D60F.FF91FC060000CALLDWORDPTRDS:[ECX+6FC]
0046D615.89853CFFFFFFMOVDWORDPTRSS:[EBP-C4],EAX
0046D61B.83BD3CFFFFFF>CMPDWORDPTRSS:[EBP-C4],0
0046D622.7D23JGESHORTBOOKEXPO.0046D647//此处自然跳。
***省略几行****
0046D647>C785F0FEFFFF>MOVDWORDPTRSS:[EBP-110],0
0046D651>66:8B9548FFFF>MOVDX,WORDPTRSS:[EBP-B8]
0046D658.66:899538FFFF>MOVWORDPTRSS:[EBP-C8],DX
0046D65F.8D4DD0LEAECX,DWORDPTRSS:[EBP-30]
0046D662.FF1508134000CALLDWORDPTRDS:[<&MSVBVM60.__vbaFreeS>
0046D668.8D4DC8LEAECX,DWORDPTRSS:[EBP-38]
0046D66B.FF1504134000CALLDWORDPTRDS:[<&MSVBVM60.__vbaFreeO>
0046D671.0FBF8538FFFFF>MOVSXEAX,WORDPTRSS:[EBP-C8]
0046D678.85C0TESTEAX,EAX
0046D67A.0F8400010000JEBOOKEXPO.0046D780//此处自然跳。否则下面提示非法激活码。
0046D680.C745FC050000>MOVDWORDPTRSS:[EBP-4],5
0046D687.C74584040002>MOVDWORDPTRSS:[EBP-7C],80020004
0046D68E.C7857CFFFFFF>MOVDWORDPTRSS:[EBP-84],0A
0046D698.C74594040002>MOVDWORDPTRSS:[EBP-6C],80020004
0046D69F.C7458C0A0000>MOVDWORDPTRSS:[EBP-74],0A
0046D6A6.C78574FFFFFF>MOVDWORDPTRSS:[EBP-8C],BOOKEXPO.00420>;UNICODE"IllegalActivationCode"
0046D6B0.C7856CFFFFFF>MOVDWORDPTRSS:[EBP-94],8
0046D6BA.8D956CFFFFFFLEAEDX,DWORDPTRSS:[EBP-94]
***省略多行****
0046D780>C745FC060000>MOVDWORDPTRSS:[EBP-4],6
0046D787.8B4508MOVEAX,DWORDPTRSS:[EBP+8]
***省略多行****
0046D7C2.898540FFFFFFMOVDWORDPTRSS:[EBP-C0],EAX
0046D7C8.83BD40FFFFFF>CMPDWORDPTRSS:[EBP-C0],0
0046D7CF.7D26JGESHORTBOOKEXPO.0046D7F7//此处自然跳。
***省略多行****
0046D7F7>C785ECFEFFFF>MOVDWORDPTRSS:[EBP-114],0
0046D801>8B4DD4MOVECX,DWORDPTRSS:[EBP-2C]
0046D804.898D0CFFFFFFMOVDWORDPTRSS:[EBP-F4],ECX
0046D80A.C745D4000000>MOVDWORDPTRSS:[EBP-2C],0
0046D811.8B950CFFFFFFMOVEDX,DWORDPTRSS:[EBP-F4]//用户名地址送EDX。
0046D817.8D4DD0LEAECX,DWORDPTRSS:[EBP-30]
0046D81A.FF15CC124000CALLDWORDPTRDS:[<&MSVBVM60.__vbaStrMo>
0046D820.8D55CCLEAEDX,DWORDPTRSS:[EBP-34]
0046D823.52PUSHEDX
0046D824.8D45D0LEAEAX,DWORDPTRSS:[EBP-30]
0046D827.50PUSHEAX
0046D828.8B4D08MOVECX,DWORDPTRSS:[EBP+8]
0046D82B.8B11MOVEDX,DWORDPTRDS:[ECX]
0046D82D.8B4508MOVEAX,DWORDPTRSS:[EBP+8]
0046D830.50PUSHEAX
0046D831.FF92F8060000CALLDWORDPTRDS:[EDX+6F8]//这个CALL重要,就是产生注册码的地方。CALL40AE0F。后面分析
。(*)
0046D837.89853CFFFFFFMOVDWORDPTRSS:[EBP-C4],EAX
0046D83D.83BD3CFFFFFF>CMPDWORDPTRSS:[EBP-C4],0
0046D844.7D23JGESHORTBOOKEXPO.0046D869
***省略多行****
0046D911>8B45CCMOVEAX,DWORDPTRSS:[EBP-34]//真码地址送EAX。
0046D914.50PUSHEAX
0046D915.8B4DD8MOVECX,DWORDPTRSS:[EBP-28]//假码地址送ECX。
0046D918.51PUSHECX
0046D919.FF1544114000CALLDWORDPTRDS:[<&MSVBVM60.__vbaStrCm>//很明显进行串比较啦。
0046D91F.F7D8NEGEAX
0046D921.1BC0SBBEAX,EAX
0046D923.40INCEAX
***省略多行****
0046D950.0FBF8D30FFFFF>MOVSXECX,WORDPTRSS:[EBP-D0]
0046D957.85C9TESTECX,ECX//如果注册码正确,则ECX=FFFFFFFF
0046D959.0F84C6030000JEBOOKEXPO.0046DD25//这个地方不跳则OK。
***下面是注册成功的感谢信息*******
0046D993.68EC054200PUSHBOOKEXPO.004205EC;UNICODE"ThankYouforregisteringBookmark
Exporter."
0046D998.6834454100PUSHBOOKEXPO.00414534"
0046D99D.FF157C104000CALLDWORDPTRDS:[<&MSVBVM60.__vbaStrCa>
0046D9A3.8BD0MOVEDX,EAX
0046D9A5.8D4DD4LEAECX,DWORDPTRSS:[EBP-2C]
0046D9A8.FF15CC124000CALLDWORDPTRDS:[<&MSVBVM60.__vbaStrMo>
0046D9AE.50PUSHEAX
0046D9AF.684C064200PUSHBOOKEXPO.0042064C;UNICODE"Alllimitationsareremoved.Enjoy."
0046D9B4.FF157C104000CALLDWORDPTRDS:[<&MSVBVM60.__vbaStrCa>
===================================================================================================
我们跟进前面(*)处的函数看看:
0040AE0F.E97C390600JMPBOOKEXPO.0046E790//其实这是跳转,真正的函数在下面。
0046E790>55PUSHEBP
0046E791.8BECMOVEBP,ESP
0046E793.83EC0CSUBESP,0C
***省略多行****
0046E7DB.8B03MOVEAX,DWORDPTRDS:[EBX]//取用户名地址并进栈。
0046E7DD.50PUSHEAX
0046E7DE.897DD8MOVDWORDPTRSS:[EBP-28],EDI
0046E7E1.897DD4MOVDWORDPTRSS:[EBP-2C],EDI
0046E7E4.897DC4MOVDWORDPTRSS:[EBP-3C],EDI
0046E7E7.897DB4MOVDWORDPTRSS:[EBP-4C],EDI
0046E7EA.FFD6CALLESI;<&MSVBVM60.__vbaLenBstr>//取用户名串长。
0046E7EC.83F806CMPEAX,6//与6比较,如果小于则下面跳走,则错。
0046E7EF.0F8CA7010000JLBOOKEXPO.0046E99C
0046E7F5.8B0BMOVECX,DWORDPTRDS:[EBX]//取用户名地址送ECX。
0046E7F7.6808074200PUSHBOOKEXPO.00420708;UNICODE"lM"//字符串"lM"地址进栈。这里是小写的L,不是一。
0046E7FC.51PUSHECX
0046E7FD.897DDCMOVDWORDPTRSS:[EBP-24],EDI
0046E800.C745E030E7F5>MOVDWORDPTRSS:[EBP-20],40F5E730
0046E807.FF157C104000CALLDWORDPTRDS:[<&MSVBVM60.__vbaStrCa>//把"lM"串接在用户名前面。比如形成"lMiloveu"的
形式。
0046E80D.8B3DCC124000MOVEDI,DWORDPTRDS:[<&MSVBVM60.__vbaSt>
0046E813.8BD0MOVEDX,EAX
0046E815.8BCBMOVECX,EBX
0046E817.FFD7CALLEDI
0046E819.8B13MOVEDX,DWORDPTRDS:[EBX]//新串地址送EDX。
0046E81B.52PUSHEDX
0046E81C.FFD6CALLESI//取新串长度。
0046E81E.894580MOVDWORDPTRSS:[EBP-80],EAX//串长送:[EBP-80]保存。下面循环用到。
0046E821.BE03000000MOVESI,3//ESI初始化为3。下面循环开始,总共循环6次。
0046E826>3B7580CMPESI,DWORDPTRSS:[EBP-80]//比较ESI和串长。
0046E829.0F8FF3000000JGBOOKEXPO.0046E922//如果大于则说明结束运算。否则继续循环。
0046E82F.8B0BMOVECX,DWORDPTRDS:[EBX]
0046E831.8D45C4LEAEAX,DWORDPTRSS:[EBP-3C]
0046E834.50PUSHEAX
0046E835.56PUSHESI
0046E836.51PUSHECX
0046E837.C745CC010000>MOVDWORDPTRSS:[EBP-34],1
0046E83E.C745C4020000>MOVDWORDPTRSS:[EBP-3C],2
0046E845.FF1514114000CALLDWORDPTRDS:[<&MSVBVM60.#631>];MSVBVM60.rtcMidCharBstr//依次取出新用户名后6位
。顺序为i,l,o,v,e,u.
0046E84B.8BD0MOVEDX,EAX
0046E84D.8D4DD8LEAECX,DWORDPTRSS:[EBP-28]
0046E850.FFD7CALLEDI
0046E852.50PUSHEAX
0046E853.FF1558104000CALLDWORDPTRDS:[<&MSVBVM60.#516>];MSVBVM60.rtcAnsiValueBstr
0046E859.8B0BMOVECX,DWORDPTRDS:[EBX]
0046E85B.894590MOVDWORDPTRSS:[EBP-70],EAX//用户名字符送内存保存。
0046E85E.8BC6MOVEAX,ESI//前面ESI的值送EAX,开始是3。
0046E860.8D55B4LEAEDX,DWORDPTRSS:[EBP-4C]
0046E863.83E802SUBEAX,2//EAX减2,得1。
0046E866.52PUSHEDX
0046E867.0F8097010000JOBOOKEXPO.0046EA04
0046E86D.50PUSHEAX
0046E86E.51PUSHECX
0046E86F.C745BC010000>MOVDWORDPTRSS:[EBP-44],1
0046E876.C745B4020000>MOVDWORDPTRSS:[EBP-4C],2
0046E87D.FF1514114000CALLDWORDPTRDS:[<&MSVBVM60.#631>];MSVBVM60.rtcMidCharBstr//依次取新用户名前6位。
顺序是l,M,i,l,o,v.
0046E883.8BD0MOVEDX,EAX
0046E885.8D4DD4LEAECX,DWORDPTRSS:[EBP-2C]
0046E888.FFD7CALLEDI
0046E88A.50PUSHEAX
0046E88B.FF1558104000CALLDWORDPTRDS:[<&MSVBVM60.#516>];MSVBVM60.rtcAnsiValueBstr
0046E891.DD45DCFLDQWORDPTRSS:[EBP-24]//这里是浮点取数指令,第一次是把一个[EBP-24]处的常数
89714送ST(0)寄存器。以后都是累加和。
0046E894.89458CMOVDWORDPTRSS:[EBP-74],EAX
0046E897.FF15A8124000CALLDWORDPTRDS:[<&MSVBVM60.__vbaFpI4>>;MSVBVM60.__vbaFpI4//把ST(0)内的浮点数形式的值
转换为16进制后送EAX。
0046E89D.99CDQ//扩展到EDX。
0046E89E.F7FEIDIVESI//EAX=EAX/ESI,余数送EDX。ESI初始值是3。然后依次是4,
5,6,7。
0046E8A0.0FBF458CMOVSXEAX,WORDPTRSS:[EBP-74]//前6位字符依次送EAX。当然是每次循环各送一个。
0046E8A4.0FBF4D90MOVSXECX,WORDPTRSS:[EBP-70]//后6位字符依次送ECX。
0046E8A8.83C201ADDEDX,1//EDX加1。
0046E8AB.0F8053010000JOBOOKEXPO.0046EA04
0046E8B1.0FAFC1IMULEAX,ECX//EAX=EAX*ECX。//间隔一位的两个字符相乘,结果送EAX。
0046E8B4.0F804A010000JOBOOKEXPO.0046EA04
0046E8BA.0FAFD0IMULEDX,EAX//EDX=EDX*EAX。这里每次EDX值不同,取决于前面所做的除法
运算结果。
0046E8BD.0F8041010000JOBOOKEXPO.0046EA04
0046E8C3.899574FFFFFFMOVDWORDPTRSS:[EBP-8C],EDX//EDX送内存保存。
0046E8C9.8D55D4LEAEDX,DWORDPTRSS:[EBP-2C]
0046E8CC.DB8574FFFFFFFILDDWORDPTRSS:[EBP-8C]//这个浮点指令取刚才保存的EDX值,但是在ST(0)内是显示
的十进制
0046E8D2.52PUSHEDX
0046E8D3.DD9D6CFFFFFFFSTPQWORDPTRSS:[EBP-94]//把刚才这个结果变为浮点数送另一位置:[EBP-94]
0046E8D9.DD856CFFFFFFFLDQWORDPTRSS:[EBP-94]//再次取回刚才这个数。
0046E8DF.DC45DCFADDQWORDPTRSS:[EBP-24]//与前面:[EBP-24]保存的浮点数相加。
0046E8E2.DD5DDCFSTPQWORDPTRSS:[EBP-24]//相加的结果送回:[EBP-24]内保存。下次循环在46E891处
的指令用到这个值。
0046E8E5.DFE0FSTSWAX//把异常字保存在AX。
0046E8E7.A80DTESTAL,0D//测试是否发生异常。
0046E8E9.0F8510010000JNZBOOKEXPO.0046E9FF
***省去多行*****
0046E90B.B801000000MOVEAX,1//EAX=1。
0046E910.83C418ADDESP,18
0046E913.03C6ADDEAX,ESI//EAX=EAX+ESI。
0046E915.0F80E9000000JOBOOKEXPO.0046EA04
0046E91B.8BF0MOVESI,EAX//EAX的值送ESI,ESI递增,准备下次循环用。
0046E91D.^E904FFFFFFJMPBOOKEXPO.0046E826//循环上去。
上面如果结束循环则跳到这里来。
0046E922>8B1D8C114000MOVEBX,DWORDPTRDS:[<&MSVBVM60.__vbaSt>
0046E928>8B45E0MOVEAX,DWORDPTRSS:[EBP-20]//得到16进制形式的浮点数结果的高4字节送EAX,低4字节送
ECX。
0046E92B.8B4DDCMOVECX,DWORDPTRSS:[EBP-24]
0046E92E.50PUSHEAX
0046E92F.51PUSHECX
0046E930.FFD3CALLEBX//转换为16进制整数。
0046E932.8BD0MOVEDX,EAX
0046E934.8D4DD8LEAECX,DWORDPTRSS:[EBP-28]
0046E937.FFD7CALLEDI//转化为字符串。
0046E939.50PUSHEAX
0046E93A.FF153C104000CALLDWORDPTRDS:[<&MSVBVM60.__vbaLenBs>//取得到的注册码串长。
0046E940.33D2XOREDX,EDX//EDX清0。
0046E942.83F808CMPEAX,8//放在EAX内的串长与8比较。
0046E945.0F9CC2SETLDL//如果小于8则DL置1,否则保持原来的0。
0046E948.F7DANEGEDX//EDX求反。
0046E94A.8D4DD8LEAECX,DWORDPTRSS:[EBP-28]
0046E94D.8BF2MOVESI,EDX//EDX送ESI。
0046E94F.FF1508134000CALLDWORDPTRDS:[<&MSVBVM60.__vbaFreeS>
0046E955.66:85F6TESTSI,SI//判断SI是否为0。
0046E958.7418JESHORTBOOKEXPO.0046E972//如果是0则跳走。否则进行下面的工作。
0046E95A.DD45DCFLDQWORDPTRSS:[EBP-24]//取:[EBP-24]值送EAX。
0046E95D.DC0D10314000FMULQWORDPTRDS:[403110]//与:[403110]内的浮点数形式的常数'7'相乘。
0046E963.DD5DDCFSTPQWORDPTRSS:[EBP-24]//保存回原位置。
0046E966.DFE0FSTSWAX
0046E968.A80DTESTAL,0D
0046E96A.0F858F000000JNZBOOKEXPO.0046E9FF
0046E970.^EBB6JMPSHORTBOOKEXPO.0046E928//继续循环上去。
如果经过乘7后的注册码串长达到8位,则从0046E958蹦到这里来。
0046E972>8B45E0MOVEAX,DWORDPTRSS:[EBP-20]//16进制浮点数形式的结果分别送EAX(高4字节),ECX(低4字
节)。
0046E975.8B4DDCMOVECX,DWORDPTRSS:[EBP-24]
0046E978.6A08PUSH8
0046E97A.50PUSHEAX
0046E97B.51PUSHECX
0046E97C.FFD3CALLEBX
0046E97E.8BD0MOVEDX,EAX
0046E980.8D4DD8LEAECX,DWORDPTRSS:[EBP-28]
0046E983.FFD7CALLEDI
0046E985.50PUSHEAX
0046E986.FF15AC124000CALLDWORDPTRDS:[<&MSVBVM60.#616>];MSVBVM60.rtcLeftCharBstr//复制已经转换为字符的
注册码到另一个位置。
0046E98C.8BD0MOVEDX,EAX//真注册码地址在EAX内。
0046E98E.8D4DE4LEAECX,DWORDPTRSS:[EBP-1C]
0046E991.FFD7CALLEDI
0046E993.8D4DD8LEAECX,DWORDPTRSS:[EBP-28]
0046E996.FF1508134000CALLDWORDPTRDS:[<&MSVBVM60.__vbaFreeS>;MSVBVM60.__vbaFreeStr
0046E99C>9BWAIT
0046E99D.68D8E94600PUSHBOOKEXPO.0046E9D8
0046E9A2.EB33JMPSHORTBOOKEXPO.0046E9D7
========================================================================================
后记:
这个小软件虽然是VB写的,界面非常简单。但是注册码的计算都在主程序内,所以,相对比较简单。通过跟踪这个软件,我明白了浮点数
用法和指令,以前很少看到这方面的资料,一般都是整数运算,可是这个软件都是浮点运算。这个注册码的计算是根据用户名得到的,如
果得到的注册码的长度不够8位则继续乘以7,如果到达8位,则得到正确注册码了。简单计算过程如下,注册机可以很容易写出:
假如用户名为iloveu,则首先在前面加上2个字符小写的"l"和大写的"M"。形成一个新串"lMiloveu"。
SUM=89715;
for(ESI=3;ESI<=8;ESI++)
{
1.计算用户名第i位和第i+2位乘积,得结果EAX;
2.用SUM除以ESI,得余数送EDX;
3.EDX=EDX+1,ESI=ESI+1;
4.EDX=EAX*EDX。
5.SUM+=EDX。
}
do{
断SUM的位数,如果小于8,则乘以7。如果等于8则结束循环。
}while(1);
结论:
Username:RegisterCode:
wanggang24105501
iloveu14669865
该程序在注册表内的H.L.M\Software\KLMsoft\BookmarkExporter键内写入RegCode和RegName子键。
感谢您浪费时间阅读此文!恭祝所有看雪坛友新春快乐!!