Eagle 发表于 2004-11-1 13:35:00

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]
查看完整版本: Eagle的破文:(重写)FlashGet1.65的算号器