NetScream 1.3.27.2006
这个程序比较怪异,一个是用+号来格开注册码使之成为若干组注册码。
另一个就是:浮点运算值与第一组注册码的差值不要超过某个定值都可以,随便挑注册码。
还有一个你点击程序的菜单都要看看注册码是否正确。
1.脱壳:
PEID:PECompact 2.x -> Jeremy Collake
RORDBG跟踪:
00DA79C2 ***API: KERNEL32.DLL!VirtualFree
可能到OEP了,如果不完全正确,请再单步走几下!
00525BB2 FFE0 JMP EAX
可能到OEP了,如果不完全正确,请再单步走几下!
00493744 55 PUSH EBP
00DA79C1 ***API: KERNEL32.DLL!GetModuleHandleA
好FLYODBG载入,忽略所有异常,HE 00525BB2,F9运行停住,然后来到OEP:
00493744 55 push ebp
00493745 8BEC mov ebp,esp
00493747 B9 36000000 mov ecx,36
LORDPE+ImportREC:dump并修复,运行ok。
Borland Delphi 6.0 - 7.0
2.断点:
Spy capure+eXescope+winhex定位注册按钮:
TForm3: OnClick = Button1Click:0047B96C;0047BD68;0047BFAC;0047C364;0047C980,0047CBFC;0048EF24;00492F40;004931DC;
断下:
0047C364 55 push ebp
这里也可以用DeDe来定位,不过加载实在慢。
3.定位核心:
断下后往下走,看到用户名注册码入栈计算:
0047C3ED 8B45 EC mov eax,dword ptr ss:[ebp-14] ; 用户名
0047C3F0 5A pop edx ; 注册码
0047C3F1 E8 621D0100 call dumped_.0048E158
0047C3F6 3C 01 cmp al,1
0047C3F8 0F85 DB000000 jnz dumped_.0047C4D9
如果不跳的话就提示谢谢注册。
4.关键call:0047C3F1 E8 621D0100 call dumped_.0048E158
4.1检查注册码是否有2B即+号,分别取出2组注册码:
0048E2DD 8B55 F8 mov edx,dword ptr ss:[ebp-8] ; zcm
0048E2E0 B8 70E84800 mov eax,dumped_.0048E870 ; 2b
0048E2E5 E8 DA63F7FF call dumped_.004046C4 ; 检查2B的位置
0048E2EA 40 inc eax ; 2B的位置+1
0048E2EB 50 push eax ; PUSH
0048E2EC 8B45 F8 mov eax,dword ptr ss:[ebp-8]
0048E2EF E8 8C60F7FF call dumped_.00404380
0048E2F4 8BC8 mov ecx,eax
0048E2F6 8B45 F8 mov eax,dword ptr ss:[ebp-8] ; zcm
0048E2F9 5A pop edx ; POP
0048E2FA E8 E162F7FF call dumped_.004045E0 ; 从第edx位开始取zcm
0048E2FF 8B55 D8 mov edx,dword ptr ss:[ebp-28] ; 剩下的注册码
0048E302 B8 70E84800 mov eax,dumped_.0048E870 ; 2B
0048E307 E8 B863F7FF call dumped_.004046C4 ; 检查2B的位置
0048E30C 48 dec eax ; 2B的位置-1
0048E30D 50 push eax
0048E30E 8D45 D4 lea eax,dword ptr ss:[ebp-2C]
0048E311 50 push eax
0048E312 8B55 F8 mov edx,dword ptr ss:[ebp-8]
0048E315 B8 70E84800 mov eax,dumped_.0048E870
0048E31A E8 A563F7FF call dumped_.004046C4
0048E31F 40 inc eax
0048E320 50 push eax
0048E321 8B45 F8 mov eax,dword ptr ss:[ebp-8]
0048E324 E8 5760F7FF call dumped_.00404380
0048E329 8BC8 mov ecx,eax
0048E32B 8B45 F8 mov eax,dword ptr ss:[ebp-8] ; zcm
0048E32E 5A pop edx ; 第一次位置+1
0048E32F E8 AC62F7FF call dumped_.004045E0 ; 取得第一批注册码
0048E334 8B45 D4 mov eax,dword ptr ss:[ebp-2C] ; 剩下的注册码
0048E337 BA 01000000 mov edx,1
0048E33C 59 pop ecx ; 第二次位置-1
0048E33D E8 9E62F7FF call dumped_.004045E0 ; 取得第二批注册码
比如练码为87654+3210+12345+678,得到2批注册码:87654&3210。
4.2用户名+取得的注册码的运算:
0048E35D 0FB600 movzx eax,byte ptr ds:[eax] ; 顺取用户名
0048E360 F7EB imul ebx ; ebx初始值=1,累增
...
0048E385 E8 3ABAF7FF call dumped_.00409DC4 ; 用户名乘积转换成十进制
0048E38A FF75 D0 push dword ptr ss:[ebp-30] ; 入栈
0048E38D 8D55 BC lea edx,dword ptr ss:[ebp-44]
0048E390 8BC3 mov eax,ebx
0048E392 E8 B5A1F7FF call dumped_.0040854C
0048E397 FF75 BC push dword ptr ss:[ebp-44] ; 序号入栈1,2,3...
0048E39A FF35 6C7F4900 push dword ptr ds:[497F6C] ; 第2批注册码入栈
0048E3A0 8D45 E4 lea eax,dword ptr ss:[ebp-1C] ;
0048E3A3 BA 03000000 mov edx,3 ; 待连接个数
0048E3A8 E8 9360F7FF call dumped_.00404440 ; 连接
0048E3AD 8B45 E4 mov eax,dword ptr ss:[ebp-1C] ; 连接值
0048E3B0 E8 D3A2F7FF call dumped_.00408688 ; 转换成十六进制
0048E3B5 8BF0 mov esi,eax
0048E3B7 8B45 E4 mov eax,dword ptr ss:[ebp-1C]
0048E3BA E8 C9A2F7FF call dumped_.00408688
0048E3BF 03F0 add esi,eax ; 转换后的十六进制×2
0048E3C1 8BC6 mov eax,esi
0048E3C3 8D55 B8 lea edx,dword ptr ss:[ebp-48]
0048E3C6 E8 81A1F7FF call dumped_.0040854C ; 转换成十进制
0048E3CB 8B55 B8 mov edx,dword ptr ss:[ebp-48] ; 转换值
这里就要小心了,如果取得的注册码值太大的话,转换成十六进制就会异常,最好取<5位。
连接的参数有3个:用户名+序号+第2组注册码
用户名:cyto,ASCII码十进制=99,121,116,111,乘积=99,242,348,444
序号:1,2,3,...
取得的第2组注册码=3210
得到的值分别为:99 1 3210,242 2 3210,348 3 3210,444 4 3210
×2后的值:19826420,...,88886420
4.3对最后一组值88886420的浮点计算:
0048E3E8 6A 16 push 16
0048E3EA 68 95B5AE55 push 55AEB595
0048E3EF 8B45 E4 mov eax,dword ptr ss:[ebp-1C] ; 最后一组计算值
0048E3F2 E8 91A2F7FF call dumped_.00408688 ; 转换成十六进制
0048E3F7 99 cdq
0048E3F8 E8 BF6BF7FF call dumped_.00404FBC ; 计算
0048E3FD 8945 C0 mov dword ptr ss:[ebp-40],eax ; 低位值
0048E400 8955 C4 mov dword ptr ss:[ebp-3C],edx ; 高位值
0012F580 24 36 25 38 C3 87 54 76 $6%8?Tv
最后一组计算值=88886420=54C4C94(H)
值×16=54C4C94×16=748E94B8
值×55AEB595=54C4C94×55AEB595=1C5F30B 38253624
高位值=值×16+值×55AEB595的高位=748E94B8+1C5F30B=765487C3
低位值=值×55AEB595的低位=38253624
转换成浮点:8.5265892670495268200E+18
4.4取扣除前2组剩下的注册码,再次检查有无2B:
0048E482 8B55 EC mov edx,dword ptr ss:[ebp-14] ; 所剩下的注册码
0048E485 B8 70E84800 mov eax,dumped_.0048E870 ; 2B
0048E48A E8 3562F7FF call dumped_.004046C4 ; 检查2B的位置
0048E48F 85C0 test eax,eax ; 返回的位置值
0048E491 0F8E 6B010000 jle dumped_.0048E602
比如练码为87654+3210+12345+678,剩下的就是12345+678。
4.5检查通过后取第4组:
0048E49B 8B55 EC mov edx,dword ptr ss:[ebp-14]
0048E49E B8 70E84800 mov eax,dumped_.0048E870
0048E4A3 E8 1C62F7FF call dumped_.004046C4
0048E4A8 40 inc eax
0048E4A9 50 push eax
0048E4AA 8B45 EC mov eax,dword ptr ss:[ebp-14]
0048E4AD E8 CE5EF7FF call dumped_.00404380
0048E4B2 8BC8 mov ecx,eax
0048E4B4 8B45 EC mov eax,dword ptr ss:[ebp-14]
0048E4B7 5A pop edx
0048E4B8 E8 2361F7FF call dumped_.004045E0
0048E4BD 8B45 AC mov eax,dword ptr ss:[ebp-54] ; 第4组
比如练码为87654+3210+12345+678,第4组就是678。
4.6取第3组注册码:
0048E4CC 8B55 EC mov edx,dword ptr ss:[ebp-14]
0048E4CF B8 70E84800 mov eax,dumped_.0048E870
0048E4D4 E8 EB61F7FF call dumped_.004046C4
0048E4D9 8BC8 mov ecx,eax
0048E4DB 49 dec ecx
0048E4DC BA 01000000 mov edx,1
0048E4E1 8B45 EC mov eax,dword ptr ss:[ebp-14]
0048E4E4 E8 F760F7FF call dumped_.004045E0
0048E4E9 8B45 A0 mov eax,dword ptr ss:[ebp-60]
比如练码为87654+3210+12345+678,第3组就是12345。
第3组累和:得到值=255=FF(H)
4.7浮点计算值与第1组注册码的运算:
0048E61C 8B45 F0 mov eax,dword ptr ss:[ebp-10] ; 第1组注册码
0048E61F E8 F8B7F7FF call dumped_.00409E1C
0048E624 DB7D 84 fstp tbyte ptr ss:[ebp-7C]
0048E627 9B wait
0048E628 8B45 E4 mov eax,dword ptr ss:[ebp-1C]
0048E62B E8 ECB7F7FF call dumped_.00409E1C
0048E630 DB6D 84 fld tbyte ptr ss:[ebp-7C]
0048E633 DEE1 fsubrp st(1),st ; 浮点值与第1组注册码差值
0048E635 D81D 8CE84800 fcomp dword ptr ds:[48E88C] ; 差值与4000比较
0048E63B DFE0 fstsw ax
0048E63D 9E sahf
0048E63E 0F87 53010000 ja dumped_.0048E797
0048E644 8B45 E4 mov eax,dword ptr ss:[ebp-1C]
0048E647 E8 D0B7F7FF call dumped_.00409E1C
0048E64C DBBD 78FFFFFF fstp tbyte ptr ss:[ebp-88]
0048E652 9B wait
0048E653 8B45 F0 mov eax,dword ptr ss:[ebp-10]
0048E656 E8 C1B7F7FF call dumped_.00409E1C
0048E65B DBAD 78FFFFFF fld tbyte ptr ss:[ebp-88]
0048E661 DEE1 fsubrp st(1),st ; 浮点值与第1组注册码差值
0048E663 D81D 8CE84800 fcomp dword ptr ds:[48E88C] ; 差值与4000比较
0048E669 DFE0 fstsw ax
0048E66B 9E sahf
0048E66C 0F87 25010000 ja dumped_.0048E797
这两个ja不能跳,跳就完。
试了好几个方法,让fsubrp st(1),st的值=0,都不会跳。
反复调试发现:fsubrp st(1),st的值只要不超过48E88C的值=4000就能通过。
4.8通过上面2个ja后,比较:
0048E672 8B45 E8 mov eax,dword ptr ss:[ebp-18] ; 第4组注册码
0048E675 8B55 E0 mov edx,dword ptr ss:[ebp-20] ; 第3组注册码累和ASCII码
0048E678 E8 4F5EF7FF call dumped_.004044CC ; 比较
0048E67D 75 0B jnz short dumped_.0048E68A ; 核心跳转
0048E67F C605 647F4900 0>mov byte ptr ds:[497F64],1
0048E686 C645 F7 01 mov byte ptr ss:[ebp-9],1
0048E68A 33C0 xor eax,eax
只要修改0048E67D处的跳转,这样就能爆破成功。
5.算法小结:
注册码需要3个+号格开得到4组注册码。
用户名与第2组注册码运算得到浮点值,浮点值要约等于第1组注册码。
第3组注册码累和=第4组注册码。
好,让第2组注册码小点,设为0,第3组注册码如果为12345的话,第4组就要=255,这样只需要反推第1组注册码,假设练码为:8+0+12345+255
得到浮点值=st(1)=8.5259734170344796160e+15
即8525973417034479.616,
第一组注册码从8525973417030480-8525973417038479任意数都可以注册成功。
用户名:cyto
注册码:8525973417034479+0+12345+255
写入注册表:
HKLM\Software\SWIFTDOG\NetScream\Name SUCCESS "cyto"
HKLM\Software\SWIFTDOG\NetScream\Serial SUCCESS "8525973417034479+0+12345+255"
[注意]APP应用上架合规检测服务,协助应用顺利上架!