首页
社区
课程
招聘
[原创]逆向MmGetPhysicalAddress并正向
2010-11-18 17:00 13421

[原创]逆向MmGetPhysicalAddress并正向

2010-11-18 17:00
13421
  这两天想做点坏事,也没啥,就是PTE欺骗啦。
  其中涉及了VirtualAddress(VA)转化PhysicalAddress(PA)的生成原理。
  于是网上找了些相关资料,很努力地看。
  但看来看去,怎么和MmGetPhysicalAddress逆向结果不大一样啊。
  这才发现,大部分现存的资料都很旧了。虽然应用原理还是差不多,但是已经不能被我们伸手党使用了。
  于是决定逆向一下MmGetPhysicalAddress,再正向它,尝试C++实现之。
----_HARDWARE_PTE结构
lkd> dt _hardware_pte
nt!_HARDWARE_PTE
   +0x000 Valid            : Pos 0, 1 Bit
   +0x000 Write            : Pos 1, 1 Bit
   +0x000 Owner            : Pos 2, 1 Bit
   +0x000 WriteThrough     : Pos 3, 1 Bit
   +0x000 CacheDisable     : Pos 4, 1 Bit
   +0x000 Accessed         : Pos 5, 1 Bit
   +0x000 Dirty            : Pos 6, 1 Bit
   +0x000 LargePage        : Pos 7, 1 Bit
   +0x000 Global           : Pos 8, 1 Bit
   +0x000 CopyOnWrite      : Pos 9, 1 Bit
   +0x000 Prototype        : Pos 10, 1 Bit
   +0x000 reserved0        : Pos 11, 1 Bit
   +0x000 PageFrameNumber  : Pos 12, 26 Bits
   +0x000 reserved1        : Pos 38, 26 Bits
   +0x000 LowPart          : Uint4B
   +0x004 HighPart         : Uint4B

由此,可以列出如下结构:
typedef struct _HARDWARE_PTE_X86PAE
  {
  union
    {
    struct
      {
      ULONGLONG Valid:1;
      ULONGLONG Write:1;
      ULONGLONG Owner:1;
      ULONGLONG WriteThrough:1;
      ULONGLONG CacheDisable:1;
      ULONGLONG Accessed:1;
      ULONGLONG Dirty:1;
      ULONGLONG LargePage:1;
      ULONGLONG Global:1;
      ULONGLONG CopyOnWrite:1;
      ULONGLONG Prototype:1;
      ULONGLONG reserved0:1;
      ULONGLONG PageFrameNumber:26;
      ULONGLONG reserved1:26;
      };
    struct
      {
      ULONG LowPart;
      ULONG HighPart;
      };
    };
  } HARDWARE_PTE_X86PAE, *PHARDWARE_PTE_X86PAE,MMPTE_HARDWARE, *PMMPTE_HARDWARE,_MMPTE_HARDWARE,HARDWARE_PTE,*PHARDWARE_PTE;

  注意,由于PAE模式下,PTE结构突破32位,所以结构体使用位域的时候,需要用__int64来做(2 byte)。
  之前我做PTE结构时,使用ulong来做位域,无论是否强制结构体对齐,结果编译器硬要把这个结构识别为3 byte。汗死。
  直到后面xIkUg大哥提供旧式结构体后,我才发现之间的差异。
  不过xIkUg大哥提供的PTE结构指明PageFrameNumber:24;很奇怪。我在XP和2003上列表的结构都指明PageFrameNumber:26。所以,在实际应用时,大家还是用windbg看看自己的pte结构好了。免得出现意外。

----MmGetPhysicalAddress的IDA结果
;Microsoft Windows XP Professional Service Pack 3 [ver 5.1.2600]
;ntkrnlpa.exe
;MD5   : E7E72F0935D0F224768126B49CF2A9E8

.text:00430CD2                         _MmGetPhysicalAddress@4 proc near       ; CODE XREF: IoSetDumpRange(x,x,x,x)+22p
.text:00430CD2                                                                 ; IoSetDumpRange(x,x,x,x)+62p ...
.text:00430CD2
.text:00430CD2                         BaseAddress     = dword ptr  8
.text:00430CD2
.text:00430CD2 8B FF                                   mov     edi, edi
.text:00430CD4 55                                      push    ebp
.text:00430CD5 8B EC                                   mov     ebp, esp
.text:00430CD7 53                                      push    ebx
.text:00430CD8 56                                      push    esi
.text:00430CD9 57                                      push    edi
.text:00430CDA 8B 7D 08                                mov     edi, [ebp+BaseAddress]
.text:00430CDD 8B CF                                   mov     ecx, edi
.text:00430CDF C1 E9 12                                shr     ecx, 12h
.text:00430CE2 81 E1 F8 3F 00 00                       and     ecx, 3FF8h
.text:00430CE8 8B 81 00 00 60 C0                       mov     eax, [ecx+0C0600000h]
.text:00430CEE 8B 89 04 00 60 C0                       mov     ecx, [ecx+0C0600004h]
.text:00430CF4 BE 81 00 00 00                          mov     esi, 81h
.text:00430CF9 8B D0                                   mov     edx, eax
.text:00430CFB 23 D6                                   and     edx, esi
.text:00430CFD 33 DB                                   xor     ebx, ebx
.text:00430CFF 3B D6                                   cmp     edx, esi
.text:00430D01 75 1F                                   jnz     short loc_430D22
.text:00430D03 85 DB                                   test    ebx, ebx
.text:00430D05 75 1B                                   jnz     short loc_430D22
.text:00430D07 0F AC C8 0C                             shrd    eax, ecx, 0Ch
.text:00430D0B C1 E9 0C                                shr     ecx, 0Ch
.text:00430D0E 8B CF                                   mov     ecx, edi
.text:00430D10 C1 E9 0C                                shr     ecx, 0Ch
.text:00430D13 25 FF FF FF 03                          and     eax, 3FFFFFFh
.text:00430D18 81 E1 FF 01 00 00                       and     ecx, 1FFh
.text:00430D1E 03 C1                                   add     eax, ecx
.text:00430D20 EB 3F                                   jmp     short loc_430D61
.text:00430D22                         ; ---------------------------------------------------------------------------
.text:00430D22
.text:00430D22                         loc_430D22:                             ; CODE XREF: MmGetPhysicalAddress(x)+2Fj
.text:00430D22                                                                 ; MmGetPhysicalAddress(x)+33j
.text:00430D22 83 E0 01                                and     eax, 1
.text:00430D25 33 C9                                   xor     ecx, ecx
.text:00430D27 0B C1                                   or      eax, ecx
.text:00430D29 74 24                                   jz      short loc_430D4F
.text:00430D2B 8B CF                                   mov     ecx, edi
.text:00430D2D C1 E9 09                                shr     ecx, 9
.text:00430D30 81 E1 F8 FF 7F 00                       and     ecx, 7FFFF8h
.text:00430D36 8B 91 04 00 00 C0                       mov     edx, [ecx+0C0000004h]
.text:00430D3C 81 E9 00 00 00 40                       sub     ecx, -0C0000000h
.text:00430D42 8B 01                                   mov     eax, [ecx]
.text:00430D44 8B C8                                   mov     ecx, eax
.text:00430D46 83 E1 01                                and     ecx, 1
.text:00430D49 33 F6                                   xor     esi, esi
.text:00430D4B 0B CE                                   or      ecx, esi
.text:00430D4D 75 06                                   jnz     short loc_430D55
.text:00430D4F
.text:00430D4F                         loc_430D4F:                             ; CODE XREF: MmGetPhysicalAddress(x)+57j
.text:00430D4F 33 C0                                   xor     eax, eax
.text:00430D51 33 D2                                   xor     edx, edx
.text:00430D53 EB 1F                                   jmp     short loc_430D74
.text:00430D55                         ; ---------------------------------------------------------------------------
.text:00430D55
.text:00430D55                         loc_430D55:                             ; CODE XREF: MmGetPhysicalAddress(x)+7Bj
.text:00430D55 0F AC D0 0C                             shrd    eax, edx, 0Ch
.text:00430D59 C1 EA 0C                                shr     edx, 0Ch
.text:00430D5C 25 FF FF FF 03                          and     eax, 3FFFFFFh
.text:00430D61
.text:00430D61                         loc_430D61:                             ; CODE XREF: MmGetPhysicalAddress(x)+4Ej
.text:00430D61 33 C9                                   xor     ecx, ecx
.text:00430D63 0F A4 C1 0C                             shld    ecx, eax, 0Ch
.text:00430D67 C1 E0 0C                                shl     eax, 0Ch
.text:00430D6A 81 E7 FF 0F 00 00                       and     edi, 0FFFh
.text:00430D70 03 C7                                   add     eax, edi
.text:00430D72 8B D1                                   mov     edx, ecx
.text:00430D74
.text:00430D74                         loc_430D74:                             ; CODE XREF: MmGetPhysicalAddress(x)+81j
.text:00430D74 5F                                      pop     edi
.text:00430D75 5E                                      pop     esi
.text:00430D76 5B                                      pop     ebx
.text:00430D77 5D                                      pop     ebp
.text:00430D78 C2 04 00                                retn    4
.text:00430D78                         _MmGetPhysicalAddress@4 endp


  一看之下,有点晕。
  没关系,有前面清楚的PTE结构指引,这个函数就比较容易理解了。
  以下就是它的C++实现:
struct VirtAddr1
  {
  unsigned int PageOFF:12;
  unsigned int PageTable:20;
  };

struct VirtAddr2
  {
  unsigned int PageOFF:12;
  unsigned int PageTableIndex:9;
  unsigned int PageLargeIndex:11;
  };

struct VirtAddr3
  {
  unsigned int PageOFF:12;
  unsigned int PageTableIndex:9;
  unsigned int PageDirIndex:9;
  unsigned int PageDirPoint:2;
  };

MMPTE_HARDWARE* const PDE_BASE = (MMPTE_HARDWARE*)0xC0600000;  //页目录表
MMPTE_HARDWARE* const PTE_BASE = (MMPTE_HARDWARE*)0xC0000000;  //进程页表

PHYSICAL_ADDRESS GetPhysicalAddress(const unsigned long VirtualAddress)
  {
  const VirtAddr1* VA1 = (const VirtAddr1*)&VirtualAddress;
  const VirtAddr2* VA2 = (const VirtAddr2*)&VirtualAddress;
  MMPTE_HARDWARE PTE = *(PDE_BASE + VA2->PageLargeIndex);
  PHYSICAL_ADDRESS PA = {0,0};
  if(!(PTE.Valid))return PA;
  if(PTE.LargePage)
    {
    PTE.PageFrameNumber += VA2->PageTableIndex;
    }
  else
    {
    PTE = *(PTE_BASE + VA1->PageTable);
    if(!(PTE.Valid))return PA;
    }
  PTE.reserved1 = 0;
  PA.HighPart = PTE.HighPart;
  PA.LowPart = PTE.LowPart;
  ((VirtAddr1*)(&PA.LowPart))->PageOFF = VA1->PageOFF;
  return PA;
  }

  到这里应该可以结束了,不过我又想看看win2003是不是有啥不一样呢?
;Microsoft Windows Server 2003 Enterprise Edition Service Pack 2 [ver 5.2.3790]
;ntkrnlpa.exe
;MD5   : 20A327D41B0A5659AAFD0AA1AD98F433

.text:00439DE0                         ; __int64 __stdcall MmGetPhysicalAddress(void *BaseAddress)
.text:00439DE0                                         public _MmGetPhysicalAddress@4
.text:00439DE0                         _MmGetPhysicalAddress@4 proc near       ; CODE XREF: IoSetDumpRange(x,x,x,x)+1Ep
.text:00439DE0                                                                 ; IoSetDumpRange(x,x,x,x)+5Dp ...
.text:00439DE0
.text:00439DE0                         var_8           = dword ptr -8
.text:00439DE0                         BaseAddress     = dword ptr  8
.text:00439DE0
.text:00439DE0 8B FF                                   mov     edi, edi
.text:00439DE2 55                                      push    ebp
.text:00439DE3 8B EC                                   mov     ebp, esp
.text:00439DE5 51                                      push    ecx
.text:00439DE6 51                                      push    ecx
.text:00439DE7 53                                      push    ebx
.text:00439DE8 8B 5D 08                                mov     ebx, [ebp+BaseAddress]
.text:00439DEB 8B C3                                   mov     eax, ebx
.text:00439DED C1 E8 12                                shr     eax, 12h
.text:00439DF0 25 F8 3F 00 00                          and     eax, 3FF8h
.text:00439DF5 56                                      push    esi
.text:00439DF6 8D 88 00 00 60 C0                       lea     ecx, [eax+0C0600000h]
.text:00439DFC 8B 31                                   mov     esi, [ecx]
.text:00439DFE 8B 51 04                                mov     edx, [ecx+4]
.text:00439E01 57                                      push    edi
.text:00439E02 BF 81 00 00 00                          mov     edi, 81h
.text:00439E07 89 75 F8                                mov     [ebp+var_8], esi
.text:00439E0A 23 F7                                   and     esi, edi
.text:00439E0C 33 C0                                   xor     eax, eax
.text:00439E0E 3B F7                                   cmp     esi, edi
.text:00439E10 75 09                                   jnz     short loc_439E1B
.text:00439E12 85 C0                                   test    eax, eax
.text:00439E14 75 05                                   jnz     short loc_439E1B
.text:00439E16 8B 45 F8                                mov     eax, [ebp+var_8]
.text:00439E19 EB 23                                   jmp     short loc_439E3E
.text:00439E1B                         ; ---------------------------------------------------------------------------
.text:00439E1B
.text:00439E1B                         loc_439E1B:                             ; CODE XREF: MmGetPhysicalAddress(x)+30j
.text:00439E1B                                                                 ; MmGetPhysicalAddress(x)+34j
.text:00439E1B 8B 01                                   mov     eax, [ecx]
.text:00439E1D 8B 51 04                                mov     edx, [ecx+4]
.text:00439E20 8B C8                                   mov     ecx, eax
.text:00439E22 83 E1 01                                and     ecx, 1
.text:00439E25 33 F6                                   xor     esi, esi
.text:00439E27 0B CE                                   or      ecx, esi
.text:00439E29 74 4F                                   jz      short loc_439E7A
.text:00439E2B 8B C8                                   mov     ecx, eax
.text:00439E2D 81 E1 80 00 00 00                       and     ecx, 80h
.text:00439E33 56                                      push    esi
.text:00439E34 89 4D F8                                mov     [ebp+var_8], ecx
.text:00439E37 59                                      pop     ecx
.text:00439E38 74 1C                                   jz      short loc_439E56
.text:00439E3A 85 C9                                   test    ecx, ecx
.text:00439E3C 75 18                                   jnz     short loc_439E56
.text:00439E3E
.text:00439E3E                         loc_439E3E:                             ; CODE XREF: MmGetPhysicalAddress(x)+39j
.text:00439E3E 0F AC D0 0C                             shrd    eax, edx, 0Ch
.text:00439E42 8B CB                                   mov     ecx, ebx
.text:00439E44 C1 E9 0C                                shr     ecx, 0Ch
.text:00439E47 25 FF FF FF 03                          and     eax, 3FFFFFFh
.text:00439E4C 81 E1 FF 01 00 00                       and     ecx, 1FFh
.text:00439E52 03 C1                                   add     eax, ecx
.text:00439E54 EB 33                                   jmp     short loc_439E89
.text:00439E56                         ; ---------------------------------------------------------------------------
.text:00439E56
.text:00439E56                         loc_439E56:                             ; CODE XREF: MmGetPhysicalAddress(x)+58j
.text:00439E56                                                                 ; MmGetPhysicalAddress(x)+5Cj
.text:00439E56 8B CB                                   mov     ecx, ebx
.text:00439E58 C1 E9 09                                shr     ecx, 9
.text:00439E5B 81 E1 F8 FF 7F 00                       and     ecx, 7FFFF8h
.text:00439E61 8B 91 04 00 00 C0                       mov     edx, [ecx+0C0000004h]
.text:00439E67 81 E9 00 00 00 40                       sub     ecx, -0C0000000h
.text:00439E6D 8B 01                                   mov     eax, [ecx]
.text:00439E6F 8B C8                                   mov     ecx, eax
.text:00439E71 83 E1 01                                and     ecx, 1
.text:00439E74 33 F6                                   xor     esi, esi
.text:00439E76 0B CE                                   or      ecx, esi
.text:00439E78 75 06                                   jnz     short loc_439E80
.text:00439E7A
.text:00439E7A                         loc_439E7A:                             ; CODE XREF: MmGetPhysicalAddress(x)+49j
.text:00439E7A 33 C0                                   xor     eax, eax
.text:00439E7C 33 D2                                   xor     edx, edx
.text:00439E7E EB 1F                                   jmp     short loc_439E9F
.text:00439E80                         ; ---------------------------------------------------------------------------
.text:00439E80
.text:00439E80                         loc_439E80:                             ; CODE XREF: MmGetPhysicalAddress(x)+98j
.text:00439E80 0F AC D0 0C                             shrd    eax, edx, 0Ch
.text:00439E84 25 FF FF FF 03                          and     eax, 3FFFFFFh
.text:00439E89
.text:00439E89                         loc_439E89:                             ; CODE XREF: MmGetPhysicalAddress(x)+74j
.text:00439E89 33 C9                                   xor     ecx, ecx
.text:00439E8B 0F A4 C1 0C                             shld    ecx, eax, 0Ch
.text:00439E8F C1 EA 0C                                shr     edx, 0Ch
.text:00439E92 C1 E0 0C                                shl     eax, 0Ch
.text:00439E95 81 E3 FF 0F 00 00                       and     ebx, 0FFFh
.text:00439E9B 03 C3                                   add     eax, ebx
.text:00439E9D 8B D1                                   mov     edx, ecx
.text:00439E9F
.text:00439E9F                         loc_439E9F:                             ; CODE XREF: MmGetPhysicalAddress(x)+9Ej
.text:00439E9F 5F                                      pop     edi
.text:00439EA0 5E                                      pop     esi
.text:00439EA1 5B                                      pop     ebx
.text:00439EA2 C9                                      leave
.text:00439EA3 C2 04 00                                retn    4
.text:00439EA3                         _MmGetPhysicalAddress@4 endp

  粗看起来,是不一样了,但其实是一样的。不知道为什么多了一些不必要的判断与跳转。
  另外就是Vista的MiGetPhysicalAddress,计算过程都差不多,但多了更多的判断与跳转,还有一些无实际意义的计算,这个我很不明白是为什么。如果有牛人知道,请告知一下。
  代码有点长,不贴了。看过Vista的MiGetPhysicalAddress,其中显示,reserved0这个位被使用了,但只做了一个判断,没有实际意义。
  再者,XP与2003的MmGetVirtualForPhysical结果完全一样。而Vista多了一句“and     eax, 0FFFFFFFCh”,也就是取到PTE放弃最后两位。但是想来想去,好像也没什么实际意义。

  编译器开完全优化,编译出来的结果如下:
.text:000117B0                         ; _LARGE_INTEGER __stdcall GetPhysicalAddress(const unsigned int VirtualAddress)
.text:000117B0                         ?GetPhysicalAddress@@YG?AT_LARGE_INTEGER@@K@Z proc near
.text:000117B0                                                                 ; CODE XREF: Refresh(void *)+10p
.text:000117B0
.text:000117B0                         VirtualAddress  = dword ptr  4
.text:000117B0
.text:000117B0 53                                      push    ebx
.text:000117B1 8B 5C 24 08                             mov     ebx, [esp+4+VirtualAddress]
.text:000117B5 55                                      push    ebp
.text:000117B6 8B C3                                   mov     eax, ebx
.text:000117B8 C1 E8 15                                shr     eax, 15h
.text:000117BB 56                                      push    esi
.text:000117BC 8B 34 C5 00 00 60 C0                    mov     esi, ds:0C0600000h[eax*8]
.text:000117C3 8B CE                                   mov     ecx, esi
.text:000117C5 57                                      push    edi
.text:000117C6 8B 3C C5 04 00 60 C0                    mov     edi, ds:0C0600004h[eax*8]
.text:000117CD 83 E1 01                                and     ecx, 1
.text:000117D0 33 ED                                   xor     ebp, ebp
.text:000117D2 33 C0                                   xor     eax, eax
.text:000117D4 33 D2                                   xor     edx, edx
.text:000117D6 0B CD                                   or      ecx, ebp
.text:000117D8 74 61                                   jz      short loc_1183B
.text:000117DA 8B CE                                   mov     ecx, esi
.text:000117DC 81 E1 80 00 00 00                       and     ecx, 80h
.text:000117E2 0B CD                                   or      ecx, ebp
.text:000117E4 74 27                                   jz      short loc_1180D
.text:000117E6 8B C3                                   mov     eax, ebx
.text:000117E8 C1 E8 0C                                shr     eax, 0Ch
.text:000117EB 25 FF 01 00 00                          and     eax, 1FFh
.text:000117F0 B9 00 10 00 00                          mov     ecx, 1000h
.text:000117F5 F7 E1                                   mul     ecx
.text:000117F7 03 C6                                   add     eax, esi
.text:000117F9 13 D7                                   adc     edx, edi
.text:000117FB 33 C6                                   xor     eax, esi
.text:000117FD 33 D7                                   xor     edx, edi
.text:000117FF 25 00 F0 FF FF                          and     eax, 0FFFFF000h
.text:00011804 83 E2 3F                                and     edx, 3Fh
.text:00011807 33 F0                                   xor     esi, eax
.text:00011809 33 FA                                   xor     edi, edx
.text:0001180B EB 1E                                   jmp     short loc_1182B
.text:0001180D                         ; ---------------------------------------------------------------------------
.text:0001180D
.text:0001180D                         loc_1180D:                              ; CODE XREF: GetPhysicalAddress(ulong)+34j
.text:0001180D 8B CB                                   mov     ecx, ebx
.text:0001180F C1 E9 0C                                shr     ecx, 0Ch
.text:00011812 8B 34 CD 00 00 00 C0                    mov     esi, ds:0C0000000h[ecx*8]
.text:00011819 8B 3C CD 04 00 00 C0                    mov     edi, ds:0C0000004h[ecx*8]
.text:00011820 8B CE                                   mov     ecx, esi
.text:00011822 83 E1 01                                and     ecx, 1
.text:00011825 33 ED                                   xor     ebp, ebp
.text:00011827 0B CD                                   or      ecx, ebp
.text:00011829 74 10                                   jz      short loc_1183B
.text:0001182B
.text:0001182B                         loc_1182B:                              ; CODE XREF: GetPhysicalAddress(ulong)+5Bj
.text:0001182B 8B C6                                   mov     eax, esi
.text:0001182D 33 C3                                   xor     eax, ebx
.text:0001182F 83 E7 3F                                and     edi, 3Fh
.text:00011832 25 FF 0F 00 00                          and     eax, 0FFFh
.text:00011837 33 C6                                   xor     eax, esi
.text:00011839 8B D7                                   mov     edx, edi
.text:0001183B
.text:0001183B                         loc_1183B:                              ; CODE XREF: GetPhysicalAddress(ulong)+28j
.text:0001183B                                                                 ; GetPhysicalAddress(ulong)+79j
.text:0001183B 5F                                      pop     edi
.text:0001183C 5E                                      pop     esi
.text:0001183D 5D                                      pop     ebp
.text:0001183E 5B                                      pop     ebx
.text:0001183F C2 04 00                                retn    4
.text:0001183F                         ?GetPhysicalAddress@@YG?AT_LARGE_INTEGER@@K@Z endp

  看起来比系统的小了一些。
  怎么说呢,光看MmGetPhysicalAddress实在是晕。但由C实现出来,原理异常清晰。
  同时,解析过XP、2003、Vista以后,发现它们没有太大改动,那么,我们可以放心使用自己实现的GetPhysicalAddress喽。

  最后感谢xIkUg。
  胡乱写写,小小心得而已,欢迎拍砖。

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

收藏
点赞7
打赏
分享
最新回复 (5)
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jerrynpc 2010-11-19 07:31
2
0
楼主辛苦,努力学习ing...
雪    币: 695
活跃值: (25)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
patapon 4 2010-11-19 09:00
3
0
紧随jerry师傅的脚步进来支持,lz辛苦了~
雪    币: 7353
活跃值: (1956)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
寒冰心结 2010-11-19 09:40
4
0
好文章..学习了.

谢谢分享..
雪    币: 1265
活跃值: (3547)
能力值: ( LV9,RANK:220 )
在线值:
发帖
回帖
粉丝
黑手鱼 3 2019-11-13 17:59
5
0
正好看到这里,好文章
雪    币: 83
活跃值: (1037)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
killpy 2 2019-11-16 12:01
6
0
感谢分享
游客
登录 | 注册 方可回帖
返回