21.03.2013 Views

Problem - Kevin Tafuro

Problem - Kevin Tafuro

Problem - Kevin Tafuro

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Discussion<br />

Both C and C++ allow the definition of functions that take a variable number of<br />

arguments. The header file stdarg.h defines three macros, * va_start( ), va_arg( ), and<br />

va_end( ), that can be used to obtain the arguments in the variable argument list.<br />

First, you must call the macro va_start( ), possibly followed by an arbitrary number<br />

of calls to va_arg( ), and finally, you must call va_end( ).<br />

A function that takes a variable number of arguments does not know the number of<br />

arguments present or the type of each argument in the argument list; the function<br />

must therefore have some other way of knowing how many arguments should be<br />

present, so as to not make too many calls to va_arg( ). In fact, the ANSI C standard<br />

does not define the behavior that occurs should va_arg( ) be called too many times.<br />

Often, the behavior is to keep returning data from the stack until a hardware exception<br />

occurs, which will crash your program, of course.<br />

Calling va_arg( ) too many times can have disastrous effects. In Recipe 13.2, we discussed<br />

format string attacks against the printf family of functions. One particularly<br />

dangerous format specifier is %n, which causes the number of bytes written so far to<br />

the output destination (whether it’s a string via sprintf( ), or a file via fprintf( )) to<br />

be written into the next argument in the variable argument list. For example:<br />

int x;<br />

printf("hello, world%n\n", &x);<br />

In this example code, the integer value 12 would be written into the variable x. Imagine<br />

what would happen if no argument were present after the format string, and the<br />

return address were the next thing on the stack: an attacker could overwrite the<br />

return address, possibly resulting in arbitrary code execution.<br />

There is no easy way to protect the printf family of functions against this type of<br />

attack, except to properly sanitize input that could eventually make its way down<br />

into a call to one of the printf family of functions. However, it is possible to protect<br />

variable argument functions that you write against possible mistakes that would<br />

leave the code vulnerable to such an attack.<br />

The first solution we’ve presented is compiler- and processor-specific because it<br />

makes use of a GCC-specific built-in function, __builtin_frame_address( ), and of<br />

knowledge of how the stack is organized on an x86 based processor to determine<br />

where the arguments pushed by the caller end. With a small amount of effort, this<br />

* The ANSI C standard dictates that va_start( ), va_arg( ), and va_end( ) must be macros. However, it does<br />

not place any requirements on their expansion. Some implementations may simply expand the macros to<br />

built-in function calls (GCC does this). Others may be expressions performing pointer arithmetic (Microsoft<br />

Visual C++ does this). Others still may provide some completely different kind of implementation for the<br />

macros.<br />

Using Variable Arguments Properly | 711<br />

This is the Title of the Book, eMatter Edition<br />

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!