Eagle的破文:(重写)FlashGet1.65的算号器
Eagle的破文:(重写)FlashGet1.65的算号器再次声明:本破文曾发表于www.chinadfcg.com
声明:上次写完1.60A的算号器,LeNgHost告诉我,FlashGet会在一段时间后验证第四段KEY,所以现在针对最新的FlashGet重写了算号破文。谢谢大家的支持。其实,这个算号器算出来的号还不是正版的。只能用一段时间,因为最后的几段的算法我没有时间去找了。
【破解作者】 Eagle
【作者邮箱】 eagle_twenty@163.com
【使用工具】 OllyDbg1.09
【破解平台】 WinXP
【软件名称】 FlashGet1.65
【加壳方式】 无壳
【破解声明】
--------------------------------------------------------------------------------
【破解内容】
安装FlashGet1.60A并运行,输入完注册码的时候,它会提示重新启动软件来检测是否注册成功,同时用RegMoniter监视到FlashGet1.60A写入注册表项RegPass, RegName等。用PEID侦壳:无。
1.用OD加载FlashGet1.60A,查找参考字符串,在涉及RegPass的地方下断,运行
2.程序第一次即中断在此,从上下文来看,这段代码有大量的跳转,有很大可能是注册码验证代码
0041DCE6|. 68 98E55200 PUSH flashget.0052E598 ;ASCII "RegPass"
0041DCEB|. 8D4C24 1C LEA ECX,DWORD PTR SS:
0041DCEF|. 68 A0C15200 PUSH flashget.0052C1A0 ;ASCII "General"
0041DCF4|. 51 PUSH ECX
0041DCF5|. 8BCD MOV ECX,EBP
;这个CALL将从注册表中读入注册码
0041DCF7|. E8 54C70C00 CALL flashget.004EA450
分析下面一段代码,可以发现每个条件跳转都跳向flashget.0041DE7B,可以那儿就是验证失败后的跳转方向
……
0041DD27|. 0F84 4E010000JE flashget.0041DE7B
……
0041DD35|. 0F84 40010000JE flashget.0041DE7B
……
0041DD4F|. 0F8E 26010000JLE flashget.0041DE7B
……
0041DD63|. 0F8C 12010000JL flashget.0041DE7B
……
0041DD77|. 0F8C FE000000JL flashget.0041DE7B
……
;下面这个CALL是计算KEY的长度的,要求的KEY的长度为0x2C,也就是44位
0041DD86|. E8 F4200B00 CALL flashget.004CFE7F
0041DD8B|. 8B55 00 MOV EDX,DWORD PTR SS:
0041DD8E|. 8B42 F8 MOV EAX,DWORD PTR DS:
0041DD91|. 83F8 2C CMP EAX,2C
0041DD94|. 0F85 E1000000JNZ flashget.0041DE7B
;下面是验证注册码的类型的,fgc-和fgf-两种KEY的验证算法是一的,
;但用来对KEY进行解密的密钥是不一样的,我们可以看到密钥类型的标志是存入DWORD PTR SS:
;这次破解我们用的是fgf-的类型的密钥
0041DD9A|. 68 B0E55200 PUSH flashget.0052E5B0 ;ASCII "fgc-"
0041DD9F|. 8BCD MOV ECX,EBP
0041DDA1|. E8 401D0B00 CALL flashget.004CFAE6
0041DDA6|. 85C0 TEST EAX,EAX
0041DDA8|. 75 06 JNZ SHORT flashget.0041DDB0
0041DDAA|. 895C24 10 MOV DWORD PTR SS:,EBX
0041DDAE|. EB 18 JMP SHORT flashget.0041DDC8
0041DDB0|> 68 A8E55200 PUSH flashget.0052E5A8 ;ASCII "fgf-"
0041DDB5|. 8BCD MOV ECX,EBP
0041DDB7|. E8 2A1D0B00 CALL flashget.004CFAE6
0041DDBC|. 85C0 TEST EAX,EAX
0041DDBE|. 0F85 B7000000JNZ flashget.0041DE7B
0041DDC4|. 894424 10 MOV DWORD PTR SS:,EAX
;下面是对KEY的验证算法
0041DDC8|> 6A 2C PUSH 2C
0041DDCA|. 8BCD MOV ECX,EBP
0041DDCC|. E8 7A680B00 CALL flashget.004D464B
0041DDD1|. 8BF8 MOV EDI,EAX
0041DDD3|. 33C9 XOR ECX,ECX
0041DDD5|. 83C7 04 ADD EDI,4
0041DDD8|. 33F6 XOR ESI,ESI
分析下面一个循环,我们把每一段KEY的四们定义成ABCD,则有
0041DDDA|> 8B07 /MOV EAX,DWORD PTR DS:
0041DDDC|. 8BD6 |MOV EDX,ESI
0041DDDE|. 83C7 04 |ADD EDI,4
0041DDE1|. 83EA 00 |SUB EDX,0 ;Switch (cases 0..2)
0041DDE4|. 894424 1C |MOV DWORD PTR SS:,EAX
0041DDE8|. 74 26 |JE SHORT flashget.0041DE10
0041DDEA|. 4A |DEC EDX
0041DDEB|. 74 17 |JE SHORT flashget.0041DE04
0041DDED|. 4A |DEC EDX
0041DDEE|. 75 38 |JNZ SHORT flashget.0041DE28
0041DDF0|. 0FBE4C24 1E |MOVSX ECX,BYTE PTR SS: ;Case 2 of switch 0041DDE1
0041DDF5|. 0FBED4 |MOVSX EDX,AH
0041DDF8|. 0FAFCA |IMUL ECX,EDX
0041DDFB|. 0FBE5424 1F |MOVSX EDX,BYTE PTR SS:
0041DE00|. 03CA |ADD ECX,EDX
0041DE02|. EB 1F |JMP SHORT flashget.0041DE23
;ECX = B * C + D
0041DE04|> 0FBE4C24 1E |MOVSX ECX,BYTE PTR SS: ;Case 1 of switch 0041DDE1
0041DE09|. 0FBED4 |MOVSX EDX,AH
0041DE0C|. 23CA |AND ECX,EDX
0041DE0E|. EB 0B |JMP SHORT flashget.0041DE1B
;ECX = C AND B
0041DE10|> 8A4C24 1E |MOV CL,BYTE PTR SS: ;Case 0 of switch 0041DDE1
0041DE14|. 8AD4 |MOV DL,AH
0041DE16|. 33CA |XOR ECX,EDX
0041DE18|. 83E1 7F |AND ECX,7F
;ECX = C XOR B,不要被后面的那个AND ECX,7F迷惑了,它只不过是用来把高位屏蔽的
0041DE1B|> 0FBE5424 1F |MOVSX EDX,BYTE PTR SS:
0041DE20|. 0FAFCA |IMUL ECX,EDX
;ECX = ECX * D
0041DE23|> 0FBEC0 |MOVSX EAX,AL
0041DE26|. 03C8 |ADD ECX,EAX
;ECX = ECX + A
;处理后那些跳转,可以得到
;Case 0:ECX = (C XOR B) * D + A
;Case 1:ECX = (C AND B) * D + A
;Case 2:ECX = B * C + D + A
;下面是用验证密钥来对算得的ECX值进行验证,我们来看它的密钥获取方法
;密钥存放在DS:起始的一段空间,为kevinhyx12345,
;如果KEY的第一段为fgf-,运算所用到的密钥是顺序从这个字符串中读取的,
;如果KEY的第一段是fgc-,运算所用到的密钥是顺序在Case 2的时候会从DS:中读取,即密钥的第四位: i
0041DE28|> 8B4424 10 |MOV EAX,DWORD PTR SS: ;Default case of switch 0041DDE1
0041DE2C|. 85C0 |TEST EAX,EAX
0041DE2E|. 74 0C |JE SHORT flashget.0041DE3C
0041DE30|. 0FBE1D 2BC7520>|MOVSX EBX,BYTE PTR DS:
0041DE37|. 83FE 02 |CMP ESI,2
0041DE3A|. 74 07 |JE SHORT flashget.0041DE43
0041DE3C|> 0FBE9E 28C7520>|MOVSX EBX,BYTE PTR DS:
;对于运算结果的验证也很简单,只是用密钥的ASC码来除ECX中的值,余数在EDX中。
0041DE43|> 8BC1 |MOV EAX,ECX
0041DE45|. 33D2 |XOR EDX,EDX
0041DE47|. F7F3 |DIV EBX
;以上是对指定段的KEY的验证运算,下面是对结果的判断
0041DE49|. 8BC6 |MOV EAX,ESI
0041DE4B|. 83E8 00 |SUB EAX,0 ;Switch (cases 0..2)
0041DE4E|. 74 13 |JE SHORT flashget.0041DE63
0041DE50|. 48 |DEC EAX
0041DE51|. 74 09 |JE SHORT flashget.0041DE5C
0041DE53|. 48 |DEC EAX
0041DE54|. 75 11 |JNZ SHORT flashget.0041DE67
;余数是否为0
0041DE56|. 85D2 |TEST EDX,EDX ;Case 2 of switch 0041DE4B
0041DE58|. 75 18 |JNZ SHORT flashget.0041DE72
0041DE5A|. EB 0B |JMP SHORT flashget.0041DE67
;余数是否为8
0041DE5C|> 83FA 08 |CMP EDX,8 ;Case 1 of switch 0041DE4B
0041DE5F|. 75 11 |JNZ SHORT flashget.0041DE72
0041DE61|. EB 04 |JMP SHORT flashget.0041DE67
;余数是否为0
0041DE63|> 85D2 |TEST EDX,EDX ;Case 0 of switch 0041DE4B
0041DE65|. 75 0B |JNZ SHORT flashget.0041DE72
0041DE67|> 46 |INC ESI ;Default case of switch 0041DE4B
0041DE68|. 83FE 03 |CMP ESI,3
0041DE6B|. 7D 23 |JGE SHORT flashget.0041DE90
0041DE6D|.^E9 68FFFFFF \JMP flashget.0041DDDA
所以这三段的KEY的验证算法是:
Case 0(B XOR C) * D + A) MOD X = 0,这儿X是'k'
Case 1(B AND C) * D + A) MOD X = 0,这儿X是'e'
Case 2B * C + D + A) MOD X = 0,对于fgf-类的KEY,这儿X是'v';对于fgc-类的KEY,这儿X是'i'
LeNgHost告诉我,FlashGet会在一段时间后验证第四段KEY,于是我就在程序正常运行后在那段已经读入内存的KEY上下了内存断点,并在RegPass也下了断点。出去逛完一个下午后……中断成功了……
0042514C|. 8B48 10 MOV ECX,DWORD PTR DS:
0042514F|. 83C0 10 ADD EAX,10
00425152|. 894C24 08 MOV DWORD PTR SS:,ECX
00425156|. 6A FF PUSH -1
00425158|. 0FBE4424 0E MOVSX EAX,BYTE PTR SS:
0042515D|. 0FBED5 MOVSX EDX,CH
00425160|. 0BC2 OR EAX,EDX
00425162|. 0FBE5424 0F MOVSX EDX,BYTE PTR SS:
00425167|. 0FAFC2 IMUL EAX,EDX
0042516A|. 0FBEC9 MOVSX ECX,CL
0042516D|. 03C1 ADD EAX,ECX
;跟踪分析得EAX = (B OR C) * D + A
0042516F|. 33D2 XOR EDX,EDX
;验证用的密钥直接来自DS:,哈哈,就是'i'
00425171|. 0FBE0D 2BC7520>MOVSX ECX,BYTE PTR DS:
00425178|. F7F1 DIV ECX
0042517A|. 8BCE MOV ECX,ESI
;判断余数是否为0
0042517C|. 85D2 TEST EDX,EDX
0042517E|. 74 1E JE SHORT flashget.0042519E
所以这一段的算法是((B OR C) * D + A) MOD X = 0,这儿X是'i'
只要KEY能符合这四个条件就可以了。我用VB做出了对应的算号器代码:
Randomize
Dim intEbx As Integer
Dim i As Integer, j As Integer, k As Integer, intChar As Integer
Dim strCode As String
If fgf Then
strCode = "fgf-"
intEbx = 118
Else
strCode = "fgc-"
intEbx = 105
End If
Do
intChar = 97 + Int(Rnd() * 25)
For i = 48 To 57
For j = 48 To 57
For k = 48 To 57
If (((i Xor j) And 127) * k + intChar) Mod 107 = 0 Then
strCode = strCode & Chr(intChar) & Chr(i) & Chr(j) & Chr(k)
Exit Do
End If
Next k
Next j
Next i
Loop
Do
intChar = 97 + Int(Rnd() * 25)
For i = 48 To 57
For j = 48 To 57
For k = 48 To 57
If ((i And j) * k + intChar) Mod 101 = 8 Then
strCode = strCode & Chr(intChar) & Chr(i) & Chr(j) & Chr(k)
Exit Do
End If
Next k
Next j
Next i
Loop
Do
intChar = 97 + Int(Rnd() * 25)
For i = 48 To 57
For j = 48 To 57
For k = 48 To 57
If (i * j + k + intChar) Mod intEbx = 0 Then
strCode = strCode & Chr(intChar) & Chr(i) & Chr(j) & Chr(k)
Exit Do
End If
Next k
Next j
Next i
Loop
Do
intChar = 97 + Int(Rnd() * 25)
For i = 48 To 57
For j = 48 To 57
For k = 48 To 57
If ((i Or j) * k + intChar) Mod 105 = 0 Then
strCode = strCode & Chr(intChar) & Chr(i) & Chr(j) & Chr(k)
Exit Do
End If
Next k
Next j
Next i
Loop
'后面的24位随机生成。
For i = 1 To 6
intChar = 97 + Int(Rnd() * 25)
strCode = strCode & Chr(intChar)
For j = 1 To 3
intChar = 48 + Int(Rnd() * 9)
strCode = strCode & Chr(intChar)
Next j
Next i
最后字符串strCode就是所要求的KEY
页:
[1]