题目:分析Bookmark Exporter之注册机制
软件介绍:该软件可以在不同浏览器(IE,NetScape等)之间转换你的收藏夹(书签),里面有你常用的网络地址。并且可以产生非常专
业的层叠菜单,还可把产生的菜单发布到网络上供随时查看。软件来自《电脑爱好者2003光盘》。
工具:Softice,PEID
引子:今天又安装调试了一个软件,用PEID查看,得知这个软件是VB写的,无壳。试用期20天,过期则有功能限制(启动时有NAG,只可
以生成40个菜单项)。启动程序,打开HELP菜单,单击Register,输入用户名iloveu,注意用户名必须大于6位。激活码1234-5678。调出
SOFTICE,下断点bpx hmemcpy,F5退出,点击Register按钮,被拦截。7次F12,换F10跟踪,很快就来到如下代码处。
0046D3F4 . FF90 A0000000 CALL DWORD PTR DS:[EAX+A0]
0046D3FA . DBE2 FCLEX //我们回到这里。
0046D3FC . 8985 38FFFFFF MOV DWORD PTR SS:[EBP-C8],EAX
0046D402 . 83BD 38FFFFFF >CMP DWORD PTR SS:[EBP-C8],0
0046D409 . 7D 26 JGE SHORT BOOKEXPO.0046D431 //自然跳。
***省略几行****
0046D4D3 . DBE2 FCLEX
0046D4D5 . 8985 28FFFFFF MOV DWORD PTR SS:[EBP-D8],EAX
0046D4DB . 83BD 28FFFFFF >CMP DWORD PTR SS:[EBP-D8],0
0046D4E2 . 7D 26 JGE SHORT BOOKEXPO.0046D50A //自然跳。
***省略几行****
0046D50A > C785 F8FEFFFF >MOV DWORD PTR SS:[EBP-108],0 //从这里正式开始。
0046D514 > 8B45 D4 MOV EAX,DWORD PTR SS:[EBP-2C] //第一部分注册码"1234"地址送EAX。
0046D517 . 50 PUSH EAX
0046D518 . 8B4D D0 MOV ECX,DWORD PTR SS:[EBP-30] //第二部分注册码地址"5678"送ECX。
0046D51B . 51 PUSH ECX
0046D51C . FF15 7C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCa> //串接两部分注册码。
0046D522 . 8BD0 MOV EDX,EAX
0046D524 . 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
***省略几行****
0046D595 . FF92 A0000000 CALL DWORD PTR DS:[EDX+A0]
0046D59B . DBE2 FCLEX
0046D59D . 8985 40FFFFFF MOV DWORD PTR SS:[EBP-C0],EAX
0046D5A3 . 83BD 40FFFFFF >CMP DWORD PTR SS:[EBP-C0],0
0046D5AA . 7D 26 JGE SHORT BOOKEXPO.0046D5D2 //此处自然跳。
***省略几行****
0046D5FB . 8D8D 48FFFFFF LEA ECX,DWORD PTR SS:[EBP-B8]
0046D601 . 51 PUSH ECX
0046D602 . 8D55 D0 LEA EDX,DWORD PTR SS:[EBP-30] //用户名地址送EDX。
0046D605 . 52 PUSH EDX
0046D606 . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
0046D609 . 8B08 MOV ECX,DWORD PTR DS:[EAX]
0046D60B . 8B55 08 MOV EDX,DWORD PTR SS:[EBP+8]
0046D60E . 52 PUSH EDX
0046D60F . FF91 FC060000 CALL DWORD PTR DS:[ECX+6FC]
0046D615 . 8985 3CFFFFFF MOV DWORD PTR SS:[EBP-C4],EAX
0046D61B . 83BD 3CFFFFFF >CMP DWORD PTR SS:[EBP-C4],0
0046D622 . 7D 23 JGE SHORT BOOKEXPO.0046D647 //此处自然跳。
***省略几行****
0046D647 > C785 F0FEFFFF >MOV DWORD PTR SS:[EBP-110],0
0046D651 > 66:8B95 48FFFF>MOV DX,WORD PTR SS:[EBP-B8]
0046D658 . 66:8995 38FFFF>MOV WORD PTR SS:[EBP-C8],DX
0046D65F . 8D4D D0 LEA ECX,DWORD PTR SS:[EBP-30]
0046D662 . FF15 08134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeS>
0046D668 . 8D4D C8 LEA ECX,DWORD PTR SS:[EBP-38]
0046D66B . FF15 04134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeO>
0046D671 . 0FBF85 38FFFFF>MOVSX EAX,WORD PTR SS:[EBP-C8]
0046D678 . 85C0 TEST EAX,EAX
0046D67A . 0F84 00010000 JE BOOKEXPO.0046D780 //此处自然跳。否则下面提示非法激活码。
0046D680 . C745 FC 050000>MOV DWORD PTR SS:[EBP-4],5
0046D687 . C745 84 040002>MOV DWORD PTR SS:[EBP-7C],80020004
0046D68E . C785 7CFFFFFF >MOV DWORD PTR SS:[EBP-84],0A
0046D698 . C745 94 040002>MOV DWORD PTR SS:[EBP-6C],80020004
0046D69F . C745 8C 0A0000>MOV DWORD PTR SS:[EBP-74],0A
0046D6A6 . C785 74FFFFFF >MOV DWORD PTR SS:[EBP-8C],BOOKEXPO.00420>; UNICODE "Illegal Activation Code"
0046D6B0 . C785 6CFFFFFF >MOV DWORD PTR SS:[EBP-94],8
0046D6BA . 8D95 6CFFFFFF LEA EDX,DWORD PTR SS:[EBP-94]
***省略多行****
0046D780 > C745 FC 060000>MOV DWORD PTR SS:[EBP-4],6
0046D787 . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
***省略多行****
0046D7C2 . 8985 40FFFFFF MOV DWORD PTR SS:[EBP-C0],EAX
0046D7C8 . 83BD 40FFFFFF >CMP DWORD PTR SS:[EBP-C0],0
0046D7CF . 7D 26 JGE SHORT BOOKEXPO.0046D7F7 //此处自然跳。
***省略多行****
0046D7F7 > C785 ECFEFFFF >MOV DWORD PTR SS:[EBP-114],0
0046D801 > 8B4D D4 MOV ECX,DWORD PTR SS:[EBP-2C]
0046D804 . 898D 0CFFFFFF MOV DWORD PTR SS:[EBP-F4],ECX
0046D80A . C745 D4 000000>MOV DWORD PTR SS:[EBP-2C],0
0046D811 . 8B95 0CFFFFFF MOV EDX,DWORD PTR SS:[EBP-F4] //用户名地址送EDX。
0046D817 . 8D4D D0 LEA ECX,DWORD PTR SS:[EBP-30]
0046D81A . FF15 CC124000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
0046D820 . 8D55 CC LEA EDX,DWORD PTR SS:[EBP-34]
0046D823 . 52 PUSH EDX
0046D824 . 8D45 D0 LEA EAX,DWORD PTR SS:[EBP-30]
0046D827 . 50 PUSH EAX
0046D828 . 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8]
0046D82B . 8B11 MOV EDX,DWORD PTR DS:[ECX]
0046D82D . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
0046D830 . 50 PUSH EAX
0046D831 . FF92 F8060000 CALL DWORD PTR DS:[EDX+6F8] //这个CALL重要,就是产生注册码的地方。CALL 40AE0F。后面分析
。(*)
0046D837 . 8985 3CFFFFFF MOV DWORD PTR SS:[EBP-C4],EAX
0046D83D . 83BD 3CFFFFFF >CMP DWORD PTR SS:[EBP-C4],0
0046D844 . 7D 23 JGE SHORT BOOKEXPO.0046D869
***省略多行****
0046D911 > 8B45 CC MOV EAX,DWORD PTR SS:[EBP-34] //真码地址送EAX。
0046D914 . 50 PUSH EAX
0046D915 . 8B4D D8 MOV ECX,DWORD PTR SS:[EBP-28] //假码地址送ECX。
0046D918 . 51 PUSH ECX
0046D919 . FF15 44114000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCm> //很明显进行串比较啦。
0046D91F . F7D8 NEG EAX
0046D921 . 1BC0 SBB EAX,EAX
0046D923 . 40 INC EAX
***省略多行****
0046D950 . 0FBF8D 30FFFFF>MOVSX ECX,WORD PTR SS:[EBP-D0]
0046D957 . 85C9 TEST ECX,ECX //如果注册码正确,则ECX=FFFFFFFF
0046D959 . 0F84 C6030000 JE BOOKEXPO.0046DD25 //这个地方不跳则OK。
***下面是注册成功的感谢信息*******
0046D993 . 68 EC054200 PUSH BOOKEXPO.004205EC ; UNICODE "Thank You for registering Bookmark
Exporter."
0046D998 . 68 34454100 PUSH BOOKEXPO.00414534 "
0046D99D . FF15 7C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCa>
0046D9A3 . 8BD0 MOV EDX,EAX
0046D9A5 . 8D4D D4 LEA ECX,DWORD PTR SS:[EBP-2C]
0046D9A8 . FF15 CC124000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
0046D9AE . 50 PUSH EAX
0046D9AF . 68 4C064200 PUSH BOOKEXPO.0042064C ; UNICODE "All limitations are removed. Enjoy."
0046D9B4 . FF15 7C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCa>
===================================================================================================
我们跟进前面(*)处的函数看看:
0040AE0F . E9 7C390600 JMP BOOKEXPO.0046E790 //其实这是跳转,真正的函数在下面。
0046E790 > 55 PUSH EBP
0046E791 . 8BEC MOV EBP,ESP
0046E793 . 83EC 0C SUB ESP,0C
***省略多行****
0046E7DB . 8B03 MOV EAX,DWORD PTR DS:[EBX] //取用户名地址并进栈。
0046E7DD . 50 PUSH EAX
0046E7DE . 897D D8 MOV DWORD PTR SS:[EBP-28],EDI
0046E7E1 . 897D D4 MOV DWORD PTR SS:[EBP-2C],EDI
0046E7E4 . 897D C4 MOV DWORD PTR SS:[EBP-3C],EDI
0046E7E7 . 897D B4 MOV DWORD PTR SS:[EBP-4C],EDI
0046E7EA . FFD6 CALL ESI ; <&MSVBVM60.__vbaLenBstr> //取用户名串长。
0046E7EC . 83F8 06 CMP EAX,6 //与6比较,如果小于则下面跳走,则错。
0046E7EF . 0F8C A7010000 JL BOOKEXPO.0046E99C
0046E7F5 . 8B0B MOV ECX,DWORD PTR DS:[EBX] //取用户名地址送ECX。
0046E7F7 . 68 08074200 PUSH BOOKEXPO.00420708 ;UNICODE "lM" //字符串 "lM" 地址进栈。这里是小写的L,不是一。
0046E7FC . 51 PUSH ECX
0046E7FD . 897D DC MOV DWORD PTR SS:[EBP-24],EDI
0046E800 . C745 E0 30E7F5>MOV DWORD PTR SS:[EBP-20],40F5E730
0046E807 . FF15 7C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCa> //把 "lM" 串接在用户名前面。比如形成 "lMiloveu"的
形式。
0046E80D . 8B3D CC124000 MOV EDI,DWORD PTR DS:[<&MSVBVM60.__vbaSt>
0046E813 . 8BD0 MOV EDX,EAX
0046E815 . 8BCB MOV ECX,EBX
0046E817 . FFD7 CALL EDI
0046E819 . 8B13 MOV EDX,DWORD PTR DS:[EBX] //新串地址送EDX。
0046E81B . 52 PUSH EDX
0046E81C . FFD6 CALL ESI //取新串长度。
0046E81E . 8945 80 MOV DWORD PTR SS:[EBP-80],EAX //串长送:[EBP-80]保存。下面循环用到。
0046E821 . BE 03000000 MOV ESI,3 //ESI初始化为3。下面循环开始,总共循环6次。
0046E826 > 3B75 80 CMP ESI,DWORD PTR SS:[EBP-80] //比较ESI和串长。
0046E829 . 0F8F F3000000 JG BOOKEXPO.0046E922 //如果大于则说明结束运算。否则继续循环。
0046E82F . 8B0B MOV ECX,DWORD PTR DS:[EBX]
0046E831 . 8D45 C4 LEA EAX,DWORD PTR SS:[EBP-3C]
0046E834 . 50 PUSH EAX
0046E835 . 56 PUSH ESI
0046E836 . 51 PUSH ECX
0046E837 . C745 CC 010000>MOV DWORD PTR SS:[EBP-34],1
0046E83E . C745 C4 020000>MOV DWORD PTR SS:[EBP-3C],2
0046E845 . FF15 14114000 CALL DWORD PTR DS:[<&MSVBVM60.#631>] ; MSVBVM60.rtcMidCharBstr //依次取出新用户名后6位
。顺序为i,l,o,v,e,u.
0046E84B . 8BD0 MOV EDX,EAX
0046E84D . 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
0046E850 . FFD7 CALL EDI
0046E852 . 50 PUSH EAX
0046E853 . FF15 58104000 CALL DWORD PTR DS:[<&MSVBVM60.#516>] ; MSVBVM60.rtcAnsiValueBstr
0046E859 . 8B0B MOV ECX,DWORD PTR DS:[EBX]
0046E85B . 8945 90 MOV DWORD PTR SS:[EBP-70],EAX //用户名字符送内存保存。
0046E85E . 8BC6 MOV EAX,ESI //前面ESI的值送EAX,开始是3。
0046E860 . 8D55 B4 LEA EDX,DWORD PTR SS:[EBP-4C]
0046E863 . 83E8 02 SUB EAX,2 //EAX减2,得1。
0046E866 . 52 PUSH EDX
0046E867 . 0F80 97010000 JO BOOKEXPO.0046EA04
0046E86D . 50 PUSH EAX
0046E86E . 51 PUSH ECX
0046E86F . C745 BC 010000>MOV DWORD PTR SS:[EBP-44],1
0046E876 . C745 B4 020000>MOV DWORD PTR SS:[EBP-4C],2
0046E87D . FF15 14114000 CALL DWORD PTR DS:[<&MSVBVM60.#631>] ; MSVBVM60.rtcMidCharBstr //依次取新用户名前6位。
顺序是l,M,i,l,o,v.
0046E883 . 8BD0 MOV EDX,EAX
0046E885 . 8D4D D4 LEA ECX,DWORD PTR SS:[EBP-2C]
0046E888 . FFD7 CALL EDI
0046E88A . 50 PUSH EAX
0046E88B . FF15 58104000 CALL DWORD PTR DS:[<&MSVBVM60.#516>] ; MSVBVM60.rtcAnsiValueBstr
0046E891 . DD45 DC FLD QWORD PTR SS:[EBP-24] //这里是浮点取数指令,第一次是把一个[EBP-24]处的常数
89714送ST(0)寄存器。以后都是累加和。
0046E894 . 8945 8C MOV DWORD PTR SS:[EBP-74],EAX
0046E897 . FF15 A8124000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFpI4>>; MSVBVM60.__vbaFpI4 //把ST(0)内的浮点数形式的值
转换为16进制后送EAX。
0046E89D . 99 CDQ //扩展到EDX。
0046E89E . F7FE IDIV ESI //EAX=EAX/ESI ,余数送EDX。ESI初始值是3。然后依次是4,
5,6,7。
0046E8A0 . 0FBF45 8C MOVSX EAX,WORD PTR SS:[EBP-74] //前6位字符依次送EAX。当然是每次循环各送一个。
0046E8A4 . 0FBF4D 90 MOVSX ECX,WORD PTR SS:[EBP-70] //后6位字符依次送ECX。
0046E8A8 . 83C2 01 ADD EDX,1 // EDX加1。
0046E8AB . 0F80 53010000 JO BOOKEXPO.0046EA04
0046E8B1 . 0FAFC1 IMUL EAX,ECX //EAX=EAX*ECX。 //间隔一位的两个字符相乘,结果送EAX。
0046E8B4 . 0F80 4A010000 JO BOOKEXPO.0046EA04
0046E8BA . 0FAFD0 IMUL EDX,EAX //EDX=EDX*EAX。这里每次EDX值不同,取决于前面所做的除法
运算结果。
0046E8BD . 0F80 41010000 JO BOOKEXPO.0046EA04
0046E8C3 . 8995 74FFFFFF MOV DWORD PTR SS:[EBP-8C],EDX //EDX送内存保存。
0046E8C9 . 8D55 D4 LEA EDX,DWORD PTR SS:[EBP-2C]
0046E8CC . DB85 74FFFFFF FILD DWORD PTR SS:[EBP-8C] //这个浮点指令取刚才保存的EDX值,但是在ST(0)内是显示
的十进制
0046E8D2 . 52 PUSH EDX
0046E8D3 . DD9D 6CFFFFFF FSTP QWORD PTR SS:[EBP-94] //把刚才这个结果变为浮点数送另一位置:[EBP-94]
0046E8D9 . DD85 6CFFFFFF FLD QWORD PTR SS:[EBP-94] //再次取回刚才这个数。
0046E8DF . DC45 DC FADD QWORD PTR SS:[EBP-24] //与前面:[EBP-24]保存的浮点数相加。
0046E8E2 . DD5D DC FSTP QWORD PTR SS:[EBP-24] //相加的结果送回:[EBP-24] 内保存。下次循环在46E891处
的指令用到这个值。
0046E8E5 . DFE0 FSTSW AX //把异常字保存在AX。
0046E8E7 . A8 0D TEST AL,0D //测试是否发生异常。
0046E8E9 . 0F85 10010000 JNZ BOOKEXPO.0046E9FF
***省去多行*****
0046E90B . B8 01000000 MOV EAX,1 //EAX=1。
0046E910 . 83C4 18 ADD ESP,18
0046E913 . 03C6 ADD EAX,ESI //EAX=EAX+ESI。
0046E915 . 0F80 E9000000 JO BOOKEXPO.0046EA04
0046E91B . 8BF0 MOV ESI,EAX //EAX的值送ESI,ESI递增,准备下次循环用。
0046E91D .^E9 04FFFFFF JMP BOOKEXPO.0046E826 //循环上去。
上面如果结束循环则跳到这里来。
0046E922 > 8B1D 8C114000 MOV EBX,DWORD PTR DS:[<&MSVBVM60.__vbaSt>
0046E928 > 8B45 E0 MOV EAX,DWORD PTR SS:[EBP-20] //得到16进制形式的浮点数结果的高4字节送EAX,低4字节送
ECX。
0046E92B . 8B4D DC MOV ECX,DWORD PTR SS:[EBP-24]
0046E92E . 50 PUSH EAX
0046E92F . 51 PUSH ECX
0046E930 . FFD3 CALL EBX //转换为16进制整数。
0046E932 . 8BD0 MOV EDX,EAX
0046E934 . 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
0046E937 . FFD7 CALL EDI //转化为字符串。
0046E939 . 50 PUSH EAX
0046E93A . FF15 3C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaLenBs> //取得到的注册码串长。
0046E940 . 33D2 XOR EDX,EDX //EDX清0。
0046E942 . 83F8 08 CMP EAX,8 //放在EAX内的串长与8比较。
0046E945 . 0F9CC2 SETL DL //如果小于8则DL置1,否则保持原来的0。
0046E948 . F7DA NEG EDX //EDX求反。
0046E94A . 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
0046E94D . 8BF2 MOV ESI,EDX //EDX送ESI。
0046E94F . FF15 08134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeS>
0046E955 . 66:85F6 TEST SI,SI //判断SI是否为0。
0046E958 . 74 18 JE SHORT BOOKEXPO.0046E972 //如果是0则跳走。否则进行下面的工作。
0046E95A . DD45 DC FLD QWORD PTR SS:[EBP-24] //取:[EBP-24] 值送EAX。
0046E95D . DC0D 10314000 FMUL QWORD PTR DS:[403110] //与:[403110] 内的浮点数形式的常数'7'相乘。
0046E963 . DD5D DC FSTP QWORD PTR SS:[EBP-24] //保存回原位置。
0046E966 . DFE0 FSTSW AX
0046E968 . A8 0D TEST AL,0D
0046E96A . 0F85 8F000000 JNZ BOOKEXPO.0046E9FF
0046E970 .^EB B6 JMP SHORT BOOKEXPO.0046E928 //继续循环上去。
如果经过乘7后的注册码串长达到8位,则从0046E958 蹦到这里来。
0046E972 > 8B45 E0 MOV EAX,DWORD PTR SS:[EBP-20] //16进制浮点数形式的结果分别送EAX(高4字节),ECX(低4字
节)。
0046E975 . 8B4D DC MOV ECX,DWORD PTR SS:[EBP-24]
0046E978 . 6A 08 PUSH 8
0046E97A . 50 PUSH EAX
0046E97B . 51 PUSH ECX
0046E97C . FFD3 CALL EBX
0046E97E . 8BD0 MOV EDX,EAX
0046E980 . 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
0046E983 . FFD7 CALL EDI
0046E985 . 50 PUSH EAX
0046E986 . FF15 AC124000 CALL DWORD PTR DS:[<&MSVBVM60.#616>] ; MSVBVM60.rtcLeftCharBstr //复制已经转换为字符的
注册码到另一个位置。
0046E98C . 8BD0 MOV EDX,EAX //真注册码地址在EAX内。
0046E98E . 8D4D E4 LEA ECX,DWORD PTR SS:[EBP-1C]
0046E991 . FFD7 CALL EDI
0046E993 . 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
0046E996 . FF15 08134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeS>; MSVBVM60.__vbaFreeStr
0046E99C > 9B WAIT
0046E99D . 68 D8E94600 PUSH BOOKEXPO.0046E9D8
0046E9A2 . EB 33 JMP SHORT BOOKEXPO.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:
wanggang 24105501
iloveu 14669865
该程序在注册表内的H.L.M\Software\KLMsoft\BookmarkExporter键内写入RegCode和RegName子键。
感谢您浪费时间阅读此文!恭祝所有看雪坛友新春快乐!!
qduwg
qduwg@163.com
2006年1月25日结稿Ethiopia
[招生]系统0day安全班,企业级设备固件漏洞挖掘,Linux平台漏洞挖掘!