小弟处女作,请多关照!以小弟首篇破文祝老婆生日快乐!
Hamber(hitetoshi@163.com)
软件:X-posure(骨密度计量学)
主页:http://www.pronosco.com/
说明:Pronosco X-posure System 是多年来骨密度计量学中研究和发展的顶点。
工具:SoftICE,W32DASM
平台:Windows 2000
纯属技术交流,请勿随意散步或用于商业用途。
该软件安装后有Xposure.exe和Settings.exe两个重要文件。Xposure.exe为主程序文件,如果没有输入序列号,则在运行时会弹出对话框告知序列号错误。Settings.exe用来输入和验证序列号。
运行Settings.exe,在Serial中输入1234567890,SoftICE例行手续,不再介绍,断下后走到这里:
…
:004060BB 8BF1 mov esi, ecx
:004060BD 8B842480000000 mov eax, dword ptr [esp+00000080] //序列号串长
:004060C4 C744247000000000 mov [esp+70], 00000000
:004060CC 83F80F cmp eax, 0000000F
:004060CF 0F84E4000000 je 004061B9 //不跳则MessageBox
看来序列号必须为15个字符。重新输入123456789098765,再走到:
:00406E0E 8B442410 mov eax, dword ptr [esp+10] //第1个字符
:00406E12 64892500000000 mov dword ptr fs:[00000000], esp
:00406E19 81EC9C000000 sub esp, 0000009C
:00406E1F 53 push ebx
:00406E20 56 push esi
:00406E21 57 push edi
:00406E22 8BF1 mov esi, ecx
:00406E24 50 push eax
:00406E25 E8660E0000 call 00407C90 //关键
…
:00406E31 8B9424BA000000 mov edx, dword ptr [esp+000000BA]//第3个字符
…
:00406E3D E84E0E0000 call 00407C90
…
:00406E49 8B9424BB000000 mov edx, dword ptr [esp+000000BB]//第4个字符
…
:00406E55 E8360E0000 call 00407C90
…
:00406E61 8B9424BC000000 mov edx, dword ptr [esp+000000BC]//第5个字符
…
:00406E6D E81E0E0000 call 00407C90
…
:00406E79 8B9424BD000000 mov edx, dword ptr [esp+000000BD]//第6个字符
…
:00406E85 E8060E0000 call 00407C90
:00406E8A 8B8C24D8000000 mov ecx, dword ptr [esp+000000D8]
:00406E91 8B1DFC344100 mov ebx, dword ptr [MSVCRT!isdigit]
:00406E97 33FF xor edi, edi
:00406E99 8901 mov dword ptr [ecx], eax
:00406E9B 0FBE943CBF000000 movsx edx, byte ptr [esp+edi+000000BF]//第8个字符
:00406EA3 52 push edx
:00406EA4 FFD3 call ebx //是否为数字
:00406EA6 83C404 add esp, 00000004
:00406EA9 85C0 test eax, eax
:00406EAB 0F8434010000 je 00406FE5
:00406EB1 47 inc edi
:00406EB2 83FF06 cmp edi, 00000006
:00406EB5 7CE4 jl 00406E9B //重复6次,即依次检查第8到第13个字符
:00406EB7 8D9424BF000000 lea edx, dword ptr [esp+000000BF]
:00406EBE 52 push edx
:00406EBF FF1500354100 Call dword ptr [MSVCRT!atoi] //将第8-13个字符转换为数字
:00406EC5 8B8C24E0000000 mov ecx, dword ptr [esp+000000E0]
:00406ECC 8B9424CA000000 mov edx, dword ptr [esp+000000CA]
:00406ED3 83C404 add esp, 00000004
:00406ED6 8901 mov dword ptr [ecx], eax //保存转换的结果
从上面可以看出,第8到第13个字符必须为数字,00407C90这个位置也比较关键,跟进去看下:
:00407C90 6AFF push FFFFFFFF
:00407C92 68421E4100 push 00411E42
:00407C97 64A100000000 mov eax, dword ptr fs:[00000000]
:00407C9D 50 push eax
:00407C9E 64892500000000 mov dword ptr fs:[00000000], esp
:00407CA5 83EC4C sub esp, 0000004C
:00407CA8 8A44245C mov al, byte ptr [esp+5C] //当前字符
:00407CAC 53 push ebx
:00407CAD 88442460 mov byte ptr [esp+60], al //当前字符
:00407CB1 33DB xor ebx, ebx
:00407CB3 0FBEC0 movsx eax, al
:00407CB6 50 push eax
:00407CB7 885C2465 mov byte ptr [esp+65], bl
:00407CBB FF15FC344100 Call dword ptr [MSVCRT!isdigit] //是否为数字
:00407CC1 83C404 add esp, 00000004
:00407CC4 85C0 test eax, eax
:00407CC6 7420 je 00407CE8 //跳则MessageBox
:00407CC8 8D4C2460 lea ecx, dword ptr [esp+60] //当前字符
:00407CCC 51 push ecx
:00407CCD FF1500354100 Call dword ptr [MSVCRT!atoi] //转为数字
:00407CD3 8B4C2454 mov ecx, dword ptr [esp+54]
:00407CD7 83C404 add esp, 00000004
:00407CDA 64890D00000000 mov dword ptr fs:[00000000], ecx
:00407CE1 5B pop ebx
:00407CE2 83C458 add esp, 00000058
:00407CE5 C20400 ret 0004
由此可见,第1,3,4,5,6个字符必须为数字。再来到这里:
:00406EE9 8A8C24B9000000 mov cl, byte ptr [esp+000000B9] //第2个字符
:00406EF0 B02D mov al, 2D //’-‘
:00406EF2 3AC8 cmp cl, al
:00406EF4 0F8488010000 je 00407082 //不跳则MessageBox
…|
:00407082 388424BE000000 cmp byte ptr [esp+000000BE], al //第7个字符
:00407089 0F84EB000000 je 0040717A //不跳则MessageBox
…
:0040717A 388424C5000000 cmp byte ptr [esp+000000C5], al //第14个字符
:00407181 0F84EE000000 je 00407275 //不跳则MessageBox
根据上面的分析,可以得出序列号的完整形式:A-BCDE-FGHIJK-L,其中的A-L必须全部为10进制数字。在Seril中输入1-2345-678987-6,继续,来到这里:
:00407290 64A100000000 mov eax, dword ptr fs:[00000000]
:00407296 8B542404 mov edx, dword ptr [esp+04] //A(这里A即代表数字1,下同)
:0040729A 6AFF push FFFFFFFF
:0040729C 68321D4100 push 00411D32
:004072A1 50 push eax
:004072A2 8B442414 mov eax, dword ptr [esp+14] //B
:004072A6 64892500000000 mov dword ptr fs:[00000000], esp
:004072AD 83EC4C sub esp, 0000004C
:004072B0 03D0 add edx, eax //A+B
:004072B2 8B442464 mov eax, dword ptr [esp+64] //C
:004072B6 53 push ebx
:004072B7 8B5C2470 mov ebx, dword ptr [esp+70] //E
:004072BB 55 push ebp
:004072BC 8B6C2470 mov ebp, dword ptr [esp+70] //D
:004072C0 03D0 add edx, eax //A+B+C
:004072C2 57 push edi
:004072C3 8B7C247C mov edi, dword ptr [esp+7C] //FGHIJK(678987)
:004072C7 03D5 add edx, ebp //A+B+C+D
:004072C9 03D3 add edx, ebx //A+B+C+D+E
:004072CB 03D7 add edx, edi //A+B+C+D+E+FGHIJK
:004072CD 52 push edx
:004072CE E87D090000 call 00407C50 //关键
:004072D3 39842480000000 cmp dword ptr [esp+00000080], eax与L比较
:004072DA 0F84BD000000 je 0040739D //不跳则MessageBox
由于00407C70这个CALL后有个关键的跳转,跟进去看看,果然有重大发现:
:00407C50 8B4C2404 mov ecx, dword ptr [esp+04] //得到的和
:00407C54 56 push esi
:00407C55 33F6 xor esi, esi
:00407C57 85C9 test ecx, ecx
:00407C59 7E20 jle 00407C7B //为0则MessageBox
:00407C5B B867666666 mov eax, 66666667
:00407C60 F7E9 imul ecx //乘个0x66666667
:00407C62 C1FA02 sar edx, 02 //积高为算术右移2位(除个4)
:00407C65 8BC2 mov eax, edx
:00407C67 C1E81F shr eax, 1F //逻辑右移1F(只要是无符号的数,除这么多,应该为0了吧)
:00407C6A 03D0 add edx, eax //右移前与右移后相加
:00407C6C 8D0492 lea eax, dword ptr [edx+4*edx] //做个简单的运算
:00407C6F D1E0 shl eax, 1 //左移1位(乘个2)
:00407C71 2BC8 sub ecx, eax //原来的和减去得到的结果
:00407C73 03F1 add esi, ecx
:00407C75 8BCA mov ecx, edx
:00407C77 85D2 test edx, edx
:00407C79 7FE0 jg 00407C5B //直到相减的结果为0
:00407C7B 83FE09 cmp esi, 00000009
:00407C7E 8BCE mov ecx, esi
:00407C80 7FD3 jg 00407C55 //如果ESI大于9则重来
:00407C82 8BC6 mov eax, esi //返回最后的ESI
:00407C84 5E pop esi
:00407C85 C20400 ret 0004
在这里,ESI充当了一个计数器的作用。最后用汉语翻译一下(C语言麻烦):
1:A+B+C+D+E+FGHIJK=M,设一计数器COUNT=0。
2:M*0x66666667,高双字为N。
3:将N算术右移2位(N/4)得P。
4:将P逻辑右移0x1F(应该得0吧)得Q。
5:P+Q=R。
6:R*4+R=S。
7:S逻辑左移1位(S*2)得T。
8:M-T=U;计数器COUNT+=U。
9:M=R,若R不为0,则转到第2步。
10:若COUNT>9,则COUNT=0并转到第2步。
最后根据前面分析的要求,COUNT必须等于L。
用这段代码算个合适的序列号出来,还是MessageBox,继续往下:
…
:0040646F E84C0F0000 call 004073C0 //这个CALL过不去
进去004073C0看看:
:004073C0 64A100000000 mov eax, dword ptr fs:[00000000]
:004073C6 6AFF push FFFFFFFF
:004073C8 68181E4100 push 00411E18
:004073CD 50 push eax
:004073CE 8B442410 mov eax, dword ptr [esp+10] //A
:004073D2 64892500000000 mov dword ptr fs:[00000000], esp
:004073D9 81EC80010000 sub esp, 00000180
:004073DF 53 push ebx
:004073E0 56 push esi
:004073E1 BE02000000 mov esi, 00000002
:004073E6 57 push edi
:004073E7 2BC6 sub eax, esi
:004073E9 0F84A3000000 je 00407492 //不跳则MessageBox(A必须为2)
…
:00407499 893520A14100 mov dword ptr [0041A120], esi //C
:0040749F 85C0 test eax, eax
:004074A1 0F8EBD060000 jle 00407B64 //跳则MessageBox(C不为0)
:004074A7 3BC6 cmp eax, esi
:004074A9 0F8FB5060000 jg 00407B64 //跳则MessageBox(C必须小于等于2)
:004074AF A328A14100 mov dword ptr [0041A128], eax
:004074B4 8B8424A0010000 mov eax, dword ptr [esp+000001A0] //B
:004074BB 85C0 test eax, eax
:004074BD 0F8EFE050000 jle 00407AC1 //跳则MessageBox(B不为0)
:004074C3 3BC6 cmp eax, esi
:004074C5 0F8FF6050000 jg 00407AC1 //跳则MessageBox(B必须小于等于2)
:004074CB A324A14100 mov dword ptr [0041A124], eax
:004074D0 8B8424A8010000 mov eax, dword ptr [esp+000001A8] //D
:004074D7 48 dec eax
:004074D8 0F84E8020000 je 004077C6
:004074DE 48 dec eax
:004074DF 0F8412020000 je 004076F7
:004074E5 48 dec eax
:004074E6 0F8403010000 je 004075EF
… //后面是MessageBox之路,因此D必须小于等于3且大于0。
先看D为1的情况:
:004077C6 E865CEFFFF call 00404630
:004077CB 84C0 test al, al
:004077CD 0F85A3000000 jne 00407876
… //下面是MessageBox之路
看看这个00404630
:00404630 B001 mov al, 01
:00404632 C3 ret
所以004077CD是肯定会跳的,进去00407876看看:
:00407876 B901000000 mov ecx, 00000001
:0040787B 8B8424AC010000 mov eax, dword ptr [esp+000001AC] //E
:00407882 890D2CA14100 mov dword ptr [0041A12C], ecx
:00407888 85C0 test eax, eax
:0040788A 0F8E40010000 jle 004079D0 //跳则MessageBox(E不为0)
:00407890 3BC6 cmp eax, esi
:00407892 0F8F38010000 jg 004079D0 //跳则MessageBox(E必须小于等于2)
:00407898 A330A14100 mov dword ptr [0041A130], eax
:0040789D 0F85FA000000 jne 0040799D
:004078A3 83F903 cmp ecx, 00000003
:004078A6 0F85F1000000 jne 0040799D
再看看D为2的情况:
:004076F7 E834CFFFFF call 00404630
:004076FC 84C0 test al, al
:004076FE 0F85BB000000 jne 004077BF
在004077BF处:
:004077BF 8BCE mov ecx, esi
:004077C1 E9B5000000 jmp 0040787B
来到0040787B:
:0040787B 8B8424AC010000 mov eax, dword ptr [esp+000001AC] //E
:00407882 890D2CA14100 mov dword ptr [0041A12C], ecx
:00407888 85C0 test eax, eax
:0040788A 0F8E40010000 jle 004079D0 //跳则MessageBox(E不为0)
:00407890 3BC6 cmp eax, esi
:00407892 0F8F38010000 jg 004079D0 //跳则MessageBox(E必须小于等于2)
:00407898 A330A14100 mov dword ptr [0041A130], eax
:0040789D 0F85FA000000 jne 0040799D
:004078A3 83F903 cmp ecx, 00000003
:004078A6 0F85F1000000 jne 0040799D //不跳则MessageBox
最后看看D为3的情况:
:004075EF E83CD0FFFF call 00404630
:004075F4 84C0 test al, al
:004075F6 0F85F1000000 jne 004076ED
来到004076ED:
:004076ED B903000000 mov ecx, 00000003
:004076F2 E984010000 jmp 0040787B
还是来到0040787B,但此时ecx已经为3了,故D不能为3。
到此打完收工,总结一下。序列号的形式如:A-BCDE-FGHIJK-L(所有字母代表10进制数字)。A==2;0<B<=2;0<C<=2;0<D<=2;0<E<=2;最后根据前面讲述的方法计算出L。
一个有效的序列号的例子:2-1212-678987-8
弄到这里,满以为大功告成,输入序列号,运行Xposure.exe,居然弹出MessageBox,说:The X-posure Card was not found. Please check that the X_posure Card is inseted correctly. Contact your distributor if the problem persists. 用暴破法绕过SmartCard的检查,满以为大功告成,居然又弹出MessageBox,说:Please insert a valid card in the reader.
唉,留到以后的作业。
附:新用户注册后要24小时才能发贴,利用这个时间把Xposure.exe也弄出来了,暴破的,没有一点技术含量,不提也罢。
最后发现有意思的,如果序列号的B为2,那么XPosure运行的是Demo版,为1才是正式版。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)