boy-hack / boy-hack

boy-hack
62 stars 2 forks source link

新的一年 pwn #35

Open boy-hack opened 2 years ago

boy-hack commented 2 years ago

保护机制

操作系统提供了许多安全机制来尝试降低或阻止缓冲区溢出攻击带来的安全风险,包括DEP、ASLR等。在编写漏洞利用代码的时候,需要特别注意目标进程是否开启了DEP(Linux下对应NX)、ASLR(Linux下对应PIE)等机制,例如存在DEP(NX)的话就不能直接执行栈上的数据,存在ASLR的话各个系统调用的地址就是随机化的。

栈溢出

栈溢出保护是编译器的特性,在堆栈中插入类似cookie的信息,若再次溢出覆盖的话会覆盖cookie,程序检测cookie是否一致来判断程序的进行。

gcc -fno-stack-protector -o test test.c  //禁用栈保护
gcc -fstack-protector -o test test.c  //启用堆栈保护,不过只为局部变量中含有 char 数组的函数插入保护代码
gcc -fstack-protector-all -o test test.c //启用堆栈保护,为所有函数插入保护代码

NX(DEP)

NX即No-eXecute(不可执行)的意思,NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。

gcc编译器默认开启了NX选项,如果需要关闭NX选项,可以给gcc编译器添加-z execstack参数。

gcc -z execstack -o test test.c

在Windows下,类似的概念为DEP(数据执行保护),在最新版的Visual Studio中默认开启了DEP编译选项。

PIE(ASLR)

一般情况下NX(Windows平台上称其为DEP)和地址空间分布随机化(ASLR)会同时工作。内存地址随机化机制(address space layout randomization),有以下三种情况

0 - 表示关闭进程地址空间随机化 1 - 表示将mmap的基址,stack和vdso页面随机化 2 - 表示在1的基础上增加栈(heap)的随机化

可以防范基于Ret2libc方式的针对DEP的攻击。ASLR和DEP配合使用,能有效阻止攻击者在堆栈上运行恶意代码。

查看设置:

root@kali430:~# cat /proc/sys/kernel/randomize_va_space
2
root@kali430:~# sysctl -a --pattern randomize
kernel.randomize_va_space = 2

RELRO

设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT(Global Offset Table)攻击。RELRO为” Partial RELRO”,说明我们对GOT表具有写权限。

总结

DEP(NX) 不允许执行栈上的数据 ASLR(PIE 随机化系统调用地址

RELRO 这个介绍有点长分为两种: 1.Partial RELRO GOT表仍然可写 2.Full RELRO GOT表只读

stack 栈溢出保护

boy-hack commented 2 years ago

利用手法

ret2shellcode

在堆栈上直接 执行shellcode,需要 栈溢出(carry) 和 运行执行堆栈(NX disable) 和 关闭地址随机化(方便定位函数) (PIE disable)

Rop

ROP的全称是Return Oriented Programming,简单来说就是修改返回地址,指向内存中的指令片段,也就是gadget,通过ret指令将程序的控制器拿在手里。最终组合一条rop攻击链。

Not found carry. and NX enable and PiE disable 情况 下 ,因为不能执行堆栈数据,通过对 返回地址的不断覆盖达到执行的目的 。但是寻找的地址

ret2libc

如何得到 system 函数的地址呢?system 函数属于 libc,而 libc.so 动态链接库中的函数之间相对偏移是固定的。 即使程序有 ASLR 保护,也只是针对于地址中间位进行随机,最低的 12 位并不会发生改变。而 libc 在 github 上有人进行收集,如下 https://github.com/niklasb/libc-database,可通过网站 https://libc.blukat.me/ 查询。

那么如何得到 libc 中的某个函数的地址呢?我们一般常用的方法是采用 got 表泄露,即输出某个函数对应的 got 表项的内容。当然,由于 libc 的延迟绑定机制,我们需要泄漏已经执行过的函数的地址。

信息泄漏的实现

在进行缓冲区溢出攻击的时候,如果我们将EIP跳转到write函数执行,并且在栈上安排和write相关的参数,就可以泄漏指定内存地址上的内容。比如我们可以将某一个函数的GOT条目的地址传给write函数,就可以泄漏这个函数在进程空间中的真实地址。

如果泄漏一个系统调用的内存地址,结合libc.so.6文件,我们就可以推算出其他系统调用(比如system)的地址。

格式化字符串

https://zh.wikipedia.org/wiki/%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2 通过控制 fmt内容,可以读取堆栈地址等信息,信息泄露,可任意写内存

参考

boy-hack commented 2 years ago

学习资料

linux kernal ctf