首页
社区
课程
招聘
[原创]ty123 Crackme 6破解分析
发表于: 2007-2-7 13:33 6659

[原创]ty123 Crackme 6破解分析

2007-2-7 13:33
6659

【文章标题】: ty123 Crackme 6破解分析
【文章作者】: netwind
【下载地址】: http://bbs.pediy.com/attachment.php?s=&attachmentid=4377
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  用od载入
  右键-查找-当前模块中的名称,右击GetDlgtemTextA选择在每个参考点上设置断点。
  点击菜单查看-查看断点,有两处断点
  Breakpoints
  地址          模块          激活                       反汇编                                注释
  004010D8      ty123_Cr      始终                         call    <jmp.&user32.GetDlgItemTextA
  0040124A      ty123_Cr      始终                         jmp     [<&user32.GetDlgItemTextA>]
  删除0040124a出断点。
  执行程序,断在004010d8处,来到004010d8有如下代码:
  004010D8   .  E8 6D010000   call    <jmp.&user32.GetDlgItemTextA>   ; \获取输入的用户名
  004010DD   .  85C0          test    eax, eax                        ;  判断用户名长度,为0出错
  004010DF   .  0F84 E7000000 je      004011CC
  004010E5   .  3C 12         cmp     al, 12                          ;  用户名长度大于0x12出错
  004010E7   .  0F8F DF000000 jg      004011CC
  004010ED   .  8D75 E0       lea     esi, [ebp-20]
  004010F0   .  91            xchg    eax, ecx
  004010F1   .  33C0          xor     eax, eax
  004010F3   .  33D2          xor     edx, edx
  004010F5   >  AC            lods    byte ptr [esi]                  ;  此循环将用户名各字符16进制数相加,其和放在edx中
  004010F6   .  03D0          add     edx, eax
  004010F8   .^ E2 FB         loopd   short 004010F5
  004010FA   .  66:8915 5B304>mov     [40305B], dx                    ;  将相加所的和放入内存
  00401101   .  8D35 00304000 lea     esi, [403000]
  00401107   .  8D3D 11304000 lea     edi, [403011]
  0040110D   .  B1 0B         mov     cl, 0B
  0040110F   >  AC            lods    byte ptr [esi]
  00401110   .  3207          xor     al, [edi]
  00401112   .  AA            stos    byte ptr es:[edi]
  00401113   .^ E2 FA         loopd   short 0040110F                  ;  此处循环算法对注册没有用处
  00401115   .  68 78304000   push    00403078                        ; /Arg3 = 00403078
  0040111A   .  8D45 F8       lea     eax, [ebp-8]                    ; |
  0040111D   .  50            push    eax                             ; |Arg2
  0040111E   .  68 11304000   push    00403011                        ; |将keyfile文件名playboy.dat压栈
  00401123   .  E8 98010000   call    004012C0                        ; \获取keyfile中字符串
  00401128   .  85C0          test    eax, eax                        ;  Switch (cases 1..1)
  0040112A   .  0F84 9C000000 je      004011CC
  00401130   .  8B75 F8       mov     esi, [ebp-8]                    ;  把读取串地址给esi
  00401133   .  8935 7C304000 mov     [40307C], esi
  00401139   .  48            dec     eax
  0040113A   .  0F85 8C000000 jnz     004011CC
  00401140   .  83E9 30       sub     ecx, 30                         ;  keyfile内的串长度必须为0x30; Case 1 of switch 00401128
  00401143   .  0F85 83000000 jnz     004011CC
  00401149   .  B1 08         mov     cl, 8                           ;  比较8次
  0040114B   .  51            push    ecx
  0040114C   >  66:AD         lods    word ptr [esi]                  ;  每次从keyfile串取两字符,将高位-0x3c再于0x01ff比较,不相等就错
  0040114E   .  80EC 3C       sub     ah, 3C
  00401151   .  66:3B05 59304>cmp     ax, [403059]
  00401158      75 72         jnz     short 004011CC
  0040115A   .^ E2 F0         loopd   short 0040114C
  0040115C   .  8D3D 00304000 lea     edi, [403000]                   ;  取字符串ty123[DFCG]ty123地址
  00401162   .  8D1D 21214000 lea     ebx, [402121]                   ;  取字符串Registered User!地址
  00401168   .  B1 10         mov     cl, 10                          ;  比较0x10次
  0040116A   >  AC            lods    byte ptr [esi]                  ;  此循环从上次算法取keyfile字符结束处取字符每字符都与ty123[DFCG]ty123 xor运算
  0040116B   .  3207          xor     al, [edi]                       ;  运算所得每一字符同Registered User!每一字符比较不同则错。
  0040116D   .  3A03          cmp     al, [ebx]
  0040116F      75 5B         jnz     short 004011CC
  00401171   .  43            inc     ebx
  00401172   .  47            inc     edi
  00401173   .^ E2 F5         loopd   short 0040116A
  00401175   .  B1 08         mov     cl, 8
  00401177   >  66:AD         lods    word ptr [esi]                  ;  接着上次算法取keyfile字符结束处取字符
  00401179   .  80EC 2C       sub     ah, 2C
  0040117C   .  66:3B05 5B304>cmp     ax, [40305B]
  00401183      75 47         jnz     short 004011CC
  00401185   .^ E2 F0         loopd   short 00401177                  ;  此循环每次取两字符,将高位-0x2c后再与0x02f9(用户名字符相加的和)比较不同则错
  00401187   .  A1 58114000   mov     eax, [401158]
  0040118C   .  3105 02304000 xor     [403002], eax
  00401192   .  3305 6D114000 xor     eax, [40116D]
  00401198   .  3105 06304000 xor     [403006], eax
  0040119E   .  3305 83114000 xor     eax, [401183]
  004011A4   .  3105 0B304000 xor     [40300B], eax
  004011AA   .  FF35 5D304000 push    dword ptr [40305D]              ; /Arg4 = 00000010
  004011B0   .  68 00304000   push    00403000                        ; |Arg3 = 00403000
  004011B5   .  FF35 61304000 push    dword ptr [403061]              ; |Arg2 = 0000003B
  004011BB   .  68 1D304000   push    0040301D                        ; |Arg1 = 0040301D ASCII "Congratulations! We are happy to read your solution soon ;)"
  004011C0   .  E8 9B000000   call    00401260                        ; \获得成功提示信息
  004011C5   .  68 1D304000   push    0040301D                        ;  ASCII "Congratulations! We are happy to read your solution soon ;)"
  004011CA   .  EB 05         jmp     short 004011D1                  ;  将成功信息压栈,完成破解,
  004011CC   >  68 0C214000   push    0040210C                        ;  ASCII "Unregistered Version"; Default case of switch 00401128
  004011D1   >  68 ED030000   push    3ED                             ; |ControlID = 3ED (1005.)
  004011D6   .  FF75 08       push    dword ptr [ebp+8]               ; |hWnd
  004011D9   .  E8 78000000   call    <jmp.&user32.SetDlgItemTextA>   ; \SetDlgItemTextA
  
  用户明:netwind
keyfile:playboy.dat
keyfile内容:????????&V[@/!4}!
T@????????
--------------------------------------------------------------------------------
【经验总结】
  我们将0xff01+0x3c重复8次作为keyfile前0x10个字符,
  将Registered User!每一字符同ty123[DFCG]ty123每一字符xor所得字符作为中间16个字符
  将用户名各字符和高位和底位交换(比如和为0x02ff交换后为0xff02)再+0x2c所得结果重复8次作为keyfile后16个字符
  就得到keyfile正确字符串。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年02月07日 13:30:58


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (8)
雪    币: 242
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
Originally posted by netwind
【文章标题】: ty123 Crackme 6破解分析
【文章作者】: netwind
【下载地址】: http://bbs.pediy.com/attachment.php?s=&attachmentid=4377
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
........


好快的剑!祝贺netwind大侠!

源代码解压密码:Hola a todos, me llamo ty123

Until next time...
2007-2-7 13:49
0
雪    币: 297
活跃值: (21)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
3
最初由 netwind 发布
我们将0xff01+0x3c重复8次作为keyfile前0x10个字符


并不会都是0xff01,这个数是和硬盘序号有关的,将所得的硬盘序号各字节累加才得到这个数~!,如果你的硬盘序号是:0x4454BE8E,则0x44+0x54+0xBE+0x8e=0x01E4,该数为0xE401
2007-2-7 14:39
0
雪    币: 297
活跃值: (21)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
4
具体是这里:
......
0040104D   .  6A 00         PUSH    0                                ; /pFileSystemNameSize = NULL; Case 110 (WM_INITDIALOG) of switch 00401046
0040104F   .  6A 00         PUSH    0                                ; |pFileSystemNameBuffer = NULL
00401051   .  6A 00         PUSH    0                                ; |pFileSystemFlags = NULL
00401053   .  6A 00         PUSH    0                                ; |pMaxFilenameLength = NULL
00401055   .  8D45 FC       LEA     EAX, DWORD PTR SS:[EBP-4]        ; |
00401058   .  50            PUSH    EAX                              ; |pVolumeSerialNumber
00401059   .  6A 00         PUSH    0                                ; |MaxVolumeNameSize = 0
0040105B   .  6A 00         PUSH    0                                ; |VolumeNameBuffer = NULL
0040105D   .  68 08214000   PUSH    00402108                         ; |c:\unregistered versionregistered user!
00401062   .  E8 BF010000   CALL    <JMP.&kernel32.GetVolumeInformat>; \GetVolumeInformationA
00401067   .  48            DEC     EAX
00401068   .  6A 04         PUSH    4
0040106A   .  59            POP     ECX
0040106B   .  33D2          XOR     EDX, EDX
0040106D   .  8D75 FC       LEA     ESI, DWORD PTR SS:[EBP-4]
00401070   >  AC            LODS    BYTE PTR DS:[ESI]
00401071   .  03D0          ADD     EDX, EAX
00401073   .^ E2 FB         LOOPD   SHORT 00401070
00401075   .  66:8915 59304>MOV     WORD PTR DS:[403059], DX
......
2007-2-7 14:43
0
雪    币: 242
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
Originally posted by dewar
并不会都是0xff01,这个数是和硬盘序号有关的,将所得的硬盘序号各字节累加才得到这个数~!,如果你的硬盘序号是:0x4454BE8E,则0x44+0x54+0xBE+0x8e=0x01E4,该数为0xE401


dewar大侠说得有道理!

原本今天再发一个2004年写的Reverseme,结果提示一天只能发3个贴,控制太严了吧,呵呵。

再次感谢各位大侠关注。
2007-2-7 14:47
0
雪    币: 10885
活跃值: (3288)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
6
非常感谢赐教.
开始看到GetVolumeInformationA
这个函数了,在程序开头,没怎么留心它,
曾尝试找0xff01哪里算的,
我把断点下在了GetDlgItemTextA
每次到这 0xff01就已经算出来了,
我就以为是个固定的数字

感谢,加上这段才完整.
2007-2-7 14:47
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
谢谢!!!

2007-2-9 12:06
0
雪    币: 220
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
不厚道啊不厚道,刚看到CM就看到tut了;弄的我等菜鸟没得玩了,不支持
2007-2-10 09:57
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
netwind破这个估计花了不到30分钟吧。。。今天才看到,恰好没看到教程,所以就自己研究了一下。。。现把报告贴这里应该没问题吧。。。

请诸位大侠赐教。

有几年没有玩crack了,才发现已经很生疏了,于是找了一个简单的Crackme玩玩,没想到花了近3小时……
很多基础知识不熟悉……后来用C++写KeyGen也不顺利……汇编很简单的语言用c要用指针倒来倒去的……
下面是简单的报告:

拿到ty123 Crackme6.exe,先用IDA反汇编。
代码很清晰,很有可能是用Win32Asm写的。
看关键的处理对话框消息的函数:

.text:0040103D ; *************** S U B R O U T I N E ***************************************
.text:0040103D
.text:0040103D ; Attributes: bp-based frame
.text:0040103D
.text:0040103D ; BOOL __stdcall DialogFunc(HWND,UINT,WPARAM,LPARAM)
.text:0040103D DialogFunc      proc near               ; DATA XREF: start+Eo
.text:0040103D
.text:0040103D String          = byte ptr -20h
.text:0040103D var_8           = dword ptr -8
.text:0040103D VolumeSerialNumber= dword ptr -4
.text:0040103D hDlg            = dword ptr  8
.text:0040103D arg_4           = dword ptr  0Ch
.text:0040103D arg_8           = dword ptr  10h
.text:0040103D
.text:0040103D                 push    ebp
.text:0040103E                 mov     ebp, esp
.text:00401040                 add     esp, 0FFFFFFE0h
.text:00401043                 mov     eax, [ebp+arg_4]
.text:00401046                 cmp     eax, 110h
.text:0040104B                 jnz     short loc_401081
.text:0040104B                                            ;应该是初始化函数
.text:0040104D                 push    0               ; nFileSystemNameSize
.text:0040104F                 push    0               ; lpFileSystemNameBuffer
.text:00401051                 push    0               ; lpFileSystemFlags
.text:00401053                 push    0               ; lpMaximumComponentLength
.text:00401055                 lea     eax, [ebp+VolumeSerialNumber]
.text:00401058                 push    eax             ; lpVolumeSerialNumber
.text:00401059                 push    0               ; nVolumeNameSize
.text:0040105B                 push    0               ; lpVolumeNameBuffer
.text:0040105D                 push    offset RootPathName ; "c:\\"
.text:00401062                 call    GetVolumeInformationA ;获得C盘的序列号(在格式化时被操作系统赋值)
.text:00401062
.text:00401067                 dec     eax
.text:00401068                 push    4
.text:0040106A                 pop     ecx
.text:0040106B                 xor     edx, edx
.text:0040106D                 lea     esi, [ebp+VolumeSerialNumber]
.text:0040106D
.text:00401070
.text:00401070 loc_401070:                             ; CODE XREF: DialogFunc+36j
.text:00401070                 lodsb
.text:00401071                 add     edx, eax ;将序列号的4个字节相加
.text:00401073                 loop    loc_401070
.text:00401073
.text:00401075                 mov     word_403059, dx ;保存到这里
.text:0040107C                 jmp     loc_401211
.text:0040107C
.text:00401081 ; ---------------------------------------------------------------------------
.text:00401081
.text:00401081 loc_401081:                             ; CODE XREF: DialogFunc+Ej
.text:00401081                 cmp     eax, 111h      
.text:00401086                 jnz     loc_4011F7
.text:00401086
.text:0040108C                 mov     eax, [ebp+arg_8] ;关于菜单
.text:0040108F                 and     eax, 0FFFFh
.text:00401094                 cmp     eax, 3EFh
.text:00401099                 jnz     short loc_4010B4
.text:00401099
.text:0040109B                 push    40h             ; uType
.text:0040109D                 push    offset Caption  ; "About..."
.text:004010A2                 push    offset Text     ; "Simple crackme for newbie.\r\nYou have to"...
.text:004010A7                 push    [ebp+hDlg]      ; hWnd
.text:004010AA                 call    MessageBoxA
.text:004010AA
.text:004010AF                 jmp     loc_401211
.text:004010AF
.text:004010B4 ; ---------------------------------------------------------------------------
.text:004010B4
.text:004010B4 loc_4010B4:                             ; CODE XREF: DialogFunc+5Cj
.text:004010B4                 cmp     eax, 3ECh        
.text:004010B9                 jnz     loc_4011EC
.text:004010B9
.text:004010BF                 push    18h                 ;注册按钮
.text:004010C1                 lea     eax, [ebp+String]
.text:004010C4                 push    eax
.text:004010C5                 call    RtlZeroMemory    ;将18h个单位的空间清零
.text:004010C5
.text:004010CA                 push    18h             ; nMaxCount
.text:004010CC                 lea     eax, [ebp+String]
.text:004010CF                 push    eax             ; lpString
.text:004010D0                 push    3EBh            ; nIDDlgItem
.text:004010D5                 push    [ebp+hDlg]      ; hDlg
.text:004010D8                 call    GetDlgItemTextA ;获取文本框中的文字,保存到String变量
.text:004010D8
.text:004010DD                 test    eax, eax        ;如果文字长度为0
.text:004010DF                 jz      loc_4011CC    ;失败
.text:004010DF
.text:004010E5                 cmp     al, 12h        ;是否大于12h=18
.text:004010E7                 jg      loc_4011CC    ;若大于,失败
.text:004010E7
.text:004010ED                 lea     esi, [ebp+String]
.text:004010F0                 xchg    eax, ecx
.text:004010F1                 xor     eax, eax
.text:004010F3                 xor     edx, edx
.text:004010F3
.text:004010F5
.text:004010F5 loc_4010F5:                             ; CODE XREF: DialogFunc+BBj
.text:004010F5                 lodsb
.text:004010F6                 add     edx, eax
.text:004010F8                 loop    loc_4010F5    ;将输入的文字按字节相加
.text:004010F8
.text:004010FA                 mov     word_40305B, dx    ;保存于此
.text:00401101                 lea     esi, s_Ty123DfcgTy12 ; "ty123[DFCG]ty123"
.text:00401107                 lea     edi, unk_403011
.text:0040110D                 mov     cl, 0Bh    ;操作0Bh=11个字符
.text:0040110D
.text:0040110F
.text:0040110F loc_40110F:                             ; CODE XREF: DialogFunc+D6j
.text:0040110F                 lodsb
.text:00401110                 xor     al, [edi]    ;把"ty123[DFCG]"的第i个字符和目标字符串的第i个数据做异或
.text:00401112                 stosb
.text:00401113                 loop    loc_40110F    ;通过OllyIce在此处下端点,知异或最后结果是playboy.dat
.text:00401113
.text:00401115                 push    offset unk_403078 ; int    ;下面的函数返回文件长度于此
.text:0040111A                 lea     eax, [ebp+var_8]            ;返回文件内容于此
.text:0040111D                 push    eax             ; int
.text:0040111E                 push    offset unk_403011 ; lpFileName
.text:00401123                 call    sub_4012C0    ;函数,打开playboy.dat
.text:00401123
.text:00401128                 test    eax, eax        ;如果文件不存在
.text:0040112A                 jz      loc_4011CC    ;失败
.text:0040112A
.text:00401130                 mov     esi, [ebp+var_8]
.text:00401133                 mov     hMem, esi    ;hMem=文件内容
.text:00401139                 dec     eax            ;eax=0
.text:0040113A                 jnz     loc_4011CC   
.text:0040113A
.text:00401140                 sub     ecx, 30h        ;减48
.text:00401143                 jnz     loc_4011CC    ;若不等于0失败,所以文件长度=48
.text:00401143
.text:00401149                 mov     cl, 8
.text:0040114B                 push    ecx
.text:0040114B
.text:0040114C
.text:0040114C loc_40114C:                             ; CODE XREF: DialogFunc+11Dj
.text:0040114C                 lodsw                    ;对每两个字符
.text:0040114E                 sub     ah, 3Ch            ;对第二个字符减3Ch=60
.text:00401151                 cmp     ax, word_403059    ;把两个字节拼起来,和这个变量比较(其实就是C盘的序列号)
.text:00401151
.text:00401158
.text:00401158 loc_401158:                             ; DATA XREF: DialogFunc+14Ar
.text:00401158                 jnz     short loc_4011CC    ;不等于就失败
.text:00401158
.text:0040115A                 loop    loc_40114C        ;循环8次,也就是读取16个字符
.text:0040115A
.text:0040115C                 lea     edi, s_Ty123DfcgTy12 ; "ty123[DFCG]ty123"
.text:00401162                 lea     ebx, s_RegisteredUse ; "Registered User!"
.text:00401168                 mov     cl, 10h
.text:00401168
.text:0040116A
.text:0040116A loc_40116A:                             ; CODE XREF: DialogFunc+136j
.text:0040116A                 lodsb
.text:0040116B                 xor     al, [edi]        ;把下一个输入字符挨个和"ty123[DFCG]ty123"做异或
.text:0040116B
.text:0040116D
.text:0040116D loc_40116D:                             ; DATA XREF: DialogFunc+155r
.text:0040116D                 cmp     al, [ebx]        ;判断是否等于"Registered User!"对应的字符
.text:0040116F                 jnz     short loc_4011CC    ;不等于,失败
.text:0040116F
.text:00401171                 inc     ebx
.text:00401172                 inc     edi
.text:00401173                 loop    loc_40116A        ;一共16个字符
.text:00401173                                            ;这里可以算出这16个字符应该是什么
                                                        ;只要把上面两个字符串相应位置作异或
.text:00401175                 mov     cl, 8
.text:00401175
.text:00401177
.text:00401177 loc_401177:                             ; CODE XREF: DialogFunc+148j
.text:00401177                 lodsw                    ;下面16个字节,每两个字节一组
.text:00401179                 sub     ah, 2Ch            ;高位减2Ch后
.text:0040117C                 cmp     ax, word_40305B     ;应该等于文本框输入字串和
.text:0040117C
.text:00401183
.text:00401183 loc_401183:                             ; DATA XREF: DialogFunc+161r
.text:00401183                 jnz     short loc_4011CC
.text:00401183
.text:00401185                 loop    loc_401177
.text:00401185
.text:00401187                 mov     eax, dword ptr ds:loc_401158
.text:0040118C                 xor     dword ptr s_Ty123DfcgTy12+2, eax
.text:00401192                 xor     eax, dword ptr ds:loc_40116D
.text:00401198                 xor     dword ptr s_Ty123DfcgTy12+6, eax
.text:0040119E                 xor     eax, dword ptr ds:loc_401183
.text:004011A4                 xor     dword ptr s_Ty123DfcgTy12+0Bh, eax
.text:004011AA                 push    dword_40305D
.text:004011B0                 push    offset s_Ty123DfcgTy12 ; "ty123[DFCG]ty123"
.text:004011B5                 push    dword_403061
.text:004011BB                 push    offset unk_40301D
.text:004011C0                 call    sub_401260            ;解密成功信息(具体怎么解密的不高兴看了)
.text:004011C0
.text:004011C5                 push    offset unk_40301D
.text:004011CA                 jmp     short loc_4011D1
.text:004011CA
.text:004011CC ; ---------------------------------------------------------------------------
.text:004011CC
.text:004011CC loc_4011CC:                             ; CODE XREF: DialogFunc+A2j

.text:00401217
.text:00401217 DialogFunc      endp

根据上面的分析,写keygen.cpp,g++编译通过。

#include <stdio.h>
#include <windows.h>

const char filename[]="playboy.dat";
const char str1[]="ty123[DFCG]ty123";
const char str2[]="Registered User!";
DWORD serial;

int main()
{
        FILE *datf=fopen(filename, "wb");
        if (!GetVolumeInformation("C:\\",0,0,&serial,0,0,0,0)) exit(1);
        char *p = (char *)&serial;
        unsigned short data1=0;
        for (int i=0; i<4;i++)
                data1 += (unsigned short)(unsigned char)*(p+i);
        p = (char*)&data1;
        *(p+1) += 0x3C;
        for (int i=0;i<8;i++)
                fprintf(datf, "%c%c",*p,*(p+1));
       
        for (int i=0;i<16;i++)
                fprintf(datf,"%c",str1[i] ^ str2[i]);
       
        char name[19];
        printf("Input your name(later enter this name to Crackme): ");
        scanf("%s", &name);
        unsigned short data2=0;
        for (int i=0;name[i];i++) data2+=name[i];
        p = (char*)&data2;
        *(p+1) += 0x2C;
        for (int i=0;i<8;i++)
                fprintf(datf,"%c%c", *p, *(p+1));
       
        return 0;
}
2007-2-11 21:46
0
游客
登录 | 注册 方可回帖
返回
//