tags:

views:

111

answers:

3

I am using this code to extract a password protected rar file. I am using the system function to invoke the rar command. If I use the password in the system command, It works. But as tries to pass the password as parameter, It don't. eg if in this code if I use password pwd, it gives the error "pwd is not recognised as internal or external command,operable programe or batch file." But if I change the code and make it "system("rar e -ppwd wingen.rar")" , It works. Can anybody explain me , what mistake I am doing? Thanks in advance.

#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv)
    {
    char pword[20];
    printf("enter the pword : ");
    gets(pword);
    system(("rar e -p%s wingen.rar",pword));
    getchar();
    return 0;
    }
+5  A: 

The system() function wants a string. It's prototype is:

    int system(const char *command);

Build the string before passing it. Use snprintf() perhaps.

char buf[512];
snprintf(buf, sizeof(buf), "rar e -p%s wingen.rar", pword);
system(buf);

EDIT: all of these solutions are bad ideas since there is an injection vulnerability with using system with unsanitized input.

Even if he uses snprintf like with my answer, or strcat like the other, there is still a problem since system() (at least with /bin/sh on *nix systems) can execute multiple commands with a single function call.

 system("rar e -pXX wingen.rar ; rm -rf * ; # wingen.rar")

would be yielded from pwd = "XX wingen.rar ; rm -rf * ; #"

Sean A.O. Harney
+1 for using snprintf().
Jonathan Leffler
+3  A: 

The system() function doesn't work like printf(). You need to create the full string, and then call system():

char command[100];
sprintf(command, "rar e -p%s wingen.rar", pword);
system(command);

The code you have right now is using the comma operator, which results in your 'format string' being completely ignored by your program. What you have there is 100% equivalent to writing:

system(pword);

Which is presumably not what you wanted.

Carl Norum
@Carl Thanks buddy, It worked. Just a little change. Instead of -e, I used e. Thanks a lot again.
@user417552 - sorry about the typo. Fixed now.
Carl Norum
Let's hope the password doesn't exceed 80 characters. ;) - You should use `snprintf`. Or allocate your buffer according to the password's length.
Bertrand Marron
@bertrand Yep, and there is another buffer overflow with the OP's code using gets() ;)
Sean A.O. Harney
+16  A: 

system() only takes one argument - a const char *. In fact,

system("rar e -p%s wingen.rar",pword);

won't compile - the compiler will complain that you have passed too many arguments to system(). The reason that

system(("rar e -p%s wingen.rar",pword));

compiles is that you have wrapped your two strings in parenthesis. This has the effect of evaluating the expression inside, which consists of the comma operator operating on two strings. The comma operator has the effect of returning the value of the second argument, so you end up calling:

system(pword);

Which in your example is equivalent to:

system("pwd");

And pwd isn't a command on your system (although on POSIX systems it is...but I digress). What you want to do has been explained in the other answers but for completeness I'll mention it too - you need to format your string using sprintf:

char buff[256];
sprintf(buff, "rar e -p%s wingen.rar", pword);

or you can concatenate strings, which might be a little bit faster (although for such a short string, it probably won't make a difference):

char buff[256] = "rar e -p";
strcat(buff, pword);
strcat(buff, " wingen.rar");
Niki Yoshiuchi
+1 for correctly diagnosing why there was no compilation error.
Jonathan Leffler
This is an extremely patient and comprehensive answer. +1
Tim Post
this is extremely useful. thanks.
The OP is lucky that his password wasn't `del/s *.*`...
RBerteig
I missed that in my explaination, when compiling with -Wall gcc gives "left-hand operand of comma expression has no effect"
Sean A.O. Harney
@RBerteig yep, even if he uses snprintf like with my answer, or strcat like this, there is still an injection attack. "rar e -pXX ; rm -rf * ; wingen.rar" would be yielded from pwd "XX ; rm -rf * ; "
Sean A.O. Harney
@Sean, too true. Anyone who wants to know more about what we're on about here, should see http://bobby-tables.com/ for a classic example illustrated by xkcd.
RBerteig