线下比赛多为AWD,涉及到逆向的知识点很少。为了在线下不坐牢指打开电脑无所事事疯狂偷吃茶歇区零食 ,来记录自己学习pwn的入门知识
保护
Canary
是一种栈溢出保护机制。在函数返回前会检查一个生成的随机数,如果随机数被垃圾数据覆盖或者被篡改,就会报错。
NX
类似于Windows下的DEP,将内存页改为不可执行。将程序的.text
段标记为可执行,而.data、.bss、.rodata
以及堆栈区域均标记为不可执行。所以没有办法使用ret2shellcode
的方法进行漏洞利用。
PIE
地址随机化保护。
漏洞利用方式
ret2text
在我的理解中,这就是最简单的漏洞利用方式。
通过栈溢出修改函数的返回地址,也存在系统调用函数使用,同时系统调用的命令也正好是/bin/sh
,获取到shell。
ret2shellcode
当没有系统函数在程序中,我们只能自己写进去一个shellcode
去执行。
通过在栈溢出的垃圾数据中加入shellcode
,修改返回地址到shellcode的地址运行即可
ret2syscall
当程序加入NX
保护,同时没有系统调用函数来使用,就需要这种漏洞利用手法,通过触发0x80
号中断进行系统调用。
思路如下:
- 将系统调用的编号存入EAX。例如要调用
exec
,对应的编号就是0xb
。 - 将函数的其他参数存入寄存器。例如调用
exec
, eax=0xb, ebx=/bin/sh 的地址, ecx=0, edx=0 - 触发0x80中断
如何向寄存器中填入数据?需要利用gadgets
(小片段)来实现
所谓的gadgets
就是以 ret 结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,方便控制程序的执行流程。
例如:
1 | pop eax ; ret |
这段代码的作用就是将栈顶的数据弹出给eax,然后再将栈顶的数据作为返回地址返回。
我们只需要pop出栈顶的数据到对应寄存器中,接着在新的栈顶填入要ret的地址即可,就可以做到这种攻击手法。
ret2libc
当程序中既没有调用system
函数也没有/bin/sh
字符,同时程序开启NX保护,这个时候就可以考虑使用libc当中的函数,其中封装了常用的函数,比如常用的printf,get函数。在每个libc库中的函数的偏移都是相对的,只要获取到libc的基地址,再加上函数的偏移值,就可以调用该函数。libc库中也存在字符串/bin/sh
。需要注意的是不同版本的libc对应的函数偏移与不同。
如何获取libc基地址?
首先通过延迟绑定机制获取到got
表中的函数真实地址,通过查找对应libc中函数的偏移,使用真实地址减去函数偏移即可获得libc基地址。
之后通过基地址加上当前版本的函数偏移即可实现调用。