首页
社区
课程
招聘
[原创]对[FCG]KeyGen2.0按钮特效的分析3、4、5
2007-8-7 19:52 6832

[原创]对[FCG]KeyGen2.0按钮特效的分析3、4、5

2007-8-7 19:52
6832
首先,废话几句。不知道有没有人还记得这个系列?在下因为个人原因,暂停了很久。不过最近在努力继续写。敬请期待……

另:如果您发现有错误/值得讨论的地方,请告诉我。

==========================================
    sub_406A1F中一共使用了3个func:sub_406B69、sub_406B89、sub_406D7D。

    首先看sub_406B69:

seg000:00406B69 sub_406B69      proc near               ; CODE XREF: sub_406A1F+B
seg000:00406B69                                         ; sub_406AED+A ...
seg000:00406B69
seg000:00406B69 arg_0           = dword ptr  8
//从前面的分析知道这个arg是窗口的句柄
seg000:00406B69
seg000:00406B69                 push    ebp
seg000:00406B6A                 mov     ebp, esp
seg000:00406B6C                 mov     edx, [ebp+arg_0]
seg000:00406B6F                 mov     eax, ds:dword_40A150
//即上文的WinPropLinkHead
seg000:00406B74                 test    eax, eax
seg000:00406B76                 jz      short loc_406B83
//为null
seg000:00406B78
seg000:00406B78 loc_406B78:                             ; CODE XREF: sub_406B69+18
seg000:00406B78                 cmp     edx, [eax]
//非空指针,将指针指向结构的CurrentWindow和参数比较
//其实就是寻找参数对应的窗口是否有相应的控制参数块
seg000:00406B7A                 jz      short loc_406B85
//找到,直接返回指针,即eax
seg000:00406B7C                 mov     eax, [eax+10h]
//取下一块的地址
seg000:00406B7F                 test    eax, eax
//下一块的地址是否是null
seg000:00406B81                 jnz     short loc_406B78
//不是null则循环,否则表示已到链尾
seg000:00406B83
seg000:00406B83 loc_406B83:                             ; CODE XREF: sub_406B69+D
seg000:00406B83                 xor     eax, eax
//直接返回null
seg000:00406B85
seg000:00406B85 loc_406B85:                             ; CODE XREF: sub_406B69+11
seg000:00406B85                 pop     ebp
seg000:00406B86                 retn    4
seg000:00406B86 sub_406B69      endp

    这个函数很容易写出:
    Function FindWindowInChain(Window:HWND):PWindowProperty;
    Begin
      Result:=WinPropLinkHead;
      
      While (Result<>Nil) Do
        Begin
          If Result^.CurrentWindow=Window Then
            Begin
              Break;
            End;
          Result:=Result^.NextWindowProperty;
        End;
    End;

    这样,前面的程序也需要修改。但是最好等到最后整理的时候再改。
    
    sub_406B89:

seg000:00406B89 sub_406B89      proc near               ; CODE XREF: sub_406A1F+19
seg000:00406B89
seg000:00406B89 ClassName       = byte ptr -104h
seg000:00406B89 hWnd            = dword ptr  8
seg000:00406B89
seg000:00406B89                 push    ebp
seg000:00406B8A                 mov     ebp, esp
seg000:00406B8C                 add     esp, 0FFFFFEFCh
//猜测是对齐
seg000:00406B92                 push    ebx
seg000:00406B93                 push    esi
//函数功能开始
seg000:00406B94                 mov     esi, [ebp+hWnd]
//参数
seg000:00406B97                 push    104h            ; nMaxCount
seg000:00406B9C                 lea     eax, [ebp+ClassName]
seg000:00406BA2                 push    eax             ; lpClassName
seg000:00406BA3                 push    esi             ; hWnd
seg000:00406BA4                 call    GetClassNameA
seg000:00406BA9                 xor     ebx, ebx
seg000:00406BAB
seg000:00406BAB loc_406BAB:                             ; CODE XREF: sub_406B89+41
seg000:00406BAB                 mov     eax, ebx
seg000:00406BAD                 shl     eax, 5
//这里实际是乘以20,字符串数组的第1维大小
seg000:00406BB0                 add     eax, offset dword_40A154
//字符串数组的地址
seg000:00406BB5                 push    eax
seg000:00406BB6                 lea     edx, [ebp+ClassName]
seg000:00406BBC                 push    edx
seg000:00406BBD                 call    lstrcmpi
seg000:00406BC2                 test    eax, eax
seg000:00406BC4                 jz      short loc_406BCC
//该窗口的类名符合条件
seg000:00406BC6                 inc     ebx
seg000:00406BC7                 cmp     ebx, 2
seg000:00406BCA                 jb      short loc_406BAB
//数组就2个元素
seg000:00406BCC
seg000:00406BCC loc_406BCC:                             ; CODE XREF: sub_406B89+3B
seg000:00406BCC                 sub     ebx, 1
seg000:00406BCF                 jb      short loc_406BD5
//是Button类
seg000:00406BD1                 jz      short loc_406BF2
//是Edit类
seg000:00406BD3                 jmp     short loc_406BF9
//都不是
seg000:00406BD5
seg000:00406BD5 loc_406BD5:                             ; CODE XREF: sub_406B89+46
seg000:00406BD5                 push    0FFFFFFF0h
//GWL_STYLE
seg000:00406BD7                 push    esi
seg000:00406BD8                 call    GetWindowLongA_0
seg000:00406BDD                 mov     ebx, eax
seg000:00406BDF                 and     ebx, 1Fh
seg000:00406BE2                 sub     ebx, 2
seg000:00406BE5                 jb      short loc_406BE9
seg000:00406BE7                 jmp     short loc_406BED
seg000:00406BE9
seg000:00406BE9 loc_406BE9:                             ; CODE XREF: sub_406B89+5C
seg000:00406BE9                 xor     ebx, ebx
seg000:00406BEB                 jmp     short loc_406BFC
seg000:00406BED
seg000:00406BED loc_406BED:                             ; CODE XREF: sub_406B89+5E
seg000:00406BED                 or      ebx, 0FFFFFFFFh
seg000:00406BF0                 jmp     short loc_406BFC
seg000:00406BF2
seg000:00406BF2 loc_406BF2:                             ; CODE XREF: sub_406B89+48
seg000:00406BF2                 mov     ebx, 1
seg000:00406BF7                 jmp     short loc_406BFC
seg000:00406BF9
seg000:00406BF9 loc_406BF9:                             ; CODE XREF: sub_406B89+4A
seg000:00406BF9                 or      ebx, 0FFFFFFFFh
seg000:00406BFC
seg000:00406BFC loc_406BFC:                             ; CODE XREF: sub_406B89+62
seg000:00406BFC                                         ; sub_406B89+67 ...
seg000:00406BFC                 mov     eax, ebx
seg000:00406BFE                 pop     esi
seg000:00406BFF                 pop     ebx
seg000:00406C00                 mov     esp, ebp
seg000:00406C02                 pop     ebp
seg000:00406C03                 retn    4
seg000:00406C03 sub_406B89      endp

    这个函数比较麻烦。因为dword_40A154数组的元素是按照32个字节对齐的,而我在D5里无法写出对应的形式。当然,可以用Array of Char解决这个问题,但是这样一是比较麻烦,二是我得完全按照汇编来写而不能享受数组的方便快捷。所以我在这里不打算做直接的对照翻译。等价的形式会更快。 

    Const
      Classes:Array[0..1] of PChar=('Button','Edit');
      
    Function sub_406B89(Window:HWND):Integer;
    Var
      ClassName:PChar;
      i:LongWord;
    Begin
      GetMem(ClassName,$104);
      GetClassName(Window,ClassName,$104);
    
      For i:=0 To 1 Do
        Begin
          If lstrcmpi(ClassName,Classes[i])=0 Then Break;
        End;
        
      Case i of
        0:
        Begin
          If GetWindowLong(Window,GWL_STYLE) AND $1F<2 Then
            Begin
              Result:=0;
            End
          Else
            Begin
              Result:=-1;
            End;
        End;
        1:
        Result:=1;
      Else
        Result:=-1;
      End;
    End;


=========================================

第4、5篇均在第一页

====================================

补充一下,00406BBD处的窗口类名比较时使用的类名实际是和程序有关的。在此例中,窗口由RC建立,所以类名为Button等……

[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞7
打赏
分享
最新回复 (13)
雪    币: 26415
活跃值: (18468)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2007-8-7 19:55
2
0
终于盼来了,非常地精彩。
那2篇和这篇会一起收录到《看雪论坛精华9》中去。;)
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
newkey 2007-8-7 20:04
3
0
upupup
雪    币: 375
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
firstrose 16 2007-8-7 20:11
4
0
抱歉,这篇其实不怎么样。

预告:4#长度为18k,等到5#写完后发出(周五前)。
雪    币: 433
活跃值: (176)
能力值: ( LV13,RANK:1250 )
在线值:
发帖
回帖
粉丝
冲天剑 31 2007-8-7 22:39
5
0
请问楼主,这是把同一篇文章拆成几块来发吗?

早知道可以这样,我想我的精华数还会更多些的……
雪    币: 3684
活跃值: (1036)
能力值: (RANK:760 )
在线值:
发帖
回帖
粉丝
cnbragon 18 2007-8-9 10:54
6
0
又见firstrose大大的大作,学习。。。
雪    币: 253
活跃值: (266)
能力值: ( LV12,RANK:220 )
在线值:
发帖
回帖
粉丝
WiNrOOt 5 2007-8-9 11:41
7
0
又见Bra
雪    币: 375
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
firstrose 16 2007-8-9 13:51
8
0
对[FCG]KeyGen2.0按钮特效的分析4

    粗略看了一下sub_406D7D,发现其中有很多对程序里其它函数的调用。所以这部分延后分析。

    sub_406D7D调用了以下函数:sub_406B69、sub_406974、sub_4070D9、sub_407274,其中sub_406B69已经分析。

seg000:00406974 sub_406974      proc near               ; CODE XREF: sub_406D7D+53
seg000:00406974                                         ; sub_406D7D+80 ...
seg000:00406974
seg000:00406974 arg_4           = dword ptr  0Ch
seg000:00406974 arg_8           = dword ptr  10h
seg000:00406974
seg000:00406974                 push    ebp
seg000:00406975                 mov     ebp, esp
seg000:00406977                 mov     eax, [ebp+arg_4]
seg000:0040697A                 cmp     [ebp+arg_8], 0
seg000:0040697E                 jnz     short loc_406982
seg000:00406980                 not     eax
seg000:00406982
seg000:00406982 loc_406982:                             ; CODE XREF: sub_406974+A
seg000:00406982                 pop     ebp
seg000:00406983                 retn
seg000:00406983 sub_406974      endp

    逻辑非常简单:如果参数3为0则返回参数2的反值,否则直接返回参数2。从堆栈看,有参数1,只是被忽略了。
    Function sub_406974(param1:LongWord;param2:LongWord;param3:LongWord)
    Begin
      If param3=0 Then
        Result:=param2 XOR $FFFFFFFF
      Else
        Result:=param2;
    End;

    sub_4070D9调用了sub_406C06、sub_406F99、sub_406CA5三个函数。

seg000:00406C06 sub_406C06      proc near               ; CODE XREF: sub_4070D9+25
seg000:00406C06
seg000:00406C06 Rect            = tagRECT ptr -10h
seg000:00406C06 arg_0           = dword ptr  8
seg000:00406C06
seg000:00406C06                 push    ebp
seg000:00406C07                 mov     ebp, esp
seg000:00406C09                 add     esp, 0FFFFFFF0h
//分配临时变量
seg000:00406C0C                 push    ebx
seg000:00406C0D                 mov     ebx, [ebp+arg_0]
//ebx=arg0
seg000:00406C10                 lea     eax, [ebp+Rect]
seg000:00406C13                 push    eax             ; lpRect
seg000:00406C14                 push    dword ptr [ebx] ; hWnd
//从这里可以看出,arg0实际是指针,指向的结构体开始部分为窗口句柄
seg000:00406C16                 call    GetWindowRect
seg000:00406C1B                 push    dword ptr [ebx] ; hWnd
seg000:00406C1D                 call    GetWindowDC
seg000:00406C22                 mov     [ebx+4], eax
//将对应的DC保存到结构体的[4]
seg000:00406C25                 push    dword ptr [ebx+4] ; HDC
seg000:00406C28                 call    CreateCompatibleDC
seg000:00406C2D                 mov     [ebx+8], eax
//memdc
seg000:00406C30                 push    1               ; int
seg000:00406C32                 push    dword ptr [ebx+8] ; HDC
seg000:00406C35                 call    SetBkMode
seg000:00406C3A                 cmp     dword ptr [ebx+10h], 0
//如果结构体的[10h]是0
seg000:00406C3E                 jz      short loc_406C4D
//非0就直接选择对象
seg000:00406C40                 push    dword ptr [ebx+10h] ; HGDIOBJ
seg000:00406C43                 push    dword ptr [ebx+8] ; HDC
seg000:00406C46                 call    SelectObject
seg000:00406C4B                 jmp     short loc_406C6F
seg000:00406C4D
seg000:00406C4D loc_406C4D:                             ; CODE XREF: sub_406C06+38
seg000:00406C4D                 mov     edx, [ebp+Rect.bottom]
seg000:00406C50                 sub     edx, [ebp+Rect.top]
seg000:00406C53                 push    edx             ; int
seg000:00406C54                 mov     ecx, [ebp+Rect.right]
seg000:00406C57                 sub     ecx, [ebp+Rect.left]
seg000:00406C5A                 push    ecx             ; int
seg000:00406C5B                 push    dword ptr [ebx+4] ; HDC
seg000:00406C5E                 call    CreateCompatibleBitmap
seg000:00406C63                 push    eax             ; HGDIOBJ
seg000:00406C64                 push    dword ptr [ebx+8] ; HDC
seg000:00406C67                 call    SelectObject
seg000:00406C6C                 mov     [ebx+10h], eax
//看来[10h]是bitmap的句柄
seg000:00406C6F
seg000:00406C6F loc_406C6F:                             ; CODE XREF: sub_406C06+45
seg000:00406C6F                 cmp     dword ptr [ebx+0Ch], 1
seg000:00406C73                 jnz     short loc_406C9B
//[0ch]是什么,从下文看不出
seg000:00406C75                 push    0CC0020h        ; DWORD
//SRCCOPY
seg000:00406C7A                 push    0               ; int
seg000:00406C7C                 push    0               ; int
seg000:00406C7E                 push    dword ptr [ebx+4] ; HDC
seg000:00406C81                 mov     eax, [ebp+Rect.bottom]
seg000:00406C84                 sub     eax, [ebp+Rect.top]
seg000:00406C87                 push    eax             ; int
seg000:00406C88                 mov     edx, [ebp+Rect.right]
seg000:00406C8B                 sub     edx, [ebp+Rect.left]
seg000:00406C8E                 push    edx             ; int
seg000:00406C8F                 push    0               ; int
seg000:00406C91                 push    0               ; int
seg000:00406C93                 push    dword ptr [ebx+8] ; HDC
seg000:00406C96                 call    BitBlt
//保存原始DC?
seg000:00406C9B
seg000:00406C9B loc_406C9B:                             ; CODE XREF: sub_406C06+6D
seg000:00406C9B                 mov     eax, [ebx+8]
//返回MEM DC的句柄
seg000:00406C9E                 pop     ebx
seg000:00406C9F                 mov     esp, ebp
seg000:00406CA1                 pop     ebp
seg000:00406CA2                 retn    4
seg000:00406CA2 sub_406C06      endp

Type
  WindowsDCInfo=Record
    hWindow:HWND;
    WinDC:HDC;
    CompDC:HDC;
    unknown:LongWord;
    hBitmap:HBITMAP;
  End;
  PWindowsDCInfo=^WindowsDCInfo;

Function sub_406C06(Var DCInfo:WindowsDCInfo):HDC;
Var
  Rect:TRect;
Begin
  GetWindowRect(DCInfo.hWindow,Rect);
  DCInfo.WinDC:=GetWindowDC(DCInfo.hWindow);
  DCInfo.CompDC:=CreateCompatibleDC(DCInfo.WinDC);
  SetBkMode(DCInfo.CompDC,TRANSPARENT);
  
  If DCInfo.hBitmap<>0 Then
    Begin
      SelectObject(DCInfo.CompDC,DCInfo.hBitmap);
    End
  Else
    Begin
      DCInfo.hBitmap:=CreateCompatibleBitmap(DCInfo.WinDC,Rect.right-Rect.left,Rect.bottom-Rect.top);
      SelectObject(DCInfo.CompDC,DCInfo.hBitmap);
    End;
    
  If DCInfo.unknown=1 Then
    Begin
      BitBlt(DCInfo.CompDC,0,0,Rect.right-Rect.left,Rect.bottom-Rect.top,DCInfo.WinDC,0,0,SRCCOPY);
    End;
    
  Result:=DCInfo.CompDC;

End;


    显然,某些东西依然未知。

    看起来,sub_406F99就是生成渐变的核心过程。各位打起精神来! 首先,从GradientFill的两个call得到,var_48处是一个Arrayp[0..3] of TRIVERTEX的结构数组。var_54和var_8分别是GRADIENT_TRIANGLE和GRADIENT_RECT。但d5里对于TRIVERTEX的定义似乎有问题:COLOR16是8位而不是16位。最好的办法是自己重新写定义。

seg000:00406F99 ; int __stdcall sub_406F99(HDC,int,int)
seg000:00406F99 sub_406F99      proc near               ; CODE XREF: sub_4070D9+DC
seg000:00406F99                                         ; sub_4070D9+F0
seg000:00406F99
seg000:00406F99 var_54          = dword ptr -54h
seg000:00406F99 var_50          = dword ptr -50h
seg000:00406F99 var_4C          = dword ptr -4Ch
seg000:00406F99 var_48          = dword ptr -48h
seg000:00406F99 var_8           = dword ptr -8
seg000:00406F99 var_4           = dword ptr -4
seg000:00406F99 arg_0           = dword ptr  8
seg000:00406F99 arg_4           = dword ptr  0Ch
seg000:00406F99 arg_8           = dword ptr  10h
seg000:00406F99
seg000:00406F99                 push    ebp
seg000:00406F9A                 mov     ebp, esp
seg000:00406F9C                 add     esp, 0FFFFFFACh
//分配局部堆栈变量
seg000:00406F9F                 push    ebx
seg000:00406FA0                 push    esi
seg000:00406FA1                 push    edi
seg000:00406FA2                 mov     eax, [ebp+arg_8]
//eax=arg_8
seg000:00406FA5                 mov     edx, [ebp+arg_4]
//edx=arg_4
seg000:00406FA8                 lea     esi, [ebp+var_48]
seg000:00406FAB                 xor     ebx, ebx
//ebx=0
seg000:00406FAD
seg000:00406FAD loc_406FAD:                             ; CODE XREF: sub_406F99+70
seg000:00406FAD                 xor     ecx, ecx
seg000:00406FAF                 mov     cl, [eax+ebx*4]
//arg_8应该是指针
seg000:00406FB2                 shl     ecx, 8
//ecx=((eax+ebx*4)^) shl 8
seg000:00406FB5                 mov     edi, ebx
seg000:00406FB7                 shl     edi, 4
seg000:00406FBA                 mov     [esi+edi+8], cx
//注意:TRIVERTEX长度为10h=4h shl 4,所以这里应该写成
//var_48[ebx].Red=ecx and $FFFF
seg000:00406FBF                 movzx   ecx, word ptr [eax+ebx*4]
seg000:00406FC3                 sar     ecx, 8
seg000:00406FC6                 and     ecx, 0FFh
seg000:00406FCC                 shl     ecx, 8
//ecx=(((arg_8+ebx*4)^ sar 8)and $ff) shl 8
seg000:00406FCF                 mov     edi, ebx
seg000:00406FD1                 shl     edi, 4
seg000:00406FD4                 mov     [esi+edi+0Ah], cx
//var_48[ebx].Green=ecx and $FFFF
seg000:00406FD9                 mov     ecx, [eax+ebx*4]
seg000:00406FDC                 shr     ecx, 10h
seg000:00406FDF                 and     ecx, 0FFh
seg000:00406FE5                 shl     ecx, 8
seg000:00406FE8                 mov     edi, ebx
seg000:00406FEA                 shl     edi, 4
seg000:00406FED                 mov     [esi+edi+0Ch], cx
//var_48[ebx].Blue=(((arg_8+ebx*4)^ shr $10)and $ff) shl 8
seg000:00406FF2                 mov     ecx, [eax+ebx*4]
seg000:00406FF5                 shr     ecx, 18h
seg000:00406FF8                 shl     ecx, 8
seg000:00406FFB                 mov     edi, ebx
seg000:00406FFD                 shl     edi, 4
seg000:00407000                 mov     [esi+edi+0Eh], cx
//var_48[ebx].Alpha=(((arg_8^+ebx*4) shr $18) shl 8) and $ffff
seg000:00407005                 inc     ebx
seg000:00407006                 cmp     ebx, 4
seg000:00407009                 jl      short loc_406FAD
//loc_406FAD到此为一个循环
//for ebx:=0 to 3 do ....
//综合一下,arg_8的结构应该是Array[0..3] of DWORD,元素的结构为TColorRef,但是最高8位为Alpha值
seg000:0040700B                 mov     ecx, [edx]
seg000:0040700D                 mov     [esi], ecx
//看来arg_4也是指针
//var48[0].x=arg_4^
seg000:0040700F                 mov     ecx, [edx+4]
seg000:00407012                 mov     [esi+4], ecx
//var48[0].y=arg_4^[4]
seg000:00407015                 mov     ecx, [edx+8]
seg000:00407018                 lea     ebx, [esi+10h]
seg000:0040701B                 mov     [ebx], ecx
//var48[1].x=arg_4^[8]
seg000:0040701D                 mov     ecx, [edx+4]
seg000:00407020                 lea     ebx, [esi+10h]
seg000:00407023                 mov     [ebx+4], ecx
//var48[1].y=arg_4^[4]
seg000:00407026                 mov     ecx, [edx]
seg000:00407028                 lea     ebx, [esi+20h]
seg000:0040702B                 mov     [ebx], ecx
//var48[2].x=arg_4^
seg000:0040702D                 mov     ecx, [edx+0Ch]
seg000:00407030                 lea     ebx, [esi+20h]
seg000:00407033                 mov     [ebx+4], ecx
//var48[2].y=arg_4^[$c]
seg000:00407036                 mov     ecx, [edx+8]
seg000:00407039                 lea     ebx, [esi+30h]
seg000:0040703C                 mov     [ebx], ecx
//var48[3].x=arg_4^[$8]
seg000:0040703E                 mov     edx, [edx+0Ch]
seg000:00407041                 lea     ecx, [esi+30h]
seg000:00407044                 mov     [ecx+4], edx
//var48[3].y=arg_4^[$c]
//看来arg_4指向的应该是rect结构
seg000:00407047                 mov     edx, [eax]
seg000:00407049                 cmp     edx, [eax+8]
seg000:0040704C                 jnz     short loc_407054
//if arg_8^<>arg_8^[8] then goto loc_407054
seg000:0040704E                 mov     ecx, [eax+4]
seg000:00407051                 cmp     ecx, [eax+0Ch]
//无实际用途?
seg000:00407054
seg000:00407054 loc_407054:                             ; CODE XREF: sub_406F99+B3
seg000:00407054                 mov     edx, [eax]
seg000:00407056                 cmp     edx, [eax+4]
seg000:00407059                 jnz     short loc_40706A
//if arg_8^<>arg_8^[4] then goto loc_40706A
seg000:0040705B                 mov     ecx, [eax+8]
seg000:0040705E                 cmp     ecx, [eax+0Ch]
seg000:00407061                 jnz     short loc_40706A
//if arg_8^[8]<>arg_8^[$c] then goto loc_40706A
seg000:00407063                 mov     ebx, 1
//ebx=GRADIENT_FILL_RECT_V
seg000:00407068                 jmp     short loc_40706F
seg000:0040706A
seg000:0040706A loc_40706A:                             ; CODE XREF: sub_406F99+C0
seg000:0040706A                                         ; sub_406F99+C8
seg000:0040706A                 mov     ebx, 2
//ebx=GRADIENT_FILL_TRIANGLE
seg000:0040706F
seg000:0040706F loc_40706F:                             ; CODE XREF: sub_406F99+CF
seg000:0040706F                 cmp     ebx, 2
seg000:00407072                 jnz     short loc_407089
//if ebx<>GRADIENT_FILL_TRIANGLE then goto loc_407089
seg000:00407074                 xor     eax, eax
seg000:00407076                 mov     [ebp+var_54], eax
seg000:00407079                 mov     [ebp+var_50], 1
seg000:00407080                 mov     [ebp+var_4C], 2
//var_54.Vertex1=0
//var_54.Vertex2=1
//var_54.Vertex3=2
seg000:00407087                 jmp     short loc_407095
seg000:00407089
seg000:00407089 loc_407089:                             ; CODE XREF: sub_406F99+D9
seg000:00407089                 xor     edx, edx
seg000:0040708B                 mov     [ebp+var_8], edx
seg000:0040708E                 mov     [ebp+var_4], 3
//var_8.UpperLeft=0
//var_8.LowerRight=3
seg000:00407095
seg000:00407095 loc_407095:                             ; CODE XREF: sub_406F99+EE
seg000:00407095                 push    ebx             ; ULONG
seg000:00407096                 push    1               ; ULONG
seg000:00407098                 cmp     ebx, 2
seg000:0040709B                 jnz     short loc_4070A2
seg000:0040709D                 lea     ecx, [ebp+var_54]
seg000:004070A0                 jmp     short loc_4070A5
seg000:004070A2
seg000:004070A2 loc_4070A2:                             ; CODE XREF: sub_406F99+102
seg000:004070A2                 lea     ecx, [ebp+var_8]
seg000:004070A5
seg000:004070A5 loc_4070A5:                             ; CODE XREF: sub_406F99+107
seg000:004070A5                 push    ecx             ; PVOID
seg000:004070A6                 push    4               ; ULONG
seg000:004070A8                 push    esi             ; PTRIVERTEX
seg000:004070A9                 push    [ebp+arg_0]     ; HDC
seg000:004070AC                 call    GradientFill
//注意0040709B的判断
seg000:004070B1                 cmp     ebx, 2
seg000:004070B4                 jnz     short loc_4070D0
//如果ebx=GRADIENT_FILL_TRIANGLE,那么继续
seg000:004070B6                 mov     [ebp+var_54], 3
//var_54.Vertex1=3
seg000:004070BD                 push    2               ; ULONG
//GRADIENT_FILL_TRIANGLE
seg000:004070BF                 push    1               ; ULONG
seg000:004070C1                 lea     eax, [ebp+var_54]
seg000:004070C4                 push    eax             ; PVOID
seg000:004070C5                 push    4               ; ULONG
seg000:004070C7                 push    esi             ; PTRIVERTEX
seg000:004070C8                 push    [ebp+arg_0]     ; HDC
seg000:004070CB                 call    GradientFill
seg000:004070D0
seg000:004070D0 loc_4070D0:                             ; CODE XREF: sub_406F99+11B
seg000:004070D0                 pop     edi
seg000:004070D1                 pop     esi
seg000:004070D2                 pop     ebx
seg000:004070D3                 mov     esp, ebp
seg000:004070D5                 pop     ebp
seg000:004070D6                 retn    0Ch
seg000:004070D6 sub_406F99      endp

    从调用代码看,这段代码没有返回值。下面的代码做了一点整理。

    
Type
  COLOR16 = Word;

  PTriVertex = ^TTriVertex;
  _TRIVERTEX = Packed Record
    x: Longint;
    y: Longint;
    Red: COLOR16;
    Green: COLOR16;
    Blue: COLOR16;
    Alpha: COLOR16;
  End;
  TTriVertex = _TRIVERTEX;
  TRIVERTEX = _TRIVERTEX;
  
  AlphaRGB=Packed Record
    Case Byte Of
    1:(
    Alpha:Byte;
    Blue:Byte;
    Green:Byte;
    Red:Byte);
    2:(
    ARGB:LongWord);
  End;

Procedure DoGradientFill(WinDC:HDC;DCRect:PRect;AlphaRGBArray:Array[0..3] of AlphaRGB);
Var
  GT:GRADIENT_TRIANGLE;
  TVs:Array[0..3] of TRIVERTEX;
  GR:GRADIENT_RECT;
  i:LongWord;
Begin

  For i:=0 To 3 Do
    Begin
      TVs[i].Red:=AlphaRGBArray[i].Red;
      TVs[i].Green:=AlphaRGBArray[i].Green;
      TVs[i].Blue:=AlphaRGBArray[i].Blue;
      TVs[i].Alpha:=AlphaRGBArray[i].Alpha;
    End;

  TVs[0].x:=DCRect^.Left;
  TVs[0].y:=DCRect^.Top;
  TVs[1].x:=DCRect^.Right;
  TVs[1].y:=DCRect^.Top;
  TVs[2].x:=DCRect^.Left;
  TVs[2].y:=DCRect^.Bottom;
  TVs[3].x:=DCRect^.Right;
  TVs[3].y:=DCRect^.Bottom;
  
  If (DCRect^.Left=DCRect^.Top) AND (DCRect^.Right=DCRect^.Bottom) Then
    Begin
      GR.UpperLeft:=0;
      GR.LowerRight:=3;
      GradientFill(WinDC,@TVs,4,@GR,1,GRADIENT_FILL_RECT_V);
    End
  Else
    Begin
      GT.Vertex1:=0;
      GT.Vertex2:=1;
      GT.Vertex3:=2;
      GradientFill(WinDC,@TVs,4,@GT,1,GRADIENT_FILL_TRIANGLE);

      GT.Vertex1:=3;
      GradientFill(WinDC,@TVs,4,@GT,1,GRADIENT_FILL_TRIANGLE);
    End;

End;


    小结:保持清醒的头脑是非常重要的。我曾经算错mov的地址,后来从头看才发现错误所在。

    OK,休息。
雪    币: 375
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
firstrose 16 2007-8-9 13:55
9
0
对[FCG]KeyGen2.0按钮特效的分析5

这个过程应该比较简单。

seg000:00406CA5 sub_406CA5      proc near               ; CODE XREF: sub_4070D9+18D
seg000:00406CA5
seg000:00406CA5 Rect            = tagRECT ptr -10h
seg000:00406CA5 arg_0           = dword ptr  8
seg000:00406CA5
seg000:00406CA5                 push    ebp
seg000:00406CA6                 mov     ebp, esp
seg000:00406CA8                 add     esp, 0FFFFFFF0h
seg000:00406CAB                 push    ebx
seg000:00406CAC                 mov     ebx, [ebp+arg_0]
seg000:00406CAF                 cmp     dword ptr [ebx+0Ch], 1
//arg_0又是指针
seg000:00406CB3                 jnz     short loc_406CE6
seg000:00406CB5                 lea     eax, [ebp+Rect]
seg000:00406CB8                 push    eax             ; lpRect
seg000:00406CB9                 push    dword ptr [ebx] ; hWnd
seg000:00406CBB                 call    GetWindowRect
seg000:00406CC0                 push    0CC0020h        ; DWORD
seg000:00406CC5                 push    0               ; int
seg000:00406CC7                 push    0               ; int
seg000:00406CC9                 push    dword ptr [ebx+8] ; HDC
seg000:00406CCC                 mov     edx, [ebp+Rect.bottom]
seg000:00406CCF                 sub     edx, [ebp+Rect.top]
seg000:00406CD2                 push    edx             ; int
seg000:00406CD3                 mov     ecx, [ebp+Rect.right]
seg000:00406CD6                 sub     ecx, [ebp+Rect.left]
seg000:00406CD9                 push    ecx             ; int
seg000:00406CDA                 push    0               ; int
seg000:00406CDC                 push    0               ; int
seg000:00406CDE                 push    dword ptr [ebx+4] ; HDC
seg000:00406CE1                 call    BitBlt
seg000:00406CE6
seg000:00406CE6 loc_406CE6:                             ; CODE XREF: sub_406CA5+E
seg000:00406CE6                 cmp     dword ptr [ebx+10h], 0
seg000:00406CEA                 jz      short loc_406CFD
seg000:00406CEC                 push    dword ptr [ebx+10h] ; HGDIOBJ
seg000:00406CEF                 push    dword ptr [ebx+8] ; HDC
seg000:00406CF2                 call    SelectObject
seg000:00406CF7                 push    eax             ; HGDIOBJ
seg000:00406CF8                 call    DeleteObject
seg000:00406CFD
seg000:00406CFD loc_406CFD:                             ; CODE XREF: sub_406CA5+45
seg000:00406CFD                 push    dword ptr [ebx+8] ; HDC
seg000:00406D00                 call    DeleteDC
seg000:00406D05                 push    dword ptr [ebx+4] ; hDC
seg000:00406D08                 push    dword ptr [ebx] ; hWnd
seg000:00406D0A                 call    ReleaseDC
seg000:00406D0F                 pop     ebx
seg000:00406D10                 mov     esp, ebp
seg000:00406D12                 pop     ebp
seg000:00406D13                 retn    4
seg000:00406D13 sub_406CA5      endp

    实在没有什么难度,注释都不必写。唯一值得注意的是,arg_0是个什么玩意。对照一下sub_406C06的分析,可以看出,arg_0就是WindowsDCInfo的指针。

Procedure sub_406CA5(DCInfo:PWindowsDCInfo);
Var
  Rect:TRect;
Begin
  If DCInfo^.unknown=1 Then
    Begin
      GetWindowRect(DCInfo.hWindow,Rect);
      BitBlt(DCInfo.WinDC,0,0,Rect.right-Rect.left,Rect.bottom-Rect.top,DCInfo.CompDC,0,0,SRCCOPY);
    End;
    
  If DCInfo^.hBitmap<>0 Then
    Begin
      DeleteObject(SelectObject(DCInfo.CompDC,DCInfo.hBitmap));
    End;
    
  DeleteDC(DCInfo.CompDC);
  ReleaseDC(DCInfo.hWindow,DCInfo.WinDC);
End;


    看来这段代码是释放sub_406C06生成的DC资源。
   
    终于开始分析sub_4070D9了:

seg000:004070D9 sub_4070D9      proc near               ; CODE XREF: sub_406D7D+5C
seg000:004070D9                                         ; sub_406D7D+89 ...
seg000:004070D9
seg000:004070D9 String          = byte ptr -124h
seg000:004070D9 var_24          = dword ptr -24h
seg000:004070D9 hDC             = dword ptr -1Ch
seg000:004070D9 var_18          = dword ptr -18h
seg000:004070D9 var_14          = dword ptr -14h
seg000:004070D9 var_10          = dword ptr -10h
seg000:004070D9 arg_0           = dword ptr  8
seg000:004070D9
seg000:004070D9                 push    ebp
seg000:004070DA                 mov     ebp, esp
seg000:004070DC                 add     esp, 0FFFFFEDCh
seg000:004070E2                 push    ebx
seg000:004070E3                 push    esi
seg000:004070E4                 push    edi
seg000:004070E5                 mov     ebx, [ebp+arg_0]
seg000:004070E8                 lea     edi, [ebp+var_10]
seg000:004070EB                 mov     eax, [ebx]
//arg_0仍然是指针
seg000:004070ED                 mov     [ebp+var_24], eax
//联系004070FE处代码,这里eax即arg_0^应该是窗口句柄。
seg000:004070F0                 xor     edx, edx
seg000:004070F2                 mov     [ebp+var_18], edx
//unknown
seg000:004070F5                 xor     ecx, ecx
seg000:004070F7                 mov     [ebp+var_14], ecx
//hBitmap
seg000:004070FA                 lea     eax, [ebp+var_24]
seg000:004070FD                 push    eax
seg000:004070FE                 call    sub_406C06
//内部调用
seg000:00407103                 push    edi             ; lpRect
seg000:00407104                 push    dword ptr [ebx] ; hWnd
seg000:00407106                 call    GetWindowRect
//var_10就是Rect了
seg000:0040710B                 mov     edx, [edi]
seg000:0040710D                 sub     [edi+8], edx
//var_10.right-=var_10.left
seg000:00407110                 mov     ecx, [edi+4]
seg000:00407113                 sub     [edi+0Ch], ecx
//var_10.bottom-=var_10.top
seg000:00407116                 xor     eax, eax
seg000:00407118                 mov     [edi+4], eax
//var_10.top=0
seg000:0040711B                 mov     [edi], eax
//var_10.left=0
seg000:0040711D                 test    byte ptr [ebx+8], 1
seg000:00407121                 jz      short loc_407131
//if arg_0^[8] and 1 =0 then goto loc_407131
seg000:00407123                 push    0Fh             ; nIndex
//COLOR_3DFACE
seg000:00407125                 call    GetSysColor
seg000:0040712A                 sub     eax, 202020h
seg000:0040712F                 jmp     short loc_407136
seg000:00407131
seg000:00407131 loc_407131:                             ; CODE XREF: sub_4070D9+48
seg000:00407131                 mov     eax, 733C00h
seg000:00407136
seg000:00407136 loc_407136:                             ; CODE XREF: sub_4070D9+56
seg000:00407136                 push    eax             ; COLORREF
seg000:00407137                 call    CreateSolidBrush
seg000:0040713C                 mov     esi, eax
//esi=hBrush
seg000:0040713E                 push    esi             ; hbr
seg000:0040713F                 push    edi             ; lprc
seg000:00407140                 push    [ebp+hDC]       ; hDC
seg000:00407143                 call    FrameRect
//这里的hDC实际是CompDC
seg000:00407148                 push    esi             ; HGDIOBJ
seg000:00407149                 call    DeleteObject
seg000:0040714E                 push    0FFFFFFFFh      ; dy
seg000:00407150                 push    0FFFFFFFFh      ; dx
seg000:00407152                 push    edi             ; lprc
seg000:00407153                 call    InflateRect
seg000:00407158                 test    byte ptr [ebx+8], 1
seg000:0040715C                 jz      short loc_40717C
//if arg_0^[8] and 1 =0 then goto loc_40717C
seg000:0040715E                 push    0EAF4F5h        ; COLORREF
seg000:00407163                 call    CreateSolidBrush
seg000:00407168                 mov     esi, eax
seg000:0040716A                 push    esi             ; hbr
seg000:0040716B                 push    edi             ; lprc
seg000:0040716C                 push    [ebp+hDC]       ; hDC
seg000:0040716F                 call    FillRect
seg000:00407174                 push    esi             ; HGDIOBJ
seg000:00407175                 call    DeleteObject
seg000:0040717A                 jmp     short loc_4071BA
seg000:0040717C
seg000:0040717C loc_40717C:                             ; CODE XREF: sub_4070D9+83
seg000:0040717C                 test    byte ptr [ebx+8], 2
//看来arg_0^[8]应该是位组合
seg000:00407180                 jz      short loc_407186
seg000:00407182                 xor     eax, eax
seg000:00407184                 jmp     short loc_4071A8
seg000:00407186
seg000:00407186 loc_407186:                             ; CODE XREF: sub_4070D9+A7
seg000:00407186                 test    byte ptr [ebx+8], 4
seg000:0040718A                 jz      short loc_407190
seg000:0040718C                 xor     eax, eax
seg000:0040718E                 jmp     short loc_4071A8
seg000:00407190
seg000:00407190 loc_407190:                             ; CODE XREF: sub_4070D9+B1
seg000:00407190                 test    byte ptr [ebx+8], 8
seg000:00407194                 jnz     short loc_40719C
seg000:00407196                 test    byte ptr [ebx+8], 10h
seg000:0040719A                 jz      short loc_4071A3
seg000:0040719C
seg000:0040719C loc_40719C:                             ; CODE XREF: sub_4070D9+BB
seg000:0040719C                 mov     eax, 2
seg000:004071A1                 jmp     short loc_4071A8
seg000:004071A3
seg000:004071A3 loc_4071A3:                             ; CODE XREF: sub_4070D9+C1
seg000:004071A3                 mov     eax, 2
//上面这一段代码有点奇怪。特别是40719A。怀疑是原作者削掉了一些条件值。
seg000:004071A8
seg000:004071A8 loc_4071A8:                             ; CODE XREF: sub_4070D9+AB
seg000:004071A8                                         ; sub_4070D9+B5 ...
seg000:004071A8                 shl     eax, 4
seg000:004071AB                 add     eax, offset dword_40A19C
//dword_40A19C应该是数组首地址。注意这里的eax计算,暗示这是3*4的AlphaRGB
seg000:004071B0                 push    eax             ; int
seg000:004071B1                 push    edi             ; int
seg000:004071B2                 push    [ebp+hDC]       ; HDC
seg000:004071B5                 call    sub_406F99
seg000:004071BA
seg000:004071BA loc_4071BA:                             ; CODE XREF: sub_4070D9+A1
seg000:004071BA                 test    byte ptr [ebx+8], 2
seg000:004071BE                 jz      short loc_4071CE
seg000:004071C0                 push    offset dword_40A1CC ; int
seg000:004071C5                 push    edi             ; int
seg000:004071C6                 push    [ebp+hDC]       ; HDC
seg000:004071C9                 call    sub_406F99
seg000:004071CE
seg000:004071CE loc_4071CE:                             ; CODE XREF: sub_4070D9+E5
seg000:004071CE                 test    byte ptr [ebx+8], 8
seg000:004071D2                 jz      short loc_4071E7
seg000:004071D4                 push    0FFFFFFFFh      ; dy
seg000:004071D6                 push    0FFFFFFFFh      ; dx
seg000:004071D8                 push    edi             ; lprc
seg000:004071D9                 call    InflateRect
seg000:004071DE                 push    edi             ; lprc
seg000:004071DF                 push    [ebp+hDC]       ; hDC
seg000:004071E2                 call    DrawFocusRect
seg000:004071E7
seg000:004071E7 loc_4071E7:                             ; CODE XREF: sub_4070D9+F9
seg000:004071E7                 push    100h            ; nMaxCount
seg000:004071EC                 lea     edx, [ebp+String]
seg000:004071F2                 push    edx             ; lpString
seg000:004071F3                 push    dword ptr [ebx] ; hWnd
seg000:004071F5                 call    GetWindowTextA
//取得窗口标题,最多256字节
seg000:004071FA                 test    eax, eax
seg000:004071FC                 jz      short loc_40725B
seg000:004071FE                 test    byte ptr [ebx+8], 2
seg000:00407202                 jz      short loc_40720E
seg000:00407204                 push    1               ; dy
seg000:00407206                 push    1               ; dx
seg000:00407208                 push    edi             ; lprc
seg000:00407209                 call    OffsetRect
seg000:0040720E
seg000:0040720E loc_40720E:                             ; CODE XREF: sub_4070D9+129
seg000:0040720E                 test    byte ptr [ebx+8], 1
seg000:00407212                 jz      short loc_40721B
seg000:00407214                 mov     ecx, 94A2A5h
seg000:00407219                 jmp     short loc_40721D
seg000:0040721B
seg000:0040721B loc_40721B:                             ; CODE XREF: sub_4070D9+139
seg000:0040721B                 xor     ecx, ecx
seg000:0040721D
seg000:0040721D loc_40721D:                             ; CODE XREF: sub_4070D9+140
seg000:0040721D                 push    ecx             ; COLORREF
seg000:0040721E                 push    [ebp+hDC]       ; HDC
seg000:00407221                 call    SetTextColor
seg000:00407226                 push    0
seg000:00407228                 push    0
seg000:0040722A                 push    31h
//WM_GETFONT
seg000:0040722C                 push    dword ptr [ebx]
seg000:0040722E                 call    SendMessageA_0
seg000:00407233                 push    eax             ; HGDIOBJ
seg000:00407234                 push    [ebp+hDC]       ; HDC
seg000:00407237                 call    SelectObject
seg000:0040723C                 mov     esi, eax
seg000:0040723E                 push    25h
//DT_SINGLELINE+DT_VCENTER+DT_CENTER
seg000:00407240                 push    edi
seg000:00407241                 push    0FFFFFFFFh
seg000:00407243                 lea     eax, [ebp+String]
seg000:00407249                 push    eax
seg000:0040724A                 push    [ebp+hDC]
seg000:0040724D                 call    DrawTextA_0
seg000:00407252                 push    esi             ; HGDIOBJ
seg000:00407253                 push    [ebp+hDC]       ; HDC
seg000:00407256                 call    SelectObject
seg000:0040725B
seg000:0040725B loc_40725B:                             ; CODE XREF: sub_4070D9+123
seg000:0040725B                 mov     [ebp+var_18], 1
seg000:00407262                 lea     edx, [ebp+var_24]
seg000:00407265                 push    edx
seg000:00407266                 call    sub_406CA5
seg000:0040726B                 pop     edi
seg000:0040726C                 pop     esi
seg000:0040726D                 pop     ebx
seg000:0040726E                 mov     esp, ebp
seg000:00407270                 pop     ebp
seg000:00407271                 retn    4
seg000:00407271 sub_4070D9      endp

    通过查找引用,可以知道arg_0是PWindowProperty类型的。

Const
  ARGBs:Array[0..2] of Array[0..3] of AlphaRGB=
  (
  ((ARGB:$A5B2B5),(ARGB:$CED7D6),(ARGB:$CED7D6),(ARGB:$DEEFF7)),
  ((ARGB:$CEF3FF),(ARGB:$63CBFF),(ARGB:$63CBFF),(ARGB:$31B2FF)),
  ((ARGB:$FAE3BA),(ARGB:$CCA372),(ARGB:$BC9362),(ARGB:$BE9463))
  )
  ;

  GradientARGBs:Array[0..3] of AlphaRGB=
    ((ARGB:$DEE3E7),(ARGB:$E7E7E7),(ARGB:$DEE3E7),(ARGB:$FFDEE3E7));

Procedure sub_4070D9(wp:PWindowProperty);
Var
  title:Array[0..256] of Char;
  r:Rect;
  DCInfo:WindowsDCInfo;
  Brush:HBRUSH;
  color:COLORREF;
  clrindex:Byte;
  fnt:HFONT;

Begin
  DCInfo.hWindow:=wp^.CurrentWindow;
  DCInfo.unknown:=0;
  DCInfo.hBitmap:=0;
  sub_406C06(DCInfo);

  GetWindowRect(wp^.CurrentWindow,r);
  r.right:=r.right-r.left;
  r.bottom:=r.bottom-r.top;
  r.top:=0;
  r.left:=0;

  If wp^.Preserve2 AND 1<>0 Then
    Begin
      color:=GetSysColor(COLOR_3DFACE)-$202020;
    End
  Else
    Begin
      color:=$733C00;
    End;

  Brush:=CreateSolidBrush(color);
  FrameRect(DCInfo.CompDC,r,Brush);
  DeleteObject(Brush);
  
  InflateRect(r,-1,-1);

  If wp^.Preserve2 AND 1<>0 Then
    Begin
      Brush:=CreateSolidBrush($EAF4F5);
      FillRect(DCInfo.CompDC,r,Brush);
      DeleteObject(Brush);
    End
  Else
    Begin

      If (wp^.Preserve2 AND 2=0) AND (wp^.Preserve2 AND 4=0) Then
        Begin
          clrindex:=2;
        End
      Else
        Begin
          clrindex:=0;
        End;

      sub_406F99(DCInfo.CompDC,r,ARGBs[clrindex]);
    End;
    
  If wp^.Preserve2 AND 2<>0 Then
    Begin
      DoGradientFill(DCInfo.CompDC,r,GradientARGBs);
    End;

  If wp^.Preserve2 AND 8<>0 Then
    Begin
      InflateRect(r,-1,-1);
      DrawFocusRect(DCInfo.CompDC,r);
    End;

  If GetWindowText(wp^.CurrentWindow,@title,$100)<>0 Then
    Begin
      If wp^.Preserve2 AND 2<>0 Then
        Begin
          OffsetRect(r,1,1);
        End;

      If wp^.Preserve2 AND 1<>0 Then
        Begin
          clrindex:=94A2A5h
        End
      Else
        Begin
          clrindex:=0;
        End;
        
      SetTextColor(DCInfo.CompDC,clrindex);
      fnt:=SelectObject(DCInfo.CompDC,SendMessage(wp^.CurrentWindow,WM_GETFONT,0,0));
      DrawTextA(DCInfo.CompDC,@title,-1,r);
      SelectObject(DCInfo.CompDC,fnt);
    End;

  DCInfo.unknown:=1;
  sub_406CA5(DCInfo);
End;


    我不得不说,这段函数确实够长……换句话说,长得该死……
    不过,wp^.Preserve2到底是什么玩意,确实值得分析。
雪    币: 1687
活跃值: (681)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
yijun8354 12 2007-8-9 17:06
10
0
支持+学习~~~
雪    币: 204
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
网络阿牛 2007-8-9 21:12
11
0
太强了,呵呵,支持
雪    币: 107
活跃值: (55)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
xy2000 1 2007-8-10 13:22
12
0
这个应该是很久前的一个东东了,难得还有人记得
雪    币: 375
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
firstrose 16 2007-8-10 19:46
13
0
已更新,第6篇(结局)写作中,将另开帖。请耐心等待。
雪    币: 1022
活跃值: (31)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
lingyu 1 2007-8-11 00:08
14
0
支持
游客
登录 | 注册 方可回帖
返回