【破文标题】某英语复读软件MFC简单算法
【破文作者】KiLlL
【破解时间】2006-01-21 23:25
【破解声明】仅为技术交流之用!
【破解过程】
很好的复读软件,这里仅做算法分析。名字省去了。
MFC,没有壳,很方便。机器码的生成用到了dll,那个dll是aspack压缩的。
根据错误提示的对话框很容易定位到下面:
0041A88F . E8 BC7AFFFF call 00412350 //关键call
0041A894 . 84C0 test al,al
0041A896 . 53 push ebx
0041A897 . 68 58A84200 push 0042A858
0041A89C . 75 2D jnz short 0041A8CB //注册成功
开始直接爆破00412350,让al返回值为1,结果发现有暗桩,某些功能在使用时还是有提示,索性跟进去看看:
00412350 51 push ecx
00412351 53 push ebx
00412352 55 push ebp
00412353 |. 56 push esi
00412354 |. 57 push edi
00412355 |. 8BE9 mov ebp,ecx
00412357 |. E8 74110000 call 004134D0
0041235C |. 8BCD mov ecx,ebp
0041235E |. E8 5D110000 call 004134C0
00412363 |. 8BCD mov ecx,ebp
00412365 |. E8 F60A0000 call 00412E60
0041236A |. 8B45 14 mov eax,[arg.4]
0041236D |. 8D7D 14 lea edi,[arg.4]
00412370 |. 8378 F8 08 cmp dword ptr ds:[eax-8],8 ; 注册码 8位
00412374 74 08 je short 0041237E
00412376 5F pop edi
00412377 5E pop esi
00412378 5D pop ebp
00412379 |. 32C0 xor al,al
0041237B |. 5B pop ebx
0041237C |. 59 pop ecx
0041237D |. C3 retn
0041237E |> 8BCF mov ecx,edi
00412380 |. E8 8DCD0000 call <jmp.&MFC42.#4202_CString::MakeLower>
00412385 |. 8B75 18 mov esi,[arg.5] ; 我的机器码 "46674926D"
00412388 |. 8B3F mov edi,dword ptr ds:[edi] ; 假码 12345678
0041238A |. 0FBE46 05 movsx eax,byte ptr ds:[esi+5] ; 机器码第六位 9
0041238E |. 0FBE16 movsx edx,byte ptr ds:[esi] ; 机器码第一位 4
00412391 |. 8D0C40 lea ecx,dword ptr ds:[eax+eax*2] ; 39*3=AB
00412394 |. 8D0488 lea eax,dword ptr ds:[eax+ecx*4] ; eax= eax+AB*4
00412397 |. 8BCA mov ecx,edx ; 34
00412399 |. C1E1 05 shl ecx,5 ; ecx=ecx*2^5
0041239C |. 03CA add ecx,edx ; ecx=680 +34
0041239E |. 8D0C49 lea ecx,dword ptr ds:[ecx+ecx*2] ; ecx=ecx*3 6b4*3=141c
004123A1 |. 8D144A lea edx,dword ptr ds:[edx+ecx*2] ; edx+=ecx*2 286c
004123A4 |. B9 24000000 mov ecx,24
004123A9 |. 03C2 add eax,edx ; eax+=edx 2e5+286c
004123AB |. 33D2 xor edx,edx
004123AD |. F7F1 div ecx ; 2b51/24
004123AF |. 0FBE0F movsx ecx,byte ptr ds:[edi] ; 注册码第一位
004123B2 |. 8D41 D0 lea eax,dword ptr ds:[ecx-30] ; Switch (cases 30..7A)
004123B5 |. 83F8 4A cmp eax,4A ; ascii-30
004123B8 |. 0F87 34010000 ja 004124F2
004123BE |. 33DB xor ebx,ebx
004123C0 |. 8A98 302A4100 mov bl,byte ptr ds:[eax+412A30] ; 查表
004123C6 |. FF249D 9C294100 jmp dword ptr ds:[ebx*4+41299C]
004123CD |> B8 13000000 mov eax,13 ; Case 31 ('1') of switch 004123B2
004123D2 |. E9 20010000 jmp 004124F7
004123D7 |> B8 02000000 mov eax,2 ; Case 32 ('2') of switch 004123B2
004123DC |. E9 16010000 jmp 004124F7
004123E1 |> B8 01000000 mov eax,1 ; Case 33 ('3') of switch 004123B2
004123E6 |. E9 0C010000 jmp 004124F7
004123EB |> B8 07000000 mov eax,7 ; Case 34 ('4') of switch 004123B2
004123F0 |. E9 02010000 jmp 004124F7
004123F5 |> B8 22000000 mov eax,22 ; Case 35 ('5') of switch 004123B2
004123FA |. E9 F8000000 jmp 004124F7
004123FF |> B8 05000000 mov eax,5 ; Case 36 ('6') of switch 004123B2
00412404 |. E9 EE000000 jmp 004124F7
00412409 |> B8 04000000 mov eax,4 ; Case 37 ('7') of switch 004123B2
0041240E |. E9 E4000000 jmp 004124F7
00412413 |> B8 10000000 mov eax,10 ; Case 38 ('8') of switch 004123B2
00412418 |. E9 DA000000 jmp 004124F7
0041241D |> 33C0 xor eax,eax ; Case 39 ('9') of switch 004123B2
0041241F |. E9 D3000000 jmp 004124F7
00412424 |> B8 11000000 mov eax,11 ; Case 30 ('0') of switch 004123B2
00412429 |. E9 C9000000 jmp 004124F7
0041242E |> B8 1C000000 mov eax,1C ; Case 61 ('a') of switch 004123B2
00412433 |. E9 BF000000 jmp 004124F7
00412438 |> B8 0C000000 mov eax,0C ; Case 62 ('b') of switch 004123B2
0041243D |. E9 B5000000 jmp 004124F7
00412442 |> B8 14000000 mov eax,14 ; Case 63 ('c') of switch 004123B2
00412447 |. E9 AB000000 jmp 004124F7
0041244C |> B8 0E000000 mov eax,0E ; Case 64 ('d') of switch 004123B2
00412451 |. E9 A1000000 jmp 004124F7
00412456 |> B8 0D000000 mov eax,0D ; Case 65 ('e') of switch 004123B2
0041245B |. E9 97000000 jmp 004124F7
00412460 |> B8 08000000 mov eax,8 ; Case 66 ('f') of switch 004123B2
00412465 |. E9 8D000000 jmp 004124F7
0041246A |> B8 09000000 mov eax,9 ; Case 67 ('g') of switch 004123B2
0041246F |. E9 83000000 jmp 004124F7
00412474 |> B8 12000000 mov eax,12 ; Case 68 ('h') of switch 004123B2
00412479 |. EB 7C jmp short 004124F7
0041247B |> B8 03000000 mov eax,3 ; Case 69 ('i') of switch 004123B2
00412480 |. EB 75 jmp short 004124F7
00412482 |> B8 0F000000 mov eax,0F ; Case 6A ('j') of switch 004123B2
00412487 |. EB 6E jmp short 004124F7
00412489 |> B8 15000000 mov eax,15 ; Case 6B ('k') of switch 004123B2
0041248E |. EB 67 jmp short 004124F7
00412490 |> B8 1B000000 mov eax,1B ; Case 6C ('l') of switch 004123B2
00412495 |. EB 60 jmp short 004124F7
00412497 |> B8 18000000 mov eax,18 ; Case 6D ('m') of switch 004123B2
0041249C |. EB 59 jmp short 004124F7
0041249E |> B8 17000000 mov eax,17 ; Case 6E ('n') of switch 004123B2
004124A3 |. EB 52 jmp short 004124F7
004124A5 |> B8 21000000 mov eax,21 ; Case 6F ('o') of switch 004123B2
004124AA |. EB 4B jmp short 004124F7
004124AC |> B8 1A000000 mov eax,1A ; Case 70 ('p') of switch 004123B2
004124B1 |. EB 44 jmp short 004124F7
004124B3 |> B8 16000000 mov eax,16 ; Case 72 ('r') of switch 004123B2
004124B8 |. EB 3D jmp short 004124F7
004124BA |> B8 1D000000 mov eax,1D ; Case 73 ('s') of switch 004123B2
004124BF |. EB 36 jmp short 004124F7
004124C1 |> B8 1E000000 mov eax,1E ; Case 74 ('t') of switch 004123B2
004124C6 |. EB 2F jmp short 004124F7
004124C8 |> B8 23000000 mov eax,23 ; Case 75 ('u') of switch 004123B2
004124CD |. EB 28 jmp short 004124F7
004124CF |> B8 20000000 mov eax,20 ; Case 76 ('v') of switch 004123B2
004124D4 |. EB 21 jmp short 004124F7
004124D6 |> B8 19000000 mov eax,19 ; Case 77 ('w') of switch 004123B2
004124DB |. EB 1A jmp short 004124F7
004124DD |> B8 06000000 mov eax,6 ; Case 78 ('x') of switch 004123B2
004124E2 |. EB 13 jmp short 004124F7
004124E4 |> B8 1F000000 mov eax,1F ; Case 79 ('y') of switch 004123B2
004124E9 |. EB 0C jmp short 004124F7
004124EB |> B8 0A000000 mov eax,0A ; Case 7A ('z') of switch 004123B2
004124F0 |. EB 05 jmp short 004124F7
004124F2 |> B8 0B000000 mov eax,0B ; Default case of switch 004123B2
004124F7 |> 3BD0 cmp edx,eax
004124F9 |. 74 0C je short 00412507
004124FB |. 5F pop edi
004124FC |. C645 0F 10 mov byte ptr ss:[ebp+F],10
00412500 |. 5E pop esi
00412501 |. 5D pop ebp
00412502 |. 32C0 xor al,al
00412504 |. 5B pop ebx
00412505 |. 59 pop ecx
00412506 |. C3 retn
这里首先验证注册码位数,然后逐位验证。验证时没有出现真正的注册码,而是通过假码第一位跟第六位运行后得到一个数字,再利用假码第一位查表得到另外一个数字,比较这两个数字,相等则继续,否则注册失败。
注意 mov byte ptr ss:[ebp+F],10这句,成功了是 mov byte ptr ss:[ebp+F],13,这里估计是个暗桩。有兴趣下个读断点试试。
给出vb的注册机源码,对比程序代码很容易看:
str = "1234567890abcdefghijklmnoprstuvwxyz{"
str1 = "130201072205041000111c0c140e0d080912030f151b1817211a161d1e232019061f0a0b"
eax = Asc(Mid$(mc, 6, 1))
edx = Asc(Mid$(mc, 1, 1))
ecx = eax * 3
eax = eax + ecx * 4
ecx = edx
ecx = ecx * 2 ^ 5
ecx = ecx + edx
ecx = ecx * 3
edx = edx + ecx * 2
ecx = &H24
eax = eax + edx
edx = eax Mod ecx
For i = 1 To Len(str1) - 1 Step 2
If Right$("00" & Hex$(edx), 2) = UCase$(Mid$(str1, i, 2)) Then
Tmp = Mid$(str, i \ 2 + 1, 1)
Exit For
End If
Next
If Tmp = "" Then Tmp = "{"
后面的7位计算方法与之类似。有几个地方要注意:
004128E8 |. C645 0C 01 mov byte ptr ss:[ebp+C],1 ; 1
00412941 |. C645 0D 01 mov byte ptr ss:[ebp+D],1 ; 2
0041298E |. C645 0F 13 mov byte ptr ss:[ebp+F],13 ; 3
【破解心得】
有了mfc的Lib文件,mfc的函数一目了然,所以很容易看清注册流程。该软件的思路不错,在关键call里面设置了其他返回数据,因此不能采取在函数开始直接返回al值的方法来爆破,但是还是很容易找到关键点。注册成功后结果保存在注册表内。
关于利用dll取得机器码的方法不是很可靠,简单编写一个dll就可以一码多用了。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)