【文章标题】: 无知者无畏----菜菜鸟也找注册码
【文章作者】: AsmDebuger
【作者QQ号】: 38250367
【软件名称】: xxx电子教程
【下载地址】: 自己搜索下载
【编写语言】: VB
【使用工具】: OD、PEiD、Google
【操作平台】: XP SP2
【软件介绍】: 一本电子书
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
自走上学习破解之路后,就有了个习惯-看到任何需要注册的软件都要查查、脱脱壳,只是发现
大部分软件脱了壳也不能直接运行,其保护措施比较全面,因此对于我这样的菜菜鸟来说,这些软件
跟起来还很吃力,而有那么几个软件,只要脱了壳就基本上破解成功了,这样的软件,对于我们菜菜
鸟来说,正是练手的好靶子,今天提到的软件即是如此。
这两天新年刚开工,闲来无事,常在坛子里泡,无意中看到一位仁兄求破解的违规帖,于是下载
来试试手,先用PEiD查壳:ASPack 2.12 -> Alexey Solodovnikov,嗯,不算是猛壳,还记得上次我提
到的超级巡警吧?直接脱之,成功!再查:Microsoft Visual Basic 5.0 / 6.0,怀着忐忑的心情用颤抖的
右手双击了一下图标,哇!能运行,美妙的开始(说实话,最近脱过的软件,能直接运行成功的寥寥
无几)!到此我信心倍增,不过我对VB还停留在无知的阶段,还是那句老话:无知者无畏,下面就
开始寻找注册码。
软件开始运行的是一个登录窗口,显示机器码为"964446455",需要填入注册码,根据提示说明,
有个试用密码"admin168",但功能有限制, 菜菜鸟也想找注册码。回忆一下,对于VB的程序,看过
一些资料,说有个什么字符串比较的断点,名字不记得了,别急,用OD载入脱壳后的软件,Ctrl+N
查看所有函数名称:
地址 区段 类型 ( 名称 注释
……
00401030 .text 输入 MSVBVM60.__vbaSetSystemError
0040102C .text 输入 ( MSVBVM60.__vbaStrCat
0040107C .text 输入 MSVBVM60.__vbaStrCmp ;这个看起来应该是了。
0040100C .text 输入 MSVBVM60.__vbaStrI4
直接F2下断(忽略在数据段下断的提示)。运行,随便输入密码"123".点击"登陆"按钮,程序停
在MSVBVM60的领空,看堆栈:
0012F3BC 004657EC 返回到 unpacked.004657EC 来自 MSVBVM60.__vbaStrCmp
0012F3C0 0040D300 UNICODE "admin168"
0012F3C4 0015E63C UNICODE "123"
猜测是拿我们的假码和试用密码比较,我们到004657EC看看先:
004657DD > \8B45 98 MOV EAX, SS:[EBP-68]
004657E0 . 50 PUSH EAX
004657E1 . 68 00D34000 PUSH unpacked.0040D300 ; UNICODE "admin168"
004657E6 . FF15 7C104000 CALL NEAR DS:[<&MSVBVM60.__vbaStrCmp>]; MSVBVM60.__vbaStrCmp
004657EC . 8BF8 MOV EDI, EAX
果然如此,不过这个不是我们想要的,我们要的是注册码,继续往上看(往下已经提示出错了), 仍然采用"倒叙法",
注意程序流程,看是怎样跳到上面那个比较的:
0046579D . /E9 90020000 JMP unpacked.00465A32 ;这里是跳走,
004657A2 > |8B16 MOV EDX, DS:[ESI] ; unpacked.004C1620
004657A4 . |56 PUSH ESI
004657A5 . |FF92 0C030000 CALL NEAR DS:[EDX+30C]
;;;;;;;;;;;
提示窗口显示004657A2处的跳转来自 004656A0,继续往前看:
0046565F > \8B45 98 MOV EAX, SS:[EBP-68]
00465662 . 8D8D 74FFFFFF LEA ECX, SS:[EBP-8C]
00465668 . 8D56 34 LEA EDX, DS:[ESI+34]
0046566B . 51 PUSH ECX ; /var18 = ntdll.7C93056D
0046566C . 52 PUSH EDX ; |var28 = 00130000
0046566D . C745 98 00000000 MOV DWORD PTR SS:[EBP-68], 0 ; |
00465674 . 8985 7CFFFFFF MOV SS:[EBP-84], EAX ; |
0046567A . C785 74FFFFFF 088>MOV DWORD PTR SS:[EBP-8C], 8008 ; |
00465684 . FF15 84104000 CALL NEAR DS:[<&MSVBVM60.__vbaVarTstEq>] ; \__vbaVarTstEq
0046568A . 8D4D 84 LEA ECX, SS:[EBP-7C]
0046568D . 8BF8 MOV EDI, EAX
0046568F . FF15 44114000 CALL NEAR DS:[<&MSVBVM60.__vbaFreeObj>] ; MSVBVM60.__vbaFreeObj
00465695 . 8D8D 74FFFFFF LEA ECX, SS:[EBP-8C]
0046569B . FFD3 CALL NEAR EBX ; MSVBVM60.__vbaFreeVar
0046569D . 66:85FF TEST DI, DI
004656A0 . 0F84 FC000000 JE unpacked.004657A2 ;DI等零则跳到试用码比较;根据vbaVarTstEq的返回参数,
;等0则为不等,等-1则相等,猜测软件先比较注册码了。
PS:
00465684 这行有"Eq"看到它我就有点儿警觉,有可能是EQU的缩写,因此这个CALL有可能是比较
函数,Google搜索该函数提示是变量比较, 疑点!在0046565F直接下断F2.再次重新开始运行,输
入假码,点击"登陆"按钮,中断,
0046565F > \8B45 98 MOV EAX, SS:[EBP-68]
00465662 . 8D8D 74FFFFFF LEA ECX, SS:[EBP-8C]
00465668 . 8D56 34 LEA EDX, DS:[ESI+34]
0046566B . 51 PUSH ECX ; /var18 = 0012F47C
0046566C . 52 PUSH EDX ; |var28 = 0015C2AC
0046566D . C745 98 00000000 MOV DWORD PTR SS:[EBP-68], 0 ; |
00465674 . 8985 7CFFFFFF MOV SS:[EBP-84], EAX ; |
0046567A . C785 74FFFFFF 088>MOV DWORD PTR SS:[EBP-8C], 8008 ; |
00465684 . FF15 84104000 CALL NEAR DS:[<&MSVBVM60.__vbaVarTstEq>] ; \__vbaVarTstEq
运行到此,看两个参数并不能知道注册码,只得F7跟进vbaVarTstEq这个Call:
7349BBE6 MSVBVM60.__vbaVarTstEq FF7424 08 PUSH DWORD PTR SS:[ESP+8]
7349BBEA FF7424 08 PUSH DWORD PTR SS:[ESP+8] ;第一个参数压栈;
7349BBEE 6A 00 PUSH 0
7349BBF0 E8 2254FFFF CALL MSVBVM60.73491017 ;继续跟进这个Call。
进入未知函数:
73491017 55 PUSH EBP
73491018 8BEC MOV EBP, ESP
7349101A 83EC 38 SUB ESP, 38
7349101D 8B55 10 MOV EDX, SS:[EBP+10] ; unpacked.0040AD64
73491020 8B4D 0C MOV ECX, SS:[EBP+C]
;;;
73491049 0FB745 08 MOVZX EAX, WORD PTR SS:[EBP+8]
7349104D 68 01000300 PUSH 30001
73491052 50 PUSH EAX
73491053 51 PUSH ECX
73491054 52 PUSH EDX
73491055 FF15 700E4A73 CALL NEAR DS:[734A0E70] ; OLEAUT32.VarCmp
运行到这里,继续跟进OLEAUT32.VarCmp这个Call(Var为一种特殊的结构,现在还没有看到明码):
77109F38 OLEAUT32.Var> 8BFF MOV EDI, EDI
77109F3A 55 PUSH EBP
77109F3B 8BEC MOV EBP, ESP
;;;;
7710C013 6A 05 PUSH 5
7710C015 FF75 14 PUSH DWORD PTR SS:[EBP+14]
7710C018 8BFE MOV EDI, ESI
7710C01A FF75 10 PUSH DWORD PTR SS:[EBP+10]
7710C01D 8BC3 MOV EAX, EBX
7710C01F E8 6AEFFFFF CALL OLEAUT32.7710AF8E
继续运行,到了这里,仍然没有出现明码,且没有明显的比较指令、函数,继续:
7710AF8E 8BFF MOV EDI, EDI
7710AF90 55 PUSH EBP
7710AF91 8BEC MOV EBP, ESP
7710AF93 83EC 10 SUB ESP, 10
7710AF96 66:8B0F MOV CX, DS:[EDI]
;;;;
7710AFC5 56 PUSH ESI
7710AFC6 8D45 F0 LEA EAX, SS:[EBP-10]
7710AFC9 50 PUSH EAX
7710AFCA E8 1BBBFEFF CALL OLEAUT32.VariantChangeTypeEx
;看名称知道是类型转换,因为前面的变量比较可以比较不同类型的变量,因此我们猜测此处可能是
转换明码或假码的程序,直接F8过;
7710AFCF 85C0 TEST EAX, EAX
7710AFD1 7C 1D JL SHORT OLEAUT32.7710AFF0
7710AFD3 FF75 0C PUSH DWORD PTR SS:[EBP+C]
7710AFD6 FF75 08 PUSH DWORD PTR SS:[EBP+8]
7710AFD9 FF77 08 PUSH DWORD PTR DS:[EDI+8]
7710AFDC FF75 F8 PUSH DWORD PTR SS:[EBP-8]
7710AFDF E8 30F8FFFF CALL OLEAUT32.VarBstrCmp
;哇!看名称知道,久违的比较函数到来了!运行到此,看堆栈:
ESP ==> 0012F2CC 0015E63C UNICODE "1110989163.25" ;明码
ESP+4 0012F2D0 0015E664 UNICODE "123" ;假码
哈哈,这里就可以看到注册码的明码了,二话不说,记下明码,退出OD,直接运行程序,输入
我们刚才得到的明码(全部输入,包括"."),嗯,无出错提示进入软件运行界面,再点击有注册限制
的功能,已经可以显示了,至此,我们已经找到注册码;
PS:
在此推测vbaVarTstEq函数运行机制:由于变量有可能类型不同,因此该函数会根据第一个参数的类
型对第二个参数进行类型转换,然后调用相应的比较 函数进行判断,本例是UNICODE码和浮点数
进行比较,把第二参数转换成UNICODE后再进行比较,因此如果bpx VarBstrCmp可以成功,但对
于其他的程序,有可能不成功,比较保险的还是下断vbaVarTstEq,再跟进几步就可以看到注册码了。
最后说说软件的注册码计算方法(通过查浮点数指令集得到):
机器码(本机964446455)做为十进制值,先浮点除以4,再浮点乘以3
然后浮点加387654322.0000000,最后得到的浮点数即是注册码,如果小数点后为0则只需输入整数
即可;
小数点后不为零则需要输入小数点加上小数数位,由于运算过程仅除以4,因此小数点不会超过两位,
即不存在除不尽的情况,以避免无法得到注册码的BUG。
--------------------------------------------------------------------------------
【经验总结】
这个软件的破解比较容易,首先是脱壳容易,第二是没有复杂的验证方法,之所以写这篇文章,主要是说说菜菜鸟对于
一个毫不了解的语言编写的程序怎样进行破解,其实主要是先多看大牛们的教程,记下各个语言关键下断的地方(比如这个
VB程序,如果在vbaVarTstEq下断的话就更快些),看清楚程序流程,以追溯到关键地址, 遇到不清楚功能的函数直接Google,
很多情况下Google会帮我们链接到看雪的某个帖子,相信会有很大帮助的。菜菜鸟经验不足,有失偏颇之处,敬请见谅!
正在写破文的过程中接到了从卓越买的《加密与解密》(第三版)的书,质量不错,已经爱不释手了,下一步准备系
统地学习一下书本的内容,以免自己失去方向。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)