Skip to main content
gamedev.net
🔒 Locked

c stack calling conventions

Started by _walrus Sep 5, 2003 at 12:37 PM 7 replies 450+ views
Original Post
_walrus
_walrus
maybe a dumb question but i'm just curious if it is possible to push things onto the frame stack so that I wouldn't have to explicity pass them into a function. I want to do this because the number of parameters is unknown at compile time, but the function i have uses the ... type. For example this shows what i'm trying to achive: instead of: printf("%d %d %d", 1, 2, 3); i want to do: push(3) push(2) push(1) printf("%d %d %d");//assuming we push left to right onto stack that way i can pass in an arbitrary number of params at runtime: int array[] = getFromUser(); char * format = getFromUser(); for (c=arraySize-1; i>=0; i--) push(array[c]) printf(format); is this possible or is there any way to do something similar? thanks [edited by - _walrus on September 5, 2003 1:39:52 PM]
Fruny
Fruny
You could use vprintf.


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
GaulerTheGoat
GaulerTheGoat
That''s not a dumb question!

I think you should use vprintf...

Although, just for fun you could also do this:

typedef void (__stdcall *YouPushIPop) (int);
typedef void (__stdcall *IDontPop) (void);


void PopNothing (void)
{
}


void __stdcall PopAnInt (int)
{
}


void Funk (void)
{
YouPushIPop PushButDontPop = (YouPushIPop) PopNothing;
IDontPop PopButDontPush = (IDontPop) PopAnInt;

int *params = GetUsersParams ();
int num = GetNumParams ();
char *format = GetUsersFormat ();
int index;

for (index = num - 1; index; -- index)
PushButDontPop (params [index]);

printf (format);

for (index = 0; index < num; ++ index)
PopButDontPush ();
}
Now isn''t that purty! I think this will work. It can''t do anything worse than crash if it doesn''t.

I would stick with vprintf, though.
xf00f
xf00f
quote:

printf(format);


Errr - this is bad . Very bad. This is what causes format string vulnerabilities - never pass variables directly into printf or its ilk if the user has any control whatsoever over what''s getting handed to printf. Really you ought never do it anyway - bad habit. Use quotes, please.

As for the simplest solution to this problem... Look above. varargs are your friend - let the compiler do the hard work (and also help to keep your code architecture independant. And clean)
sBibi
sBibi
_walrus > google format string exploit
GaulerTheGoat
GaulerTheGoat
quote:
Original post by xf00f
quote:

printf(format);


Errr - this is bad . Very bad. This is what causes format string vulnerabilities - never pass variables directly into printf or its ilk if the user has any control whatsoever over what''s getting handed to printf. Really you ought never do it anyway - bad habit. Use quotes, please.

As for the simplest solution to this problem... Look above. varargs are your friend - let the compiler do the hard work (and also help to keep your code architecture independant. And clean)


You didn''t understand what he was asking. He wants to enter the format at run time - percent signs and all. So that''s why you must pass a non-static string to printf.

You could also use strtok:

void Funk (void)
{
char *format = GetUserFormat ();
char *token = strtok (format, "%");

printf (token);
token = strtok (NULL, "%");

while (token != NULL)
{
-- token;
*token = ''%'';
printf (token, NextUserParam ());
token = strtok (NULL, "%");
}
}
It''s still a little more work than vprintf.
sBibi
sBibi
GaulerTheGoat> "You didn't understand what he was asking. He wants to enter the format at run time - percent signs and all. So that's why you must pass a non-static string to printf."

you didn't seem to understand what xf00f said...
you should also google "format string exploit"

basically, as printf allows you to give it a pointer in witch it will write the number of bytes it has printed since the beginning of the string, you can mess up the stack and be able to write at the function calling point address, the adress that will be poped from the stack and injected into the program counter, by a the ret instruction. this way, you can make the program jump to some piece of code you've written...
usually, as it seems difficult to know where your code starting point will be exactly placed, it's often preceeded by nops (0x82 if I remember correctly?).
and this piece of code, for example on UN*X systems, can be a shell launcher code, similar to the C code: system("bash"); or whatever...
if the program you're exploiting is root, you end up with a rooted shell...
that might not be his case at all, but generally, giving the user the ability to feed printf with a format string he directly defines is a _very_ bad idea...
if he really wants to do it, why not, but anyone will be able to make his program crash, and even worse, make his program execute random code...

I can't explain very well format string exploits, I don't know the details, and I might have made some mistakes in my explanation above, if someone else could correct me or explain in more details, it'll be nice

but if you want plenty of information and examples:

http://www.google.com/search?q=format+string+exploit&ie=ISO-8859-1&hl=en&meta=



[edited by - sBibi on September 5, 2003 8:54:27 PM]
GaulerTheGoat
GaulerTheGoat
Well, that''s interesting sBibi.

I will have to read that format string exploit thing later. Off the top of head I''m not sure how much of an exploit that would be, though.

The hacker would have to inject his code into your program to begin with, in which case I don''t see why he couldn''t just run it without all the work of a format string exploit.

Also, if you use %n to overwrite some function''s return address down on the stack with the number of bytes written, you would have to write alot of bytes! Most of the user code is located at virtual addresses over 4 million.

Anyway, you had an interseting post. I will check out that link in a little bit.

BTW, I came here to edit my previous strtok post because I forgot about "%%" (and %n incidentally). I''m too lazy to do it now so I''ll just mention it.
xf00f
xf00f
The main point with using something like printf(myVar); is that it can lead to unexpected results, much like buffer overflows. Ofcourse, this *can* lead to exploitation, but most of the time it leads to crashes and buggy behaviour - even without worrying about somebody taking control of your instruction pointer, it''s really gonna annoy someone trying to use your program when they type anything with an % in it (which isn''t so very unlikely) and all hell breaks loose when printf() starts pulling random values off the stack, or worse - writing to it.

Best off using vprintf() as already advised by the (seemingly) all knowing fruny

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.